31.12

С Новым годом!

В этом году произошло знаковое для меня событие. Прошел «восторг» от использования различных фреймворков.

Раньше было чувство, что при соответствующем желании можно сделать все, поднять проект любой сложности. Надо только провести некоторые исследования и спланировать работы, а используя современные фреймворки это будет очень быстро. Формула 80/20 работает! Свой код потом можно отправить разработчикам фреймворка и следующий подобный проект сделать еще быстрее.

В этом году произошел ряд событий опустивший меня на землю.

Начнем по порядку.

Некоторое время назад (чуть больше года) на кафедре Программирования и сетевых технологий любимого института решено было провести сравнение популярных в то время php-фреймворков. Был взят мега проект по автоматизации документооборота данной кафедры, проведена аналитика, построена структура БД с учетом последующего использования ORM. Затем проект был распилен на много мелких частей и отдан студентам в качестве курсовых. Каждый из них должен был сделать веб-приложение, выполняющее какую-то часть функционала данного проекта, используя один из популярных php-фреймворков. В ряде работ обязательным условием было генерация отчетов в pdf-формате.

Каждому из студентов рекомендовалось использовать определенный фреймворк, но получилось так что к концу отведенного времени практически все стали использовать Zend Framework. Аргументированно свой выбор из 10 человек смог объяснить только 1, который сначало попробовал выполнить поставленную перед ним задачу на CodeIgnear и CakePHP. Ряд студентов отказалось от использования фреймоворков в пользу своего говно-кода. Основной аргумент — так быстрее. Однако, на решение проблем возникших при работе с БД и из-за отсутсвия каких-либо уровней абстракциив своем приложении они потратили значительно больше времени чем съэкономили. Успешно со своей задачей справилось около половины, но в последнее время это считается нормально.

В начале 2010 г.ода был подведен итог. В целом мнение такое: фреймворки — это хорошо, Zend Framework — это совсем хорошо. Зенд не страдает излишней автоматизацией, не ставит искуственных ограничений, имеет хороший ORM. Из отрицательных результатов использования фреймворков вспоминается следующее:

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

Казалось бы на фоне этого django является серебряной пулей. Все вышеперечисленные недостатки, если и имеют место быть, то в менее выраженной форме и кода надо писать на порядок меньше. Однако, python значительно менее популярен чем php и не входит в нашу программу обучения.

Вернемся к основной теме данного блога.   В течении года на различных формах и веб-конференциях поднимался вопрос о том, что джанга плохо подходит для веб-проектов и надо искать что-то другое. В конечном итоге подобные дискуссии сводились к старой пословице: «Хочешь сделать что-то хорошо, сделай это сам». С начала было трудно с этим согласиться, но данные темы поднимались с завидной регулярностью. Идея в том, что по ряду причин часть основных компонентов фреймворка могут не подходить, и от django в проекте остается ряд не особо важных вещей, которые легко можно заменить сторонними компонентами (обработка урлов например).   То есть, если глубоко не ковырятся в django и использовать его только так, как изначально предполагали разработчики, то все ок. Если надо чего-то большего, то начинаются проблемы.

В этом году я глубоко вник в django. contrib. admin. Код этого приложения ужасен (функционал размазан между разными классами и шаблонными тэгами) и слабо расширяем, кастомизация размазана между моделью и специальным классом, не всегда работают описанные в документации решения (использование методов ModelAdmin в качестве полей ChangeList). В админке используется ряд полезных компонентов (ChangeList с фильтрами), которые имеет смысл вытащить из нее и использовать отдельно, но в настоящее время это не реально.

Разобраться с админкой пришлось, т. к. переодически поступали предложения реализовать нестандартные для django-админки фичи. Последняя из них требовала понимания работы ChangeList. Было решено взять тикет связанный с работой ChangeList, помочь закрыть его и таким образом выполнить основную задачу. Благо времени на это хватало.   В итоге я доработал патч к тикету #8054, упрощающий синтаксис настройки полей в админке на страницах со списком объектов модели. Как потом оказалось тикет сильно устарел и сейчас никому не интересен. От его обсуждения для core developers осталась единственная полезная мысль — необходимость рефакторинга админки, но про это они думают уже почти. 2 года и ничего не хотят делать с админкой пока их мысли не материализуются.

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

  • Пришлось отказаться от стандартной модели пользователей, т. к. с ней реализовать проект было еще сложнее. Модель пользователей в django — это сборная солянка из 3х разных абстракций. Очень универсальная штука, решающая большое количество задач сразу из коробки, но плохо расширямая (речь идет о самой модели пользователя). Для данного проекта реально нужного в этой модели ничего нет. Абсолютно все необходимые поля пришлось бы добавлять через профиль (даже идентификатор пользователя). Поэтому логично было отказаться от модели пользователя и вместо нее использовать профиль.
  • Переписана система комментариев — существующая с одной стороны слишком сложная (куча бесполезных в данном проекте полей) с другой не расширяемая (нельзя просто унаследоваться от какого-то класса, не получив при этом кучу не нужных полей и функционала). Еслибы стандартная система комментариев расширялась через примеси, а не через наследование, то было бы проще. От части переписать комментарии было необходимо еще и из-за предыдущего пункта, т. к. комментарии в джанго завязаны на стандартных пользователей. Но суть проблемы в том, что в django нет как таковой  абстракции приложения  и нет возможности управлять связями между ними (есть шанс, что это когда-то произойдет, но опять же если хочешь эту фичу, сделай ее сам — примерно так ответили в django-developers на вопрос о мердже ветки app-loading.).
  • Серьезно рассматривался вопрос использования wxForms вместо стандартных форм, но в итоге для форм была написана примесь, добавляющая недостающий функционал, и несколько не очень красивых виджетов.
  • Чтобы стандартные формы «заработали» пришлось выполнять основную работу в методах, отвечающих за валидацию, а не в save как это обычно принято. Это связано с обработкой ошибок в логике приложения — ошибки потом в форме надо показывать.
  • Не все сообщения об ошибках в стандартных формах можно переопределить. Это относится к ошибкам формы, а не ее полей.   Обработка ошибок в формах вообще сделана немного странно. Ошибки могут быть в полях формы и в самой форме (например, если есть зависимость между полями). При чем нет стандартного механизма управления текстом ошибок в самой  форме. Текста ошибок задаются только в описании полей. Таким образом, если использовать ModelForm и при вызове метода save произойдет ошибка (например, проблема с уникальностью введенных полей), то будет показан текст ошибки полезный только для разработчика. Чтобы изменить текст на понятный пользователю, необходимо переопределить save и делать обработку  этой ошибки самостоятельно.
  • Кастомизация генерации форм. Была задача в зависимости от типа поля назначить ему определенные css классы. Это делается через атрибуты виджетов. Формы большие, полей было много, типы полей почти все стандартные. Определять у каждого поля виджет ради установки атрбиутов — не вариант. Динамически это делается такой длинной строчкой кода, что не поигравшись в консоли сразу это не напишешь.
  • Загрузка медиа для формы с удаленного сервера. Т. е. вся статика в проекте находится на одном сервере, а у какой-то формы она на другом. Форма используется несколько раз в разных шаблонах. Над проектом работает несколько человек. Вероятность того что, при внесении изменений в медиа данной формы забудут обновить шаблоны высока. Чтобы реализовать это стандартным способом, надо переопределить метод, свойство и специальный класс для генерации медиа.

Таким образом, приходим к следующему: если есть серьезное желание использовать django в своих проектах, то необходимо участвовать в его развитии и работать с сообществом, чтобы не наступать каждый раз на одни и те же грабли.

Итак, в новом году я планирую активней участвовать в сообществе разработчиков django и поспособствовать добавлению некоторых фич. В настоящее время наиболее интересны: формы, мердж app-loading, рефакторинг системы комментариев, рефакторинг админки.

С Новым годом!

© 2010 Алексей Камедов

При копировании материалов блога ссылка на источник обязательна.