Как правильно использовать Struts ActionForms, Value Objects и Entities?

Я унаследовал большое приложение Java, которое использует Struts, Spring и Hibernate. Классы и интерфейсы, которыми я занимаюсь ежедневно, это: Struts Actions, Struts ActionForms, объекты Value, интерфейсы и реализации служб, интерфейсы и реализации DAO и сущности. Я довольно четко понимаю, как и почему большинство из них, за исключением того, что я не уверен в правильном разделении обязанностей между ActionForms, Value Objects и Entities. Следует также упомянуть, что модель домена (т.е. Все сущности) не содержит значительной (если таковой) реальной бизнес-логики. Это по сути приложение CRUD, и большая часть реальной логики находится в базе данных (yuck!). Во всяком случае, есть несколько различных проблем, связанных с Java, о которых мне интересно:

1) Кажется, нет большой разницы между объектами и объектами Value (VO), и много кода должно быть записано для преобразования в другое, когда они проходят через сервисный уровень в любом направлении (Struts Actions касаются только VO, DAO имеют дело только с Entities). Таким образом, ВО и Сущности кажутся несколько избыточными. Почему они оба?

2) Где должен быть код перевода VO ↔ Entity? Сервисный уровень, Entity, VO?

3) VO помещаются непосредственно в ActionForms и напрямую связаны с тегами в JSP (например,). Это хорошая практика? Если нет, то какой дизайн?

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

5) У ОВ есть поле для идентификатора базы данных. Я думал, что у ОВ нет удостоверений? Что с этим?

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

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

3 ответа

1. Учитывая преобразование DAO-VO; будет ли это полезно, зависит от того, как используется Hibernate. Если вся обработка веб-запросов находится в одном сеансе Hibernate, вам не понадобятся отдельные VO.

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

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

3. Что касается использования VO в форме; если VO хорошо отобразит JSP, я бы сказал, почему бы и нет? Я также впечатлен тем, что модель данных так близко соответствует поддерживаемому им процессу и немного подозрительна, что база данных не была нормализована (что может или не может представлять проблемы в будущем).

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

  1. Уровень сервиса должен иметь возможность знать, какие объекты базы данных изменить, а id предназначен для этого. Уровень обслуживания должен будет получить DAO из базы данных и записать поля из VO в DAO, хотя, очевидно, нет необходимости обновлять идентификатор DAO с идентификатором VO:)

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

В зависимости от того, принимает ли VO идентификатор постороннего объекта или требует объект, вы должны либо:

  • установите id или
  • получить посторонний объект как VO по идентификатору с использованием уровня сервиса и поместите его в свой VO и сохраните его с помощью уровня обслуживания

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

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

В качестве заключительной заметки; не касайтесь вещи DAO-VO, если вы не знаете, что делаете ДЕЙСТВИТЕЛЬНО ХОРОШО. Hibernate - мощный и сложный инструмент, который обманчиво прост в использовании. Вы можете очень легко ошибаться, и их очень сложно найти. И клиенты и боссы, похоже, не оценивают введение ошибок в вещи, которые раньше работали.

Кстати; мой консерватизм в DAO-VO возникает из-за проблем с фиксацией из-за подобных проблем в переходах EJB2 в Hibernate. Дьявол находится в деталях, и изменение того, как вы справляетесь с уровнем данных, является основным рефакторингом, даже если он похож на кусок пирога.


1) Нет необходимости в отдельном VO и Entities: некоторые компании предоставляют такую ​​структуру для своего проекта. Возможно, это имело смысл в другом проекте, и, следовательно, оно было санкционировано (я могу только догадываться)

2) Сервисный уровень: это естественное разделение от DAO и Action, правильно?

3) Это не повредит, но значение Объекты привязаны до тех пор, пока они должным образом проверены перед отправкой в ​​DAO

4) Уровень обслуживания должен отвечать за перевод между ними. Во время загрузки и экономии времени

5), если у них нет тождеств, тогда как вы могли бы предотвратить дублирование?

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


Чтобы ответить на вашу последнюю часть, используйте Spring MVC вместо Struts. Затем вы можете использовать одни и те же объекты домена во всех слоях - классы, которые привязаны к параметрам формы, также используются в Hibernate и содержат реальную бизнес-логику.

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

licensed under cc by-sa 3.0 with attribution.