Джанго: Толстые модели и тощие контроллеры?

Это общий вопрос архитектуры. Во многих местах я читал, что в среде 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, читайте здесь.

Другие вопросы по тегам