Отключение резервного хранилища с помощью Spring Web MVC - PullRequest
4 голосов
/ 05 декабря 2009

Это вопрос шаблона проектирования, поэтому я проиллюстрирую его на простом примере приложения адресной книги.

Сначала несколько предположений. 1. Представляется приемлемым непосредственное использование доменных объектов БД в качестве резервного хранилища для форм Spring MVC.

Итерация 1 моего приложения Я создал сопоставленный объект JPA Person с различными прикрепленными атрибутами. Используя шаблон DAO, я создал объект постоянства, который может получать, хранить и удалять людей из базы данных. Кроме того, у меня есть фабричный метод create, чтобы я мог получить объект person. Используя этот объект DAO, я создаю простой веб-интерфейс. Все хорошо.

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

interface IPerson {
    public String getName();
    public List<IAddress> getAddresses();
}

Но когда дело доходит до обновления веб-интерфейса, чтобы иметь возможность справляться с этими множественными реализациями, у меня возникает проблема. Реализация персистентности внедряется Spring. И, поскольку у этого объекта персистентности есть фабричный метод, у меня все хорошо для создания реализации IPerson. Но если я хочу сделать что-то необычное, например, разрешить отправку нескольких адресов в рамках одного запроса, у меня возникнет проблема. Чтобы позволить этому работать с Spring, вам, кажется, нужно использовать AutoPopulationList, поэтому Spring может просто .get (#) записать копию атрибутов в.

Итак, одним из решений этой работы является требование, чтобы все реализации персистентности использовали автоматически заполняемый список и создавали правильную реализацию для всех дочерних классов. Это уместно, учитывая, что нам нужно применить этот @PostLoad с JPA, поскольку базовые списки заменяются Hibernate.

Альтернатива состоит в том, чтобы не делать никаких предположений о реализации, переданной в реализацию постоянства, и преобразовывать / копировать объекты в соответствующий тип. Это выглядит лучше, так как тогда объект Domain остается простым, а вся сложность хранения находится в DAO. В этом случае мы использовали бы реализацию Default * интерфейсов IPerson и IAddress.

Несмотря на то, что мне нравится второй вариант лучше, я не обязательно чувствую себя комфортно в этой ситуации. Кто-нибудь может предложить какие-либо идеи или советы?

Ответы [ 3 ]

4 голосов
/ 05 декабря 2009

Альтернатива состоит в том, чтобы не делать никаких предположений о реализации, передаваемой в реализацию постоянства, и преобразовывать / копировать объекты в соответствующий тип. Это выглядит лучше, так как тогда объект Domain остается простым, и вся сложность хранения находится в DAO. Альтернативой является не делать каких-либо предположений относительно реализации, переданной в постоянную реализацию, и преобразовывать / копировать объекты в соответствующий тип. .

Это шаблон, который я использовал для Spring MVC

  • Пакет объектов домена, которые не имеют ссылок на сервисы / код DAO (воспринимайте это как вашу модель)
  • Уровень контроллера, уровень служб и уровень DAO работают с объектами домена
  • Для обработки контроллеров форм используйте отдельный слой объектов «команда» или «форма», которые моделируют данные, которые пользователь заполняет в форме, , а не объекты вашего домена. Пользователи отправляют контроллеру, который связывает запрос, с объектом «команда» / «форма», а ваш контроллер отображает или преобразует эти bean-компоненты в bean-компоненты вашего домена.

Например, у вас может быть довольно богатый объект User, но когда новые пользователи регистрируются, им нужно только заполнить 2 или 3 поля. Я бы смоделировал это как UserSignupCommand, а UserSignupController использует это как класс команд (не объект User). Затем контроллер отвечает за получение компонента UserSignupCommand и преобразование данных в компонент User или любой другой тип ввода, требуемый для уровня сервисов.

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

4 голосов
/ 05 декабря 2009

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

Алан Перлис сказал: «Лучше иметь 100 функций, работающих с одной структурой данных, чем 10 функций с 10 структурами данных». Вы особенно хотите избежать структур данных, которые в значительной степени дублируют друг друга. Поддерживать избыточную кодовую базу неинтересно.

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

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

Существует бесплатная веб-книга о доменно-управляемом дизайне от http://www.infoq.com.

1 голос
/ 05 декабря 2009

У меня обычно нет интерфейсов на модельных объектах, таких как Person и Address. Интересно, почему ты решил пойти по этому пути?

Я не могу придумать несколько реализаций для каждой. Если у вашего IPerson есть реализации, такие как «Мать», «Сестра», «Друг» и т. Д., Я бы рекомендовал вместо этого использовать ролевый дизайн. Тот факт, что фраза «Джин - это мать» так хорошо звучит, не означает, что вы должны основывать свой дизайн на IS-A и наследовании.

Адрес может изменяться при перемещении между странами, поэтому это может быть более разумным, но вам будет очень сложно придумать единый интерфейс, который подойдет как для США, так и для Японии.

В итерации 2 мне нужно поддерживать несколько типов хранения,

Можете ли вы уточнить это? Что означает «несколько типов хранения»? DAO, которые используют реляционные базы данных, файловую систему, объектные базы данных и т. Д .?

поэтому я создаю интерфейс для пользователя, который имеет несколько реализаций,

Я не понимаю, как предыдущее требование делает это необходимым.

и интерфейс для персистентности DAO, опять же с несколькими реализациями.

Это обычная весенняя идиома.

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

Но моя реальная рекомендация - исключить интерфейс IPerson, если только вы не предоставите убедительную причину его сохранения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...