От сервера к тулкиту

Здесь собрана незаконченная серия заметок из ЖЖ, где делалась попытка пройтись по истории Zope, туманно порассуждать и проанализировать, как из сервера приложений родился тулкит и целый пул технологий. Писалось в 2009 году.

Введение в проблему

Вся эта канитель с переливанием кода из пустого в порожнее в Zope-коммунити приводит в крайнее уныние. Нет, я понимаю для чего нужен Zope Toolkit (ZTK), и движение в эту сторону приветствую, но тем не менее...

Я считаю себя опытным Zope-разработчиком, создавать приложения на Zope3 для меня так же естесственно, как дышать без противогаза - удобно, комфортно и быстро. А работая с другими тулкитами и языками, лишь убеждаюсь в том, что Zope ушел так далеко вперед, что не догнать. В данный момент есть возможность и необходимость определиться с используемыми решениями для нового проекта, плюс определиться со стратегией поддержкой старого. Итак, после полугодового перерыва смотрю что там творится с ZTK.

Дабы разобраться, открываю бездонный gmail, фильтрую почту по Zope-dev рассылке и просматриваю ее в обратном хронологическом порядке, пытаясь выудить полезную информацию.

Все хорошо, все перфекционно, за исключением того момента что это - переливание из пустого в порожнее. Т.е. огорчает то, что столько движений и дискуссий в контексте отсутствия чего-либо нового.

Ну, я надеялся, что уже кто-то собрал KGS для Zope3 Application Server на основе ZTK 1.0. Ан нет (Стефан Рихтер как раз сейчас пытается собрать). Запутались мужики в зависимостях.

Свой собственный сервер приложений (в основном похожий на Zope3 Application Server, но без ZMI, а также ряд других отличий) я соберу сам и без этого, но мне нужны z3c-пакеты. А у них, как известно, прописаны зависимости. И здесь, еще недавно, все было плохо, так как зависимости закинуты не на ZTK. На первый взгляд, улудшений пока что-то не видно. И это окончательно приводит в уныние.

В целом же, попробую сформулировать тезис:

Более совершенные техники проигрывают по популярности и продуктивности на первых этапах, но имеют больше шансов в перспективе. Причина в том, что для выживания на длительных сроках значимость социальных факторов уменьшается, и большее значение приобретает техническое совершенство.

Т.е. прогноз все равно оптимистичный.

Предистория: сервер приложений

На рубеже столетий появился сервер приложений Zope, написанный на Python и C, суть которого сводилась к использованию собственной объектной базы данных, позволяющей максимально прозрачно манипулировать персистентными объектами на Python. Эта база данных (ZODB) играла несколько ключевых ролей:

  1. Траверс объектов, сохраненных в ней древовидно, отображается в схему построения URL'ов.

  2. Доступ к объектам удобно настраивается по ветвям дерева, и это оказалось удобно и надежно настолько, что Zope стал особо известен своей повышенной защищенностью. Собственно, я даже не берусь предположить, есть ли кто-то или что-то, что имеет более развитую систему безопасности. В общем, это вопрос для обсуждения.

  3. Обеспечение персистентности объектов, как уже сказано, максимально прозрачно. Достаточно наследовать свой класс от persistent.Persistent.

  4. Продолжая последовательную линию объектно-ориентированной идеологии, некоторые ее паттерны, такие как наследование, были перенесены на доступ и манипулирование персистентными объектами в соответствии с их расположением в дереве базы данных. Так появился паттерн Acquisition (заимствование свойств объектов друг от друга в соответствии со схемой их взаимного расположения в дереве), который быстро проник везде где только можно, и фактически, вся логика сервера приложений Zope была пронизана идеями Acquisition.

  5. Простой API для копирования и перемещения объектов внутри дерева базы данных. Это отразилось также и на том, что во всех ZMI (варианты административного web-интерфейса ) доступен т.н. сontents-вид, возволяющий играючи перемещать объекты по базе данных, кликнув мышкой.

    Учитывая что на расположение объектов может быть завязана какая-то бизнес-логика, эта возможность достаточно интересна. Вполне вероятно создание каких-то фантастически привлекательных вещей, связанных с такой возможностью. Создается впечатление, что это что-то, такое привлекательное, ожидали создатели сервера приложений в самом начале, однако ничего по-настоящему ценного в этом направлении не было сделано (это по моему мнению. Если есть что добавить, пожалуйста прокомментируйте этот момент.)

Может быть, кому-то из нас еще придет в голову некая блестящая идея использовать возможности contents-вида так, что это действительно принесет пользу.
  1. Еще ряд возможностей (очень буду рад если кто-нибудь поправит этот список. Речь идет об идеях, возникших в рамках ZODB-программирования, и повлиявших на сам Zope.)

Наибольшее влияние на общую картину программирования в рамках Zope в первые годы оказали 2 типа персистентных объектов. Естесственно, что их идеи были проработаны с разных сторон и в разных вариантах. Это следующие типы объектов:

  1. Персистентные объекты, реализующие контейнерные типы данных, с интенсиональным и экстенсиональным соответствием общему шаблону хранения данных в виде дерева.
  2. Персистентные объекты, реализующие контейнерные типы данных для хранения исполняемого скриптового кода.

Первый тип означает что для доступа к содержимому контейнера, как правило, действительны положения 1,2,4 (т.е. траверс через web, настройка доступов, заимствование). Эти общие положения дополняются кастомным функционалом, разработанным для конкретного класса-контейнера.

Второй тип объектов привел к феномену TTW-программирования (through-the-web programming), когда некий скриптовый код вводится в форму, через браузер. Основные известные такие типы объектов следующие: Python-скрипт, Perl-скрипт, DTML-страница, ZPT-страница. Вероятно, существуют кем-то и где-то созданные и другие подобные типы, но я о них не знаю. Данный тип объектов стал хорошим подспорьем в популяризации сервера приложений, так как позволяет достаточно быстро начать использовать сервер для создания реальных сложных приложений. И тот самый TTW-код, как ни крути, оказывается проще и чище, чем типичное PHP-приложение или Perl-овские cgi-скрипты.

Предистория: TTW-программирование

Сами по себе, идея хранения кода в базе данных и идея персистентных объектов - не были новыми. Своими корнями они уходят в различные реализации Smalltalk и Lisp. При этом, в Smalltalk идея персистентного кода проработана на порядок лучше - здесь и нативность для Smalltalk, и изначально присутсвующий контроль версий. К TTW-программированию персистентных объектов также можно провести аналогию от программирования "мышой" в Squeak Smalltalk. Персистентность же в Smalltalk, стандартными средствами, обеспечивается сохранением т.н. образа. Т.е. речь идет не о базе данных как об отдельной сущности, а об имадж-ориентированном стиле программирования.

С другой стороны, различные реализации Lisp, как правило, имеют отличную поддержку имадж-ориентированного стиля работы. Но при этом, он легко сочетается с обычным, source-ориентированным стилем работы. Подключение REPL на порт и интерактивная работа с образом программы, опять же, приводит к аналогии с редактированием персистентных скриптов в ZODB (в целом, я считаю, что различные популярные Lisp-системы лучше других ориентированы на поддержку процесса разработки, но, как типичный лиспер, не умею объяснять эти преимущества. Да и нужно ли ?...).

Данные аналогии я привел для того, чтобы объяснить следующую точку зрения:

программирование персистентных объектов с хранящимся внутри них исполняемым кодом, само по себе - не такая уж плохая идея, как об этом принято говорить в современном Zope-комьюнити. Идеи, стоящие за ним, в Lisp и Smalltalk зародились раньше, гораздо лучше проработаны, используются, и сами по себе, не влекут за собой каких-то принципиальных огрешностей в архитектуре.

Тем не менее, Python - это не Smalltalk и, тем более, не Lisp. Несмотря на потрясающий динамизм Пайтона, изначально он для таких вещей не проектировался. И разработчикам Zope, по видимому, не удалось изобрести однозначно безупречной методики TTW-программирования, хотя это не значит что его (этого способа) нету совсем.

Поэтому, получив достаточно большой опыт как в разработке объектов, подобных хранимым Python-скриптам или DTML-шаблонам, так и в их использовании при создании заказных проектов, Zope-сообщество постепенно отходило от использования персистентного кода.

Первой, и решающей, причиной была невозможность использования систем контроля версий. Нет, конечно, возможность отката транзакций в базе данных есть (пока не сожмешь базу). Но это - не система контроля версий (VCS). А ведь для любого программиста, VCS, наряду с редактором, компилятором и системой сборки проектов - самые важные рабочие инструменты (последний, правда, на деле - как бог положит).

По поводу редактора - то же самое. Про external editor говорить не надо - знаю. Не удобно. А "удобно" - это главный критерий выбора текстовых редакторов.

Нужно отметить, что никаких принципиальных проблем с разработкой поддержки контроля версий для персистентных скриптов быть не должно, просто этого никто не делал. Также создавались продукты вроде ZCVSFolder?. И сейчас уже есть как минимум один фреймворк для построения ZODB-VCS-ок.

Наряду с VCS и редактором, в TTW-программировании существует третья проблема: перенос кода из одной базы данных в другую. Сам по себе, инструмент для импорта-экспорта в zope2 тщательно проработан. Но никакой речи о полной и надежной совместимости между разными инстансами сервера не может быть, если используются разные версии того кода, который, собственно, в файловой системе.

Взгляд в будущее: перспективы TTW

Продолжим разговор о TTW. Причина такого внимания к данному вопросу очевидна: то, что мы подразумеваем под расплавчатым понятием "Zope" - когда-то начиналось с виртуальной машины для TTW-программирования, написанной на Пайтоне. Эта самая виртуальная машина и называлась "Zope".

К моменту написания этой заметки (осень 2009 года), классическое TTW-программирование на основе zope2 (DTML+Python-скрипты), практикуется, и в некоторых местах - активно. Поэтому говорить, что оно совсем умерло - нельзя. Zope2 - современный потомок того первоначального сервера приложений - являет собой единый пакет, основанный на библиотеках ZTK. Надежный как скала (продукту, как никак, 10 лет, и все это время он активно поддерживался), быстрый, устойчивости его API позавидуют многие, критически безопасный и т.д. И он позволяет TTW-программирование.

В рамках сервера приложений и вэб-фреймворка Zope3 в настоящее время также существует ряд направлений в TTW,в основном связанные с редактированием всевозможных шаблонов для страничек либо редактированием таблиц стилей.

В частности, это направление тщательно прорабатывется в CMS z3ext, и направлено на обеспечение возможности полной визуальной кастомизации сайта через браузер. Т.е., подключив продукты для TTW, в этой CMS можно полностью сделать дизайн, лишь тыкая мышкой в браузере. Для чего это нужно - в принципе понятно: a) хакерский зуд разработчика этой CMS (это хорошо понятно, т.к. у самого автора статьи т.н. хакерский зуд и не проходит никогда), b) популяризация (определенный процент технических пользователей готов пользоваться этим), c) возможность настраивать дизайн в рамках отдельного контейнера - пользовательского места, что бывает нужно для крупных порталов.

Автор, опять же, делал продукты для редактирования шаблонов пару раз, с чем пришло понимание, что может быть, придется делать еще не раз. :) Один - предназначен для того, чтобы быстро, с минимумом телодвижений включить в сайт возможность редактирования любых его мест с использованием визуального редактора и с возможностью сохранять изображения. При этом новые такие места вводятся мгновенно: 1 инструкция в zcml и 1 инструкция в TAL. А также с возможностью в любой момент, быстро и безболезненно отказаться от использования этого продукта. Другой продукт - позволяет работать с динамическими шаблонами, т.е. с использованием переменных. Оба продукта создавались для текущих нужд проектов, а не "про запас".

В рамках сервера приложений Zope3 для подобных целей также есть возможность использовать пакет ZPTPage?, но это - неудачный вариант.

Т.е. понятно, что у TTW своя ниша есть, как минимум на уровне шаблонов страничек. Что же насчет более сложной бизнес-логики?

Будущее у TTW-подхода для программирования бизнес-логики в рамках Zope как сервера приложений с ZODB на борту - вполне может быть. И зависит оно больше не от спроса, а от предложения. Т.е. сначала нужно это создать, притом удачно. Попробуем пофантазировать:

  1. Специальный контейнер, позволяющий внутри него TTW-программировать что-нибудь. Зона влияния строго ограничена данным контейнером. Идеи, парадигмы, паттерны и подходы могут быть самые различные - здесь большой простор для креатива. Быстрый в изучении. Устанавливаться и работать может везде - в Zope2, Zope3, Plone, Grok, z3ext - в любой из ZODB-ориентированных ипостасей Zope. Тут же страничка помощи, причем полная. Тут же форма для экспорта/импорта/бэкапа в текстовом формате. Строгое отделение кода от данных: это даст возможность иметь более гибкую систему импортов. Тут же контроль версий - с показом diff'ов и т.д. Обязательно система 2-х одновременных версий, т.е. все изменения работают только в черновик до тех пор, пока не будут "опубликованы". Можно еще добавить возможность включать отдельный порт, и лазить в него Emacs'ом. Тут же IDE с автоформатированием, на JavaScript?. Да много чего можно придумать. Хорошо придумаешь - будут пользоваться люди. Всем будет хорошо :) Ну где такое можно еще сделать? Только в Zope, т.к. нужен траверс внутри контейнера.

Даешь админу сайта и (если нету ZMI) обеспечиваешь возможность добавлять и удалять. Многие администраторы крупных порталов вполне готовы что-нибудь "слегка" напрограммировать ло кально в некоем контейнере. Тем более что этот контейнер можно добавить в любой момент, можно убрать. Поломать - все равно ничего не поломаешь, т.к. зона действия ограничена. Пл онщики (а их уйма по всему миру), особенно Plone-интеграторы и администраторы - если будет удачная парадигма - оторвут с руками.

А можно положить в большой портал и пусть себе все прохожие регистрируются и программируют.

(Надо отметить, что продукт подобного класса скорее будет создаваться в ближайшее время. Но - с другими целями, т.к. автор эксперементирует с узкоспецфической парадигмой программирования, и для выяснения возможностей этой технологии используется все, что под руку попадется - от комбинаторов карандашом в блокноте до этого ужасного хаскелля. Вероятно, будет вариант и с Zope3+TTW. Там посмотрим, во что выльется, и с чем можно будет сьесть.)

  1. Полезная вариация предыдущей идеи: сделать нечто вроде образовательного приложения для школьников, визуальное программирование как в Squeak Smalltalk, но - через вэб.
  2. Скриптование в бизнес-приложениях (естесственно, с импортами/экспортами в тесктовый формат, контролем версий и прочими необходимыми вещами. Иначе - какое же оно будет "бизнес".). Заодно вспомнить про Naudoc, как пример того, как делать не надо :)

Вообще сама суть различного рода скриптования в сложных вэб-приложениях, при удачной реализации - это по-прежнему область для TTW. Назовем это "локальным скриптованием", чтобы отличать его от создания проекта в целом.

Таким образом, мы постарались рассмотреть феномен TTW как можно ближе. Идея заключается в том, что в ZODB-ориентированной модели серверов приложений Zope TTW-идеи имеют право на существование в том или ином виде по той простой причине, что не все пользователи Zope - разработчики, мыслящие категориями интерфейсов, адаптеров и утилит. Zope - платформа черезвычайно богатая, и может и должна говорить Welcome! гораздо большему количеству людей, чем сейчас, и гораздо более разнообразному в плане технической подготовки.

История: CMF и все-все-все

Persistence means always having to say you're sorry. (Tres Seaver, CMF creator)

Так же как идея оголтелой ООП-изации не всегда приводит к чему-то хорошему, так и Acquisition (заимствование) не стал серебряной пулей. Теоретически, он достаточно интересен и позволяет делать много чего, а практичеки - способен создать путаницу настолько, что программист перестает контролировать поведение своего кода.

Тем не менее, Zope Corporation и собравшееся вокруг него сообщество независимых разработчиков, оказались на редкость продуктивными: продукты для Zope появлялись как на дрожжах, что делало его все более привлекательным конструктором для сборки всего чего угодно, прежде всего - сложных динамических публичных сайтов и бизнес-приложений для использования во внутренних сетях корпораций. В частности, автор сам впервые столкнулся с Zope, именно создавая интранет бизнес-приложение (справедливости ради нужно добавить, что хронологически это было гораздо позже. И не то чтобы автора привлекла модель разработки... но тщательно проработанная система безопасности сильно повлияла на выбор. Это приложение работает до сих пор.)

Стоит отметить и активность в русскоязычном сегменте: термины Python и Zope в начале 0-х годов были в России почти синонимами. Также важной вехой стало появление обсуждаемого сервера в репозитариях ALT-Linux - а эта компания, чтобы плохого про нее не говорили, на тот момент была ведущей в стране организацией, занимающейся Open Source. Учитывая немалое количество вовлеченных в поддержку и использование данного дистрибутива инженеров, наличие Zope в репозитариях ALT-Linux - наверное - способствовало его распостранению. В русскоязычном сегменте также был создан ряд крупных продуктов и каркасов, работающих внутри Zope - многие из них верой и правдой служат своим заказчикам и ныне. :)

В принципе, существующая в первые годы модель разработки под Zope уже позволяла создавать переиспользуемые модули, поэтому, в деятельности Zope Corporation и сообщества разработчиков явно прослеживается ориентация на создание продуктов - это несмотря на то, что создание продуктов само по себе не приносит прибыли: прибыль приносит выполнение конечных проектов.

Вместе с многими другими продуктами был создан PTK (Portal Toolkit) и затем, как его дальнейшее развитие, CMF (Content Management Framework, т.е. каркас для проектирования систем управления контентом). CMF представляет собой целый комплекс программ и особо выделяется на фоне других продуктов, представляя собой отдельную веху в развитии Zope. Влияние CMF на все дальнейшую историю Zope трудно переоценить. CMF ввел ряд ключевых шаблонов и идей, повлиявших на создание других проектов под Zope (в том числе и новейшего времени):

  1. Первая реализация идеи skin'ов (шкур).
  2. Написание заказного кода не только TTW, но и (и прежде всего) в файловой системе.
  3. Идея "портала", когда существуют пользователи - члены портала, каждый из которых имеет свою "домашнюю" область, и возможно, может с ней что-то делать.
  4. Паттерн документооборота, когда пользователь создает документ, но не публикует (т.к. не имеет прав на это), а лишь передает администратору на обозрение. Администратор, в свою очередь может разрешить публикацию, отправить на доработку и т.д.
  5. Дополнительный функционал.

Перечисленные идеи и функционал имеют важное значение и далеко идущие последствия, и в следующих статьях мы еще вернемся к ним.

CMF оказался, по всей видимости, мощным и удачным для своего времени решением. В индустрии вэб-разработки существует устойчивая тенденция к написанию всевозможных CMS'ок (Content Management System) - т.е. тиражируемых сайтов с возможностью их настройки до неузнаваемости (т.н. "кастомизации"). Также полноценная CMS должна позволять написание новых подключаемых модулей, реализующих заказную бизнес-логику - и - обязательно - легкую и прозрачную интеграцию оных в существующую систему. Таким образом, написание полнофункциональной CMS - задача вполне себе емкая.

CMF же предоставил почти весь необходимый функционал. Так, на его основе вырос пул CMS'ок, среди которых в почти дарвиновской борьбе за выживание выделился и вырос знаменитый Plone. Стоит ли напоминать, что в самом начале Plone практически не содержал собственного кода, а был лишь настроенной CMF. И тем не менее, Plone быстро вошел (и до сих пор входит) в тройку самых лучших CMS в мире. Да еще и лидирует внутри этой тройки по качеству.

Plone 2.*

I knew that at the end of my career, I would look back on years of building walls to divide people, and feel I had spent my life making the world a worse place. (Richard Stallman)

Фановый сексапильный дефолтный дизайн Plone, "луковица" слоев качественно проработанных стилей, процедура установки и настройки продуктов, кастомизация через ZMI, безопасность и внимательное отношение разработчиков к миграции между версиями сыграли свою роль: все новые и новые заказчики "подсаживались" на эту CMS. За спросом рождалось предложение: все новые компании и независимые разработчики вступали в Plone-сообщество.

Так в полную силу заработала машина Open Source: члены сообщества разрабатывают продукты, с самого начала размещая их в открытых репозитариях под свободной лицензией, нередко разработка принимает колаборативный характер, когда в нее включаются другие члены сообщества. Продукты массово тестируются в "боевых" условиях и применяются в проектах, принося прибыль всем участникам сообщества

Подобная идеалистическая картина продуктивной инженерной демократии - несбываемая мечта многих открытых проектов. Лишь незначительному проценту удается достичь такого. Plone - удалось. Таким образом, Plone-сообщество само стало образчиком и воплощением Open Source.

Внимание на этом моменте заострено не случайно: сам факт наличия столь развитого сообщества и сложившейся схемы взаимодействия внутри него сыграл одну из решающих ролей в дальнейшем развитии всего Zope.

Сложившаяся схема работы Plone-интеграторов над отдельным проектом подразумевет максимально короткий латентный период при сдаче проекта заказчику: с самого начала он может видеть свой сайт в дефолтном виде. Устанавливаются несколько продуктов - и сайт практически готов: остается лишь изменить верстку. Такова идеальная картина. В реальности же, даже при наличии, казалось бы, всего необходимого функционала в свободных продуктах, часто требуется программирование, в том числе и разработка сугубо специфических продуктов. И здесь важной вехой стала система Archetypes, ставшая вторым (хронологически, после средств CMF) чрезвычайно широко используемым каркасом для разработки типов контента.

Понятие "фан" играет настолько большое значение в Plone (как, впрочем, и во многих других открытых проектах), что сообщество начинает позиционировать проект, изначально CMS, как вэб-фреймворк, возлагая на него те функции и надежды, для которых он не приспособлен. Да, собственно, иного выбора у него и нет - иного архитектура не позволяет.

Кроме того, не будем забывать, что корни Plone уходят в CMF. Перечисленные в прошлой статье особенности CMF повлияли на тип сайтов, создаваемых с помощью Plone. Фактически, понятие "CMS" в устах Plone означает "возможность: а) совместной работы над статьей несколькими пользователями; б) наличия домашней папки у каждого пользователя; в) определения пользователем прав доступа к своим документам".

Не следует думать, что данная модель - единственная возможная модель для CMS. Альтернативные модели существуют, и читатель сам может придумать несколько штук в ходе беглого мозгового штурма.

На этом цикл заметок был завершен, и логического продолжения нет (надоело писать)