Громоздкий ли ZTK?

Часто можно услышать подобную характеристику применительно к Zope. Давайте посмотрим, подумаем и, самое главное, посчитаем, так ли это в действительности, или это иллюзия.

Предмет обсуждения

Zope

Как указано в определениях ZTK, спектр значений этого слова широк. Сузим его, взяв конкретный пример: набор ZTK пакетов, собранный для написания приложения, аналогичный набору, используемому в генерируемом из шаблона стандартном проекте BlueBream?. Практически он аналогичен серверу приложения Zope3. Пакеты были развернуты не с помощью zc.buildout, а с помощью pip и virtualenv [1]. Приводится requirements-файл для этой сборки

Понятие громоздкости

Вероятно, здесь больше ощущения, чем объективные определения. Тем не менее, что можно подразумевать под громоздкостью?

  • объем кода самого используемого инструмента (zope) - большой
  • большое количество сущностей, паттернов, в которых легко запутаться. Много идей, которые необходимо знать, чтобы использовать инструмент эффективно (или хотя бы как-нибудь)
  • абстракции в коде самого инструмента, делающие его кострукции черезчур замысловатыми логически длинными. Инструмент загоняет пользователя в такие рамки, что он вынужден писать такие дополнительные конструкции. Невозможность писать "в лоб". Искусственные ограничения, переизбыток правил и обязательность их соблюдения.

Считаем

Объем кода zope

Указанный выше (req) файл использован пределах virtualenv:

$ pip install requirements.txt

Директория zope/ [2] взята для исследования на предмет "объема" кода. Начальный "вес", с .pyc-файлами, составил 23.9 MB, в том числе 8.8 MB в директории zope/app/. Всего - 60 субдиректорий с пространством имен zope, они же распоcтраняются как отдельные пакеты. Большинство - относительно небольшие, а вот под zope.app - 35 директорий (также распостраняются в виде отдельных egg-пакетов). Итого почти сотня "яиц".

После удаления .pyc-файлов, файлов документации, и файлов локализации (а не то, ни другое, ни третье мы не можем считать кодом фреймворка):

$ find . -name *.pyc | xargs rm
$ find . -name *.txt | xargs rm
$ cd i18n/locales/data; rm *; cd ../../..
$ rm -r app/locales

осталось 8.3 MB, в т.ч. 2.3 MB в директории zope/app/.

Акцент на zope.app сделан потому, что это - не часть ZTK, a в большей мере атавизм и излишек миграции, и работа над этим ведется. Большая часть zope.app не используется в проекте, так что как минимум половину его объема нужно смело отнимать из результатов. Или, что еще объективнее, учитывать чистый ZTK. Итого, ZTK - 6 MB.

Это была минимальная "чистка". Теперь удалим директории с явно тестовыми файлами:

$ find . -type d -name tests | xargs rm -r
$ find . -type d -name testing | xargs rm -r
$ find . -type d -name testfiles | xargs rm -r
$ find . -type d -name ftests | xargs rm -r
$ find . -name test*.py | xargs rm

и остается 5.0 MB, в т.ч. 1.6 MB под zope/app/, итого ZTK - 3.4 MB

Мне интересно знать, сколько "нормального" питоновского кода в фреймворке. Удаляем html-шаблоны и декларативные zcml-файлы [3]:

$ find . -name *.zcml | xargs rm
$ find . -name *.pt | xargs rm

Теперь директория zope/ весит 4.6 MB, в т.ч. 1.2 MB zope/app/, ZTK тот же. Т.е. уделенный объем пришелся в основном на html-шаблоны (совешенноо неиспользуемый сейчас атавизм - шаблоны пишет пользователь фреймворка, а в самом фреймворке им делать нечего). zcml же оказались несущественны при данном округлении. Оставшиеся файлы это - пайтон-модули и, немного, файлы на C и откомпилированные.

Теперь важный (и спорный) шаг. Вы видели интерфейсы? Ну разве это код? :) Типичный файл interfaces.py, лежащий почти в каждой директории, большей частью состоит из документации, и ничего не делает.)) Нормального пайтон-кода, в котором нужно отслеживать алгоритм - там нет. Кроме шуток - интерфейсы - это описания, которыми пользуется другой код, чтобы сгенерировать что-нибудь. Когда я говорю о коде, то файлы interfaces.py никак не имею в виду. Но самое главное, это конечно тот факт, что процентов 80 этих файлов - это строки с документацией. Так что обязательно удаляем:

$ find . -name interfaces.py | xargs rm

и получаем 4.2 MB, в т.ч. 1.2 MB zope.app, итого ZTK - 3 MB.

Остались забытые:

$ rm -r tal/benchmark
$ find . -name DEPENDENCIES.cfg | xargs rm
$ find . -type d -name examples | xargs rm -r
$ find zope/ -name *.png | xargs rm
$ find zope/ -name *.gif | xargs rm
$ find zope/ -name *.css | xargs rm
$ find zope/ -name *.js | xargs rm

Окончательный итог - директория zope/, состоящая именно из рабочего кода - 4.0 MB, в т.ч. zope.app - 1.0 MB, итого ZTK (Zope Toolkit) - 3 MB. Эти 3 MB - из 60-ти egg-пакетов.

Сравнение с Django

Сравнения - некорректны, и никогда таковыми не будут. Но для полноты все же - беглое сравнение с Django. Взята Django-1.2.1. Взята только директория дистрибутива, содеражщая код, т.е. django. 16.4 MB изначально, но здесь без .pyc - файлов. После удаления локализации картина проясняется:

$ rm -r conf/locale

4.9 MB. Чистим дальше:

$ find . -name *.js | xargs rm
$ find . -name *.css | xargs rm
$ find . -name *.txt | xargs rm
$ find . -name *.png | xargs rm
$ find . -name *.gif | xargs rm
$ find . -name *.html | xargs rm
$ find . -type d -name tests | xargs rm -r
$ find . -type d -name test | xargs rm -r

Теперь 3.5 MB.

Т.е. ZTK даже с интерфейсами и с zcml-файлами - меньше чем Django. При том что интерфейсы по объему почти полностью строки с документацией. Кто не видел - вот типичный пример. Еще добавим неизменные 13 строк шапки, которых нет в джанге. Объем тестов и документации в модулях не сравнивал, вероятно, он в среднем одинаковый.

Заключение по объему кода

Для меня такой результат не удивителен - я это знал, не считая. Zope3-код выглядит так: куча инфраструктуры, документации (кто сказал что это плохо?) и декларативных конструкций (тут есть место спору, да), и совсем немного рабочего кода (в котором только можно делать программные ошибки.) Так выглядит типичный код и в проектах, и в самом zope. Говорить, что BluеBream это облегченный Zope3 - не правильно. Все те же пакеты, по крайней мере на данный момент.

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

Количество сущностей, идей и паттернов

Просто перечислю. Основные идеи, в которых необходимо ориентироваться программисту:

  1. Интерфейс
  2. Схема
  3. Адаптер
  4. Подписной адаптер
  5. Подписной адаптер - обработчик
  6. Утилита
  7. Security proxy и security checker'ы (низкоуровневое)
  8. Permission
  9. Персистентность
  10. Траверс
  11. Sources & vocabularies
  12. Скины, layer'ы
  13. События
  14. Контент-провайдеры и вьюлеты
  15. Аннотации
  16. Макросы и/или компонентные виды
  17. Ресурсы
  18. Меню (несколько систем)
  19. zcml-обработчики (редко используемое)
  20. Реестры компонент, сайт-менеджеры

Основные умения:

  1. Умение написать персистентные классы и правильно манипулировать ими.
  2. Умение работать с индексами.
  3. Умение написать адаптер вида.
  4. Умение написать скин, разбив части страницы на компоненты.
  5. Способность добавить в проект и отконфигурировать авторизацию, регистрацию и профили пользователей.
  6. Умение управлять заселением инстанса ZODB локальными сайтами и утилитами.

Что ж, здесь, как видим, получасовой лекцией об MVC не отделаешься. Без хорошо оформленной инфраструктуры вида THFR ("Tutorials - HOWTOs? - FAQs? - References") очевидно, что существование фреймворка на основе ZTK практически бессмыссленно. В условиях большого количества идей важное значение принимает интегрирующая документация, помогающая объединить разрозненные представления в единое целое. Помогает этому тот факт, все идеи и шаблоны связаны несколькими базовыми, такими как компонентная модель, основанная на адаптерах.

Искусственные ограничения, заставляющие писать громоздкий пользовательский код

Если кратко, то - этого просто нет. Подробнее:

  • на bluebream можно писать "в лоб", не владея перечисленными выше идеями. Мало того, я не вижу ничего плохого в этом, и сам так начинал, написав несколько приложений, абсолютно не разбираясь в Zope3 и компонентной архитектуре, а лишь обладая умением "написать класс вида, взять параметр из запроса, отрендерить страничку". Принципиальных отличий с python-mode здесь нет, разве что код - удобнее и минималистичнее на порядок. Те приложения до сих пор работают, и я, несколько раз просматривая их, так и не увидел для себя серьезной причины переписывать их. Лично мне zope3 изначально понравился именно этим: он не делал никаких "рамок" и ограничений, и не являлся в этом смысле "фреймворком" в общепринятом виде. Он лишь дает удобную "подстилку" для разработки вэб-приложений, а использовать отдельные его возможности или нет - ваше личное дело. До сих пор мое отношение к zope3, а теперь к bluebreаm именно таково. Последний, кстати, еще дальше продвигается в данном направлении.
  • фреймворк Grok даже провоцирует писать "в лоб", намеренно уходя в сторону от идей компонентной архитектуры. "Грокать" свой, уже существующий, проект можно в любой момент, кстати. Я, правда, так и не увидел для себя причин делать это.
  • мой код обычно выглядит так: много мелких директорий, каждая из которых состоит из очень малого количества файлов (нередко 2-3), большие декларативные zcml-файлы, подробно декларирующие поведение моих и чужих компонент, модули с интерфейсам, заполненными подробной документацией, тесты, и небольшое количество собственно что-то делающего python кода (т.е. реализации интерфейсов). Иными словами: кода мало.

Таким образом, причин говорить о громоздком пользовательском коде я не вижу.

Заключение

Код самого zope (в целом, это отностится к разным значениям этого термина), и проектов, которые Вы пишете на нем - минималистичен, а байты на диске заполнены не собственно кодом, но инфраструктурой. Как показал подсчет, 90% процентов объема этой инфраструктуры не являются строго обязательными, а лишь улушают его сопровождение, и если программист хочет писать"спагетти в лоб", то никто ему делать это не запретит. Исходники Zope3 - по-видимому, меньше, чем исходники Django. Zope предлагает много идей и паттернов, и в этом можно назвать его большим или громоздким. Но при этом, не ограничивает ни в чем и позволяет писать "в лоб".

---

Обсуждение - здесь

[1]При написании сайтов делать так не рекомендуется. Обоснование же применению pip вместо buildout в данном случае - описано здесь.
[2]Из используемых в приложении модулей были еще: ZODB 2.2MB, ZEO 1.2MB, BTrees? 2.0MB, persistent, ZConfig?, zdeamon, zodbcode общим объемом не более 2MB, и директория z3c/ весом в 2.5MB (14 пакетов, в т.ч. фреймворк z3c.form). Если все указанные пакеты очистить от .pyc файлов, документации и тестов, то получится настоль мало, что я даже не стал брать их в расчет. Кроме того, z3c - уж точно нельзя считать, т.к. не часть основного фреймворка. "Подсчет громоздкости" велся только с пакетами пространства имен "zope".
[3]Для просмотра zcml-файлов не требуется математического мышление, не требуется отслеживать алгоритм. Это - не код. Это всего лишь декларация того, что Ваш python-код играет роль компонент в компонентной модели zope. Поэтому, для большей объективности оценки, я считаю правильным удалить его.