Подтвердить что ты не робот

Должны ли объекты Enterprise Java быть немыми?

В нашем устаревшем приложении Java EE есть классы классов значений (VO), которые обычно содержат только геттеры и сеттеры, возможно, equals() и hashCode(). Это (обычно) объекты, которые должны быть сохранены в хранилище постоянного хранения. (Для записи наше приложение не имеет EJB, хотя это может измениться в будущем - и мы используем Hibernate для сохранения наших объектов.) Вся бизнес-логика для управления данными в VO находится в отдельных классах (не EJB, а просто POJO). Мое мышление OO ненавидит это, так как я считаю, что операции над определенным классом должны находиться в том же классе. Поэтому у меня есть желание рефакторировать, чтобы переместить логику в соответствующие VO.

Я только что обсудил с коллегой, который гораздо более опытен в Java EE, чем я, и он подтвердил, что немые сущности, по крайней мере, были рекомендуемым способом. Тем не менее, он также недавно прочитал мнения, которые ставят под сомнение обоснованность этой позиции.

Я понимаю, что есть проблемы, которые по крайней мере ограничивают то, что может быть помещено внутри класса сущности:

  • он не должен иметь прямую зависимость от уровня данных (например, код запроса должен переходить в отдельные DAO)
  • если он напрямую открыт для более высоких уровней или для клиента (например, через SOAP), его интерфейс, возможно, потребуется ограничить

Есть ли более веские причины не, чтобы переместить логику в мои сущности? Или любые другие проблемы, которые необходимо учитывать?

4b9b3361

Ответ 1

Предполагается, что DTO и VO используются для передачи данных и не вставляют логику. бизнес-объекты, с другой стороны, должны вставлять некоторую логику. Я говорю некоторые, потому что всегда есть баланс между тем, что вы вкладываете в сервисы, которые координируют логику с участием нескольких бизнес-объектов и то, что вы вкладываете в сами бизнес-объекты. Типичная логика бизнес-объектов может быть проверкой, вычислением поля или другой операцией, которая воздействует только на один бизнес-объект за раз.

Обратите внимание, что я до сих пор не упоминал термин entity. Персистентные сущности были популяризированы с помощью ORM, и в настоящее время мы пытаемся использовать постоянные объекты как DTO, так и бизнес-объекты одновременно. То есть сам объект течет между уровнями и уровнями и содержит некоторую логику.

Есть ли более веские причины, а не переместить логику в мои сущности? Или любой другие проблемы, которые необходимо учитывать?

Как вы указали, все зависит от зависимостей и того, что вы раскрываете. Пока объекты тупые (близкие к DTO), они могут быть изолированы в выделенной банке легко, что служит API уровня. Чем больше логики вы вкладываете в сущности, тем сложнее это делается. Обратите внимание на то, что вы показываете и на что вы зависите (загружаете класс, клиент должен также иметь класс зависимости). Это относится к исключениям, иерархии наследования и т.д.

Чтобы привести пример, у меня был проект, в котором у объектов был метод toXml(...), используемый в бизнес-слое. Как следствие, клиент объектов зависел от XML.

Но если вы не слишком заботитесь о слоях и строгом разделении между API и реализацией, я думаю, что полезно переместить некоторую логику в сущности.

ИЗМЕНИТЬ

Этот вопрос обсуждался много раз и, вероятно, продолжит обсуждение, поскольку нет окончательного ответа. Несколько интересных ссылок:

Ответ 2

Я думаю, что ваша точка верна.
См. Это для больше - http://martinfowler.com/bliki/AnemicDomainModel.html
С JPA Объекты - это легкие объекты. Поэтому я не думаю, что у нее проблемы с логикой в ​​них. В случае использования с SOAP/Web Services я добавлю отдельный фасад.

Ответ 3

Помимо статьи Фаулера, упомянутой ранее, существует полный трактат о моделях с богатыми и анемичными доменами в книге Эрика Эванса "Domain Driven Design" (2004).

Кроме того, проверьте http://dddcommunity.org/

Ответ 4

Правильно, вот резюме обратной связи, полученной от моего тренера Java EE.

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

Например, рассмотрите метод calculateInterestRate() внутри BankAccount, который извлекает информацию из других объектов домена, например, проверяя, как долго кто-то был клиентом. Чтобы избежать зависимости, можно разделить метод по всем объектам, но этот подход означает, что код может закончиться разбросанным по нескольким классам. На этом этапе можно создать класс InterestCalculator.

Еще одна вещь, которую нужно учитывать, - это безопасность потоков. Singleton DAO и Services, обрабатываемые Spring, должны быть потокобезопасными, тогда как все, что находится в модели домена, будет подвергаться проблемам concurrency.

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

Ответ 5

Соглашение, о котором вы говорите, состоит в том, чтобы принять модель анемичного домена, в отличие от модели с богатым доменом, где Entities - это простые POJO, аннотированные как beans (@Entity) с минимальным минимальным с точки зрения getters и seters. Таким образом, класс с методом toXML() будет рассматриваться как богатый домен. Я думаю, это помогает сохранить четкое представление о том, что отображается в реляционной базе данных, даже если степень детализации отличается.

Преимущество состоит в том, что существует четкое разделение между логикой и данными (здесь и нарушается философия OO). Подход состоит в том, чтобы сгруппировать их в классы бизнес-логики или Сервисы. Это соответствует многоуровневой архитектуре с соответствующими уровнями: Domain, Services, DAO и UI.

Что теория.

Изменить: просто чтобы уточнить, когда я говорю там четкое разделение между логикой и данными, я имею в виду, что один объект ориентирован на данные, а другой метод ориентирован таким образом, который можно было бы считать завершением процедуры.

Ответ 6

Основная проблема с добавлением логики к этим классам - им потребуется больше атрибутов, чтобы отслеживать состояние объекта, и эти дополнительные атрибуты обычно не нужно сериализовать. Это означает, что необходима дополнительная работа в механизме сериализации этих классов.

Учитывая, что многие проекты имеют смесь jr. программисты и ср. программисты и большая часть работы выполняется младшим, которые не понимают (или не заботятся) об оптимальной сериализации, гораздо проще иметь эти простые старые Java-объекты как "объекты ценности", которые в значительной степени просто передают и получают данные и поместите логику в другое место.

Если вам удастся создать архитектуру, где логика помещается в бизнес-объект (то есть VO + Logic), я думаю, что было бы лучше. Просто имейте в виду, что вся команда находится на одной странице, и они не дублируют код и логику (что никогда не бывает правильно?)

Короткий ответ: Нет, они не должны быть всегда тупыми, но гораздо легче иметь их таким образом.

Ответ 7

Я проделал некоторое программирование на С, и в то время как ООП хорош для упрощения проблем, создавая иерархии классов, я по-прежнему считаю, что простой подход С является самым простым и самым большим во многих случаях. В C у нас есть структуры с только публичными членами, а программист передает в такие структуры функции (в Java такие функции будут, например, статическими функциями в каком-то классе), которые управляют элементами. Данные и алгоритм разделены, поскольку функции не являются членами структур. У меня всегда было ощущение, что объекты VO похожи на структуры в C.

Существует много случаев, когда язык C не является самым большим, поскольку, например, нет иерархии, нет никакого полиморфизма, вещи, которые достойные программисты ООП находят полезными. Однако в целом мне нравится этот простой подход C и предпочитают использовать его, если я не знаю, что метод ООП будет действительно полезен. Например. когда мне нужно использовать иерархию классов для моделирования чего-либо или мне нужно убедиться, что члены одного или нескольких классов (в иерархии) всегда совместимы друг с другом, тогда я не могу использовать подход C struct. Но в этих случаях у меня были бы не только сеттеры и геттеры.

Я бы также назвал эту статью о С++, но мне нравится, как этот парень объясняет такие вещи: http://www.gotw.ca/gotw/084.htm В этой статье есть 2 правила о том, когда нужно сделать функцию членом класса:

(из приведенной ниже цитаты я оставляю некоторые вещи, читаю оригинал, если вы хотите увидеть все)

  • Всегда делайте его членом, если он должен быть одним: какие операции должны быть членами, потому что язык С++ просто так говорит (например, конструкторы) или по функциональным причинам (например, они должны быть виртуальными)? Если они должны быть, тогда, ну, они просто должны быть; закрыт.

  • Предпочитаете сделать его членом, если ему нужен доступ к внутренним элементам: для каких операций требуется доступ к внутренним данным, которые мы могли бы предоставить через дружбу? Обычно они должны быть членами.

Во всех остальных случаях предпочитайте делать это nonmember nonfriend: какие операции могут работать одинаково хорошо, как nonmember nonfriends? Они могут и, как правило, должны быть не-членами. Это должен быть случай по умолчанию, к которому нужно стремиться.

У меня такое чувство, что если вы сомневаетесь в том, добавить ли функции к этим классам, у вас нет настоящей необходимости. То, что я написал здесь, является лишь частью всех причин, почему я не добавлял бы методы к таким классам, но, возможно, это отец всех моих других причин. Но это все субъективно, поэтому YMMV. Кстати, подход статических функций полезности упрощает модульное тестирование в большинстве случаев.

Ответ 8

Объекты часто генерируются. В таких языках, как Java, не существует частичного класса, поэтому мы не можем расширять сущность (не рассматривая такие шаблоны, как Visitor). Поэтому, когда вам нужно восстановить свои сущности, вам придется снова добавить бизнес-логику, что совсем не практично.

С сущностями я предпочел бы высокий уровень сцепления между объектами и их логикой.

Другие вопросы, которые следует учитывать, - это тот факт, что не все бизнес-операции над сущностью одинаковы во всех ситуациях. Кроме того, разрешение бизнес-логики в субъектах имеет тенденцию подвергать сущность взаимодействию с интеграционными технологиями, такими как XML, которые, на мой взгляд, должны всегда оставаться в стороне от логики домена. В архитектуре лука XML будет находиться во внешней оболочке и объектах домена во внутренней части, чтобы проиллюстрировать, насколько они действительно удаляются друг от друга, если вы хотите создать многоразовую подключаемую систему.