Джанго: Толстые модели и тощие контроллеры?
Это общий вопрос архитектуры. Во многих местах я читал, что в среде MVC (1) модели должны быть толстыми, а контроллеры - худыми. Но я также читал, что (2) детали зависят от среды, в которой вы разрабатываете. Итак, что, если вы разрабатываете в django?
Мой опыт работы с django заключается в том, что большая часть логики в конечном итоге оказывается в представлениях и формах. Не "бизнес-логика", а детали обработки запросов, сеансов и т. Д. С точки зрения строк кода эти детали часто перевешивают бизнес-логику манипулирования объектами модели. Я делаю что-то не так, или так работает django?
3 ответа
MVC не является универсальным решением, и в большинстве случаев он сделан неправильно и не может выполнить свои обещания: на практике изменение модели также потребует изменений в контроллере, потому что это сделано неправильно. Если вы действительно хотите слабую связь между моделью и контроллером - и люди обычно игнорируют это - вы должны использовать сервисный шаблон (открыть как изображение). Что практически никто не делает.
Вместо того, чтобы слепо придерживаться псевдо-паттерна MVC в мире PHP, Django использует прагматичный подход. Потому что в обычной реальности разработки программного обеспечения разработчик программирует вещи, которые пользователь может видеть. Тогда пользователь (ваш начальник, клиент, клиенты...) увидит вашу работу и в конечном итоге выскажет свое мнение о том, как он хочет ее увидеть в конце. Используя Django, разработчик может взять более "ориентированный на взгляд" шаблон разработки и угадать, что: это облегчает соблюдение сроков и удовлетворение пользователей. Если вы думаете об этом, у него есть идея "nosql-ish", что представление (общий вид, а не представление django) должно быть боссом того, что происходит за кулисами.
Я хотел бы поблагодарить Django за то, что он не сделал MVC неправильно, в отличие от 99% реализаций PHP MVC там.
С другой стороны, Django является единственной платформой, которая обеспечивает надлежащую изоляцию между приложениями. Каждое приложение может иметь:
- модели
- Просмотры
- шаблоны
- URLs
- статические файлы
- тесты
- формы
- необязательные дополнения (администраторы, фильтры для ajax-select, разрешения для django-полномочий, уведомления для django-уведомлений и т. д. и т. д.)
Таким образом, даже если ваши модели / представления / шаблоны будут связаны, ваш проект можно соответствующим образом разделить на небольшие (также легко читаемые) и слабо связанные приложения. Только связанные модели / виды / шаблоны / вещи связаны между собой. Скрипт с большими жирными моделями с большими скриптами с толстыми представлениями и URL - это не то, что вам нужно в Django. Например, вы не хотите, чтобы два класса моделей, такие как Article и FootballMatch, жили вместе, вы хотите создать приложение "статьи"/"блог" и приложение "спорт", которые могут жить независимо. Конечно, иногда они должны быть связаны, в этом случае это выполнимо на уровне проекта в 90% случаев (вы бы создали другое приложение, "blog_sport", если вам понадобилось связать модели или теги-шаблоны).
Например, это очень распространенная практика - определять метод get_absolute_url() в классе Model. Да, ваш модельный класс, который теоретически должен содержать только бизнес-логику, теперь связан с вашим определением URL. Насколько это плохо на практике?!! На самом деле это великолепно, потому что для добавления этого метода требуется две секунды, и вы можете использовать его везде, где используете модель: будь то в представлениях или шаблонах. Также другие приложения (например, django.contrib.admin) будут использовать его.
Еще один немного более сложный пример блеска Django заключается в том, что запросы лениво оцениваются. Это означает, что ваша функция / класс представления определит запрос, например blog_list = Blog.objects.all(), но запрос будет фактически выполнен в шаблоне, если он вызовет значение {% для блога в blog_list %}. Таким образом, бизнес-логика в этом случае происходит в шаблоне, и если что-то не получается до рендеринга шаблона: вы сохранили запрос. Но это еще не все, если ваш шаблон просто отображает счетчик {{ blog_list.count }}, запрос на выборку вообще не будет создан, и будет выполнен только запрос на подсчет. "Общий вид" решает, какая бизнес-логика нужна. Это далеко от обещаний MVC, но, честно говоря, насколько это практично?
Я хочу сказать, что вы можете применять теорию неправильно, делать это правильно (что сокращает ваш выбор до 5 веб- фреймворков со всеми языками) или просто изящно и прагматично перейти к сути дела, чтобы выполнить свою работу в стиле дзен в кратчайшие сроки: это выбор Джанго.
Это зависит от того, о чем ваше приложение, но прелесть Django в том, что он не заставляет вас помещать свой логический код в ваши представления или модели, это ваш вызов.
Если вы думаете, что какая-то логика тесно связана с вашей моделью, вы можете сделать метод из нее. Правило (для меня) заключается в том, что ваша модель должна быть независимой от среды (веб-приложение, Crontab, выполняющий команду управления и т. Д.).
Моя политика состоит в том, чтобы попытаться поставить минимум в моих моделях.
Кстати, вы не планируете обращаться request
а также sessions
в ваших моделях не так ли? это плохая идея.
Моя самая большая проблема с Django состоит в том, что они, кажется, ломают образец MVC, добавляя слой Forms. Большая часть документации побуждает вас размещать логику валидации в формах, и тот факт, что валидаторы моделей вызываются только формой, сохраняет, только усиливает это соглашение. Но, на мой взгляд, это плохое соглашение, потому что, в конце концов, слишком часто проверяются данные, которые будут преобразованы в модель.
Лучший пример того, как это плохо, - это если вы подумаете о преобразовании традиционного проекта Django в проект, ориентированный на API, с помощью Django Rest Framework и отдельного клиентского интерфейса, который просто использует этот API. Вместо того, чтобы просто оставить ваши модели нетронутыми и сохранить большую бизнес-логику, вам придется пройти через свои формы и перенести всю логику на сериализаторы (к сожалению, Django Rest Framework также следует неработающему шаблону MVC Django и добавляет дополнительный "сериализатор"). слой).
Я думаю, что подход к жирным моделям - это путь. Подробнее о том, как это реализовать в Django, читайте здесь.