Это вопрос, который я задал некоторое время назад на SO, но он может быть обсужден лучше здесь ...
Там, где я работаю, мы несколько раз обсуждали эту тему и ищем проверку на здоровье. Вот вопрос: должны ли Business Objects быть контейнерами данных (больше похожими на DTO ) или они также содержат логику, которая может выполнять некоторые функции для этого объекта.
Пример. Возьмите объект customer, он, вероятно, содержит некоторые общие свойства (Name, Id и т. Д.). Должен ли этот объект также включать функции (Save, Calc и т. Д.)?
В одной из рассуждений говорится, что отделите объект от функциональности (принципал единой ответственности) и поместите функциональность в слой или объект Business Logic.
Другая линия рассуждений говорит: нет, если у меня есть объект customer, я просто хочу вызвать Customer.Save и покончить с этим. Почему я должен знать о другом классе, чтобы спасти клиента, если я потребляю объект?
В двух последних наших проектах объекты были отделены от функциональности, но вновь возникли споры о новом проекте.
Что имеет больше смысла и почему?
источник
Ответы:
Если вы считаете, что Заказчик является частью модели предметной области, тогда имеет смысл (особенно в контексте DDD, но не ограничивается этим) иметь свойства и операции для этого объекта.
Тем не менее, с учетом сказанного, я думаю, что пример, который вы использовали, плохой, и является причиной спора. Если вы говорите о постоянстве, то клиенты обычно не «спасают» себя; все, что вы используете для настойчивости, будет. Имеет смысл, что любой тип постоянства должен принадлежать постоянному слою / разделу. Это, как правило, основа шаблона хранилища. ** Такой метод, как Customer.UpgradeWarranty () или Customer.PromoteToPreferred (), делает аргумент более понятным.
Это также не исключает возможности наличия DTO . Рассмотрим ситуацию, когда вы собираетесь передать информацию о клиенте, например, в удаленный сервис. Для клиента может не иметь смысла создавать DTO для транспорта, это архитектурная проблема, но для этого можно было бы обосновать это на уровне персистентности или на сетевом уровне / раздел / код / что-у-вас. В этом случае такой объект может иметь методы, которые выглядят так
Итак, в целом, имеет смысл иметь операции над объектом домена, которые соответствуют логическим операциям в домене.
Google для «Постоянства невежества» для ряда хороших обсуждений по этому вопросу ( этот вопрос SO , и его принятый ответ является хорошим местом для начала).
** Это немного запутано с определенным программным обеспечением OR / M, где вы вынуждены наследовать от постоянной базы, которая имеет метод «Сохранить».
источник
На самом деле, я только недавно переработал некоторый код, чтобы отделить объекты от данных. Причина в том, что данные получают через отдельный сервис, и гораздо проще просто передать необработанные данные на сервер или с сервера, а не передавать весь объект туда-сюда и иметь дело с ошибками проверки на сервере.
Для небольших проектов наличие объектов, содержащих их бизнес-логику, и данных, вероятно, хорошо, но для крупных проектов или проектов, которые могут со временем расширяться, я бы определенно разделил слои.
источник
Я думаю, что оба способа сделать это могут иметь свои преимущества, но я бы посмотрел на это с точки зрения объектно-ориентированного или доменного управления: каковы обязанности различных классов и объектов.
Итак, я бы спросил себя в вашем конкретном случае: должен ли клиент знать, как себя спасти?
Для меня ответом будет «нет»: логически для меня это не имеет смысла, и клиент вообще не должен ничего знать о какой-либо структуре постоянства (разделение обязанностей).
Что касается примеров SnOrfus с Customer.UpgradeWarranty () или Customer.PromoteToPreferred (), они, очевидно, более ориентированы на бизнес-логику, чем Customer.Save (). Существуют различные подходы к этому, но, опять же, если вы спросите себя, должен ли клиент иметь возможность обновить свою гарантию, ответ может быть как да, так и нет, в зависимости от того, как вы на это смотрите:
Вернуться к исходному вопросу; какой способ имеет больше смысла, вероятно, будет зависеть от того, кого вы спрашиваете, и от того, какой метод вы предпочитаете, но самое главное, вероятно, придерживаться одного способа сделать это.
Однако, по моему опыту, разделение данных и (бизнес) логики делает архитектуру более простой, хотя и не такой захватывающей.
источник
Я думаю, что вы конкретно говорите о разнице между
ActiveRecord
шаблоном иRepository
шаблоном. В первом сущности знают, как сохранить себя, а во втором хранилище знает о постоянстве. Я думаю, что последний предлагает лучшее разделение проблем.В более широком смысле, если сущности действуют больше как структура данных, то у них не должно быть поведения, но если у них есть поведение, то их не следует использовать как структуру данных. Пример:
Структура данных:
Структура без данных:
В первом случае вы можете без проблем перемещаться по дереву структуры данных вашей модели из любой точки рабочего кода, и это нормально, потому что вы рассматриваете его как структуру данных. В последнем случае Клиент больше похож на услугу для данного клиента, поэтому вам не следует вызывать методы для результата. Все, что вы хотите знать о клиенте, должно быть доступно путем вызова метода объекта Customer.
Итак, вы хотите, чтобы ваши объекты были структурами данных или службами? Для согласованности, кажется, лучше придерживаться одного. В первом случае поместите свою логику типа «сервис» в другое место, а не в сущность.
источник
Я не могу ответить на ваш вопрос, но мне показалось забавным, что мы также проводим эту дискуссию в одном из наших школьных проектов. Я хотел бы отделить логику от данных. Но многие мои одноклассники говорят, что объект должен содержать всю логику И данные.
Я постараюсь обобщить факты, которые они приводят:
Объект бизнес-класса представляет собой вещь, поэтому все данные и логика должны содержаться. (например, если вы хотите открыть дверь, вы делаете это сами, вы не спрашиваете кого-то еще. плохой пример, который я знаю)
Проще понять код и функциональность объекта бу.
Меньше сложности в дизайне
Я говорю им, что они ленивы, и я сделал бы это так:
Да, бизнес-классы представляют вещи, поэтому он содержит данные. Но кажется неправильным спасать себя или даже копировать. Вы не можете сделать это в RL.
Если вы возьмете на себя ответственность за все, это сделает его не пригодным для долговечности и ремонтопригодности в будущем. Если у вас есть отдельный класс, который отвечает за сохранение, если вы добавляете в проект новый объект, вы можете легко реализовать его функцию сохранения. вместо того, чтобы кодировать все это снова в этом классе.
Имея один объект, способный сохранять данные, этот объект может содержать соединение с базой данных, и весь трафик базы данных направляется на этот объект. (в основном это слой доступа к данным), иначе весь объект Business должен был бы содержать соединение. (что добавляет сложности)
Ну, так или иначе, я собираюсь спросить учителя. Когда я это сделаю, я также опубликую его ответ здесь, если хотите. ;)
редактировать:
Я забыл упомянуть, что этот проект был о книжном магазине.
источник
Ответ на самом деле будет зависеть от того, какова ваша архитектура / дизайн - архитектура DDD с моделью предметной области будет сильно отличаться от модели, ориентированной на данные CRUD, когда речь идет о проектировании объектов.
В общем, имейте в виду, что в объектно-ориентированном дизайне вы пытаетесь инкапсулировать состояние и демонстрировать поведение. Это означает, что вы, как правило, пытаетесь максимально приблизить состояние, связанное с поведением, к этому поведению - когда вы этого не делаете, вы вынуждены раскрывать состояние в той или иной форме.
В доменной модели вы хотите отделить бизнес-модель от инфраструктурных проблем, поэтому вам абсолютно необходимо избегать таких методов, как «.Save». Я не помню, когда в последний раз я «спасал» клиента в реальной жизни!
В приложении CRUD данные относятся к первоклассному гражданину, поэтому «.Save» вполне уместен.
Большинство значительных реальных приложений будут иметь смесь этих парадигм - модель предметной области, где существуют быстро меняющиеся или сложные бизнес-правила, DTO для передачи данных через границы, CRUD (или что-то между CRUD и моделью предметной области, такой как activerecord) в другом месте. Не существует единого правила, подходящего для всех.
источник
Некоторое время я обдумывал один и тот же вопрос - я думаю, что компонент данных и компонент логики должны быть разделены. Я верю в это, потому что это дает вам правильное представление о бизнес-логике как о интерфейсе с данными, которые дают смысл.
Я также изменил бы точку зрения Скотта Уитлока сверху (за исключением того, что у меня нет точек, являющихся новым членом), классы данных или бизнес-логики не должны беспокоиться о том, как объект хранится постоянно.
Тем не менее, если вы имеете дело с существующим продуктом, если у вас есть чистые, контрактные интерфейсы - это нормально и обслуживаемо тоже ...
источник