Архитектура: лучшие практики для манипулирования моделями без загрязнения POJO?И без повторения кода котельной плиты везде - PullRequest
12 голосов
/ 23 января 2012

С этой проблемой мы часто сталкиваемся. Должны быть некоторые лучшие практики для решения этой проблемы ...

Упрощенный вопрос

Где лучше всего разместить общий код, который манипулирует POJO?

такой, что:

  • POJO имеют только свойства и методы получения / установки
  • один и тот же код манипулирования моделью не повторяется "везде"
  • это очень ясно, какие классы отвечают за манипулирование моделью

* * Фон тысяча двадцать-один * * тысяча двадцать-дв

У нас есть схема, которая определяет наш домен. Исходя из этого, мы генерируем «чистую» модель, которая состоит из простых объектов (POJO), которые исходят от JAXB.

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

Пример * * 1 032 Давайте использовать продуктовый магазин в качестве общего примера. Объекты модели состоят из таких вещей, как:
Products, Aisle, Shelf, Employee, WorkSchedule, Vendor Обычные модельные манипуляции состоят из таких вещей, как:
findManagerWorkingOnDay(day, schedule), findAisleForProduct(apples), countItemsOnShelf(topShelf), product.isModified(), removeProductFromVendor(apples, vendor) Мы не хотим «загрязнять» наш поставщик POJO функцией, подобной removeProductFromVendor. Аналогично, мы не обязательно хотим расширять каждый объект модели, просто добавив свойство isModified, чтобы наш графический пользовательский интерфейс мог «включать / отключать» кнопку сохранения. Или мы? Краткое описание

Когда объект модели находится в памяти, кто должен отвечать за его манипулирование, например, перебирать список «дежурных сотрудников сегодня» и находить того, кто является «менеджером?»

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


С точки зрения наилучшей практики, где находится идеальное место для размещения статического метода:
public static Employee findManager(List<Employee> employeesOnDuty);

, который будет перебирать список сотрудников (POJO) и возвращать первый, где employee.title.toLowerCase().contains("manager")

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

Ответы [ 5 ]

6 голосов
/ 23 января 2012

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

Звучит как работа длянабор подклассов Decorator, или, как предлагает Кен, фасады.

Мне здесь нравятся декораторы, потому что тогда вы просто ссылаетесь на своего поставщика pojo по имени класса decorator, который затем будет иметь дополнительное поведение (isModified, searchByName и т. д.), все в одном месте.

5 голосов
/ 23 января 2012

Насколько я понимаю, похоже, что ваши модели POJO являются только данными (или вы хотите сохранить их в таком виде). Почему бы не создать фасадные объекты, такие как Query, Count или другие именованные функциональные группы, которые скрывают всю связанную механику ваших алгоритмов манипуляции?

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

3 голосов
/ 03 мая 2013

, несмотря на то, что данному вопросу на данный момент 1 год, надеюсь, он может оказаться полезным для некоторых других людей.Таким образом, ваш желает хранить POJO и поведение отдельно , так что эти операторы имеют место: a) POJO имеют только свойства и методы получения / установки, b) один и тот же код манипулирования моделью используется повторно, c) ясно, какие классыотвечают за манипулирование моделью , широко признанной , а достигается через разбиение приложения на уровни, т.е.:

  1. ваши POJO - это простая модель, содержащаяполя / свойства и просто методы получения / установки;
  2. бизнес-логика, относящаяся к манипуляциям над моделью, помещается на уровень обслуживания - в вашем случае все, что касается манипуляций, например, с Employee, может быть размещено в EmployeeService (и, таким образом, повторно использовано во многих местах);
  3. все, что связано с персистентностью, направляется на уровень DAO, например EmployeeDAO;
  4. для обмена данными между уровнями, например, представление и сервис - можно использовать DTO (объекты передачи данных).

В случае, если бизнес-логика помещается в бины модели, это называется доменомдизайн - люди спрашивают об этом тут и там (лично я не поклонник доменного дизайна).

Надеюсь, это поможет.

2 голосов
/ 07 февраля 2013

В аналогичной ситуации мы решили продвигать все «функции» (поведения) как первоклассных граждан нашей объектной модели.

Итак, теперь у нас есть отдельные пакеты, один с только POJO, а другойгде у нас есть объекты Function (или Процессоры), применяющие функции к этим объектам.

Например, объект Contract в качестве POJO, а ContractBilling, ContractFinder, ContractCloser и т. д. в качестве процессоров.Большинство из них оперируют контрактом или списком контрактов.

Мы сочли это очень эффективным, и это заставило нас правильно документировать все в нашей системе (поскольку функции стали объектами).Архитектурные преимущества этого подхода были потрясающими, и, хотя у нас гораздо больше объектов в этом проекте, у нас есть меньшие классы, гораздо более управляемые, понятные и легко развивающиеся.

0 голосов
/ 13 апреля 2012

Я предполагаю, что для таких операций, как find *, они принадлежат классам обслуживания;но для isModified класс обслуживания не поможет, он должен быть в самом pojo, если, конечно, модификация тоже не происходит через класс обслуживания.Соответствующий класс обслуживания может затем поддерживать состояние таких объектов в коллекции.

...