Сегодня я вступил в жаркую дискуссию с другим разработчиком в моей организации о том, где и как добавлять методы в классы с отображением базы данных. Мы используем sqlalchemy
, и основная часть существующей кодовой базы в наших моделях баз данных - это всего лишь пакет сопоставленных свойств с именем класса, почти механический перевод из таблиц базы данных в объекты Python.
В этом аргументе моя позиция заключалась в том, что основной ценностью использования ORM было то, что вы можете присоединять низкоуровневые поведения и алгоритмы к отображаемым классам. Модели - это, во-первых, классы, и, во-вторых, постоянные (они могут быть постоянными при использовании xml в файловой системе, вам не нужно заботиться). Он считал, что любое поведение вообще является «бизнес-логикой» и обязательно принадлежит где угодно, кроме постоянной модели, которая должна использоваться только для сохранения базы данных.
Я, конечно, думаю, что существует различие между тем, что является бизнес-логикой, и ее следует отделить, поскольку она имеет некоторую изоляцию от нижнего уровня того, как это реализуется, и предметной логикой, которая, как я считаю, является абстракцией, предоставляемой модельными классами. об этом спорили в предыдущем абзаце, но мне трудно разобраться, что это такое. У меня есть лучшее представление о том, каким может быть API (в нашем случае это HTTP «ReSTful»), в котором пользователи вызывают API с тем, что они хотят делать , в отличие от того, что им разрешено делать, и как это происходит. сделано
tl; dr: Какие вещи могут или должны идти в методе в отображаемом классе при использовании ORM, и что следует исключить, чтобы жить на другом уровне абстракции?
источник
Ответы:
Я в основном с тобой; ваш коллега, кажется, спорит либо об антипаттерне модели анемичного домена, либо о дублировании модели в «модели персистентности» без очевидного преимущества (я работаю над проектом Java, где это было сделано, и это огромная головная боль, связанная с ремонтопригодностью, так как это означает в три раза больше работы, когда что-либо меняется в модели).
Практическое правило: класс должен содержать логику, которая описывает основные факты о данных, которые верны при любых обстоятельствах. Логика, характерная для варианта использования, должна быть где-то еще. Примером является валидация, есть интересная статья Мартина Фаулера, где он подчеркивает, что это следует рассматривать как контекстно-зависимую.
источник
Это суждение, которое действительно зависит от вашего ожидаемого размера и масштаба того, что вы разрабатываете. Наиболее жесткий подход состоит в том, чтобы ограничить типы ORM компонентом доступа к данным и использовать POCO в общей библиотеке в качестве типов, на которые ссылаются и которые используются всеми уровнями. Это позволило бы в будущем физическое разделение, а также логическое разделение. Вы также можете решить, что между пользовательским интерфейсом и уровнем бизнес-логики должен существовать дополнительный уровень. Обычно это называется уровнем Facade или Business Interface. Этот дополнительный слой - то, где живет ваш "код варианта использования". Отдельный слабосвязанный код вызывается уровнем Facade / BI (например, Facade имеет функцию ProcessOrder (), которая вызывает бизнес-логику 1: M раз для выполнения всех шагов, необходимых для фактической обработки заказа).
Тем не менее, все это, как говорится: во многих случаях это количество архитектуры просто излишне излишним. Например, код специально для простого веб-сайта, где вы не собираетесь упаковывать его компоненты для повторного использования. Вполне допустимо создать веб-сайт MVC и использовать объекты EF для этого типа решения. Если сайт необходимо масштабировать позже, вы можете посмотреть на кластеризацию или процесс, который часто теряется, называемый «рефакторинг».
источник
Просто напомните своему коллеге, что вам не нужно переоценивать модели, как если бы это был проект Java. Я имею в виду, что сравнение двух постоянных объектов - это поведение, но оно не определено слоем постоянства. Итак, вопрос о 6 пивах таков: почему в совершенно разных классах описывается что-то одно и то же? Конечно, настойчивость является достаточно большим аспектом модели, которую нужно рассматривать отдельно, но недостаточно, чтобы ее можно было рассматривать отдельно от всего остального. Если вы водите свою машину, моете ее или разбиваете, вы все время манипулируете своей машиной.
Так почему бы просто не объединить все эти различные аспекты в один класс модели? Вам нужна куча методов класса, работающих с постоянными объектами - поместите их в один класс; у вас есть несколько методов экземпляров, имеющих дело с проверкой - поместите их в другой. Наконец, смешайте два и вуаля! Вы получили умное, самоосознанное и полностью сдержанное представление модели прямо здесь.
источник
В дополнение к другим ответам обратите внимание на скрытые cavehats при использовании моделей с расширенным доменом с ORM.
У меня были проблемы с внедрением полиморфных сервисов в классы сохраняемой модели при попытке получить что-то вроде следующего псевдокода:
В этом случае Организации может потребоваться
HRService
зависимость от конструктора (например). Обычно вы не можете легко управлять созданием классов вашей модели при использовании ORM.Я использовал Doctrine ORM и сервисный контейнер от Symfony. Я должен был обезопасить ORM не таким элегантным способом, и у меня не было выбора, кроме как отделить постоянство и бизнес-модели. Я еще не пробовал с sqlachemy, подумал. Python может оказаться более гибким, чем PHP для этого.
источник