Толстые модели против. Бизнес-логика, где вы проводите различие?


16

Сегодня я вступил в жаркую дискуссию с другим разработчиком в моей организации о том, где и как добавлять методы в классы с отображением базы данных. Мы используем sqlalchemy, и основная часть существующей кодовой базы в наших моделях баз данных - это всего лишь пакет сопоставленных свойств с именем класса, почти механический перевод из таблиц базы данных в объекты Python.

В этом аргументе моя позиция заключалась в том, что основной ценностью использования ORM было то, что вы можете присоединять низкоуровневые поведения и алгоритмы к отображаемым классам. Модели - это, во-первых, классы, и, во-вторых, постоянные (они могут быть постоянными при использовании xml в файловой системе, вам не нужно заботиться). Он считал, что любое поведение вообще является «бизнес-логикой» и обязательно принадлежит где угодно, кроме постоянной модели, которая должна использоваться только для сохранения базы данных.

Я, конечно, думаю, что существует различие между тем, что является бизнес-логикой, и ее следует отделить, поскольку она имеет некоторую изоляцию от нижнего уровня того, как это реализуется, и предметной логикой, которая, как я считаю, является абстракцией, предоставляемой модельными классами. об этом спорили в предыдущем абзаце, но мне трудно разобраться, что это такое. У меня есть лучшее представление о том, каким может быть API (в нашем случае это HTTP «ReSTful»), в котором пользователи вызывают API с тем, что они хотят делать , в отличие от того, что им разрешено делать, и как это происходит. сделано


tl; dr: Какие вещи могут или должны идти в методе в отображаемом классе при использовании ORM, и что следует исключить, чтобы жить на другом уровне абстракции?


Мне кажется, что это были две проблемы, обсуждаемые одновременно, проблема персистентности. Модели - это, во-первых, классы, а потом - персистентные (они могут быть персистентными при использовании xml в файловой системе, вам не нужно об этом заботиться). и причина для кода. Обычно все проясняется, по крайней мере для меня, когда я спрашиваю себя, почему код написан, какое требование заставляет этот код. Это требование клиентов о том, как будет работать программа, или каким образом мы решили ее реализовать. Для меня первое - это бизнес-логика, а второе - то, что вы называете доменной логикой. Как это помогает

Ответы:


10

Я в основном с тобой; ваш коллега, кажется, спорит либо об антипаттерне модели анемичного домена, либо о дублировании модели в «модели персистентности» без очевидного преимущества (я работаю над проектом Java, где это было сделано, и это огромная головная боль, связанная с ремонтопригодностью, так как это означает в три раза больше работы, когда что-либо меняется в модели).

Какие вещи могут или должны идти в методе в отображаемом классе при использовании ORM, и что следует исключить, чтобы жить на другом уровне абстракции?

Практическое правило: класс должен содержать логику, которая описывает основные факты о данных, которые верны при любых обстоятельствах. Логика, характерная для варианта использования, должна быть где-то еще. Примером является валидация, есть интересная статья Мартина Фаулера, где он подчеркивает, что это следует рассматривать как контекстно-зависимую.


+1, для второй части вашего ответа. Что касается первой части, я уверен, почему вы говорите, что анемичная модель предметной области требует так много «дополнительной» работы в случае изменения. Насколько я понимаю, изменения произойдут любым способом, но в нескольких разных классах (что отчасти плохо), но это почти одинаковое количество изменений; Я предполагаю?
NoChance

1
@ Эммад Карим: Комментарий был о наличии отдельной персистентности и моделей предметной области. Добавление свойства к модели требует добавления его к двум классам модели (а не к одному), а также к любым картам между ними (что в теории может быть автоматическим, но обычно это тот сотрудник, который считает хорошей идеей иметь отдельный класс). «модель персистентности» решает оправдать это разделение, делая их различными (например, иметь типы данных, которые более точно соответствуют модели типов БД), что в 2 + X раза превышает величину изменений, при этом X варьируется между 0 и часами потери производительности из-за неясности вопросы картирования.
Майкл Боргвардт

3

Это суждение, которое действительно зависит от вашего ожидаемого размера и масштаба того, что вы разрабатываете. Наиболее жесткий подход состоит в том, чтобы ограничить типы ORM компонентом доступа к данным и использовать POCO в общей библиотеке в качестве типов, на которые ссылаются и которые используются всеми уровнями. Это позволило бы в будущем физическое разделение, а также логическое разделение. Вы также можете решить, что между пользовательским интерфейсом и уровнем бизнес-логики должен существовать дополнительный уровень. Обычно это называется уровнем Facade или Business Interface. Этот дополнительный слой - то, где живет ваш "код варианта использования". Отдельный слабосвязанный код вызывается уровнем Facade / BI (например, Facade имеет функцию ProcessOrder (), которая вызывает бизнес-логику 1: M раз для выполнения всех шагов, необходимых для фактической обработки заказа).

Тем не менее, все это, как говорится: во многих случаях это количество архитектуры просто излишне излишним. Например, код специально для простого веб-сайта, где вы не собираетесь упаковывать его компоненты для повторного использования. Вполне допустимо создать веб-сайт MVC и использовать объекты EF для этого типа решения. Если сайт необходимо масштабировать позже, вы можете посмотреть на кластеризацию или процесс, который часто теряется, называемый «рефакторинг».


3

Просто напомните своему коллеге, что вам не нужно переоценивать модели, как если бы это был проект Java. Я имею в виду, что сравнение двух постоянных объектов - это поведение, но оно не определено слоем постоянства. Итак, вопрос о 6 пивах таков: почему в совершенно разных классах описывается что-то одно и то же? Конечно, настойчивость является достаточно большим аспектом модели, которую нужно рассматривать отдельно, но недостаточно, чтобы ее можно было рассматривать отдельно от всего остального. Если вы водите свою машину, моете ее или разбиваете, вы все время манипулируете своей машиной.

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


1

В дополнение к другим ответам обратите внимание на скрытые cavehats при использовании моделей с расширенным доменом с ORM.

У меня были проблемы с внедрением полиморфных сервисов в классы сохраняемой модели при попытке получить что-то вроде следующего псевдокода:

Person john = new Person('John Doe')
Organisation company = organisation_repository.find('some id')
Employee our_collegue_john = company.hire(john)

В этом случае Организации может потребоваться HRServiceзависимость от конструктора (например). Обычно вы не можете легко управлять созданием классов вашей модели при использовании ORM.

Я использовал Doctrine ORM и сервисный контейнер от Symfony. Я должен был обезопасить ORM не таким элегантным способом, и у меня не было выбора, кроме как отделить постоянство и бизнес-модели. Я еще не пробовал с sqlachemy, подумал. Python может оказаться более гибким, чем PHP для этого.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.