Сервисный слой в приложении Java Swing - PullRequest
8 голосов
/ 24 ноября 2010

Я думаю, действительно ли мне нужен сервисный уровень.

Я использую Spring + Hibernate для настольных приложений Swing, и в этот момент у меня есть слой gui / swing-> service layer-> dao layer. Я использую пружину только для поддержки @Transactional и для IOC-инъекции

В соответствии с передовой практикой я должен написать сервис, чтобы использовать мои daos, и поместить все управление транзакциями в сервис.

Но я понимаю, что очень-очень часто сервисный уровень реплицирует только дао-методы, например:

// a DAO example
@Repository
public class CustomerHibernateDAO extends BaseHibernateDAO implements CustomerDAO {

 public List<Customer> findAllCustomerILikeName(String name){
  return getSession()
   .createCriteria(Customer.class)
   .add(Restriction.ilike("name", name))
   .list();
 }
}

// Customer service to use this dao...
@Service
@Transactional
public class CustomerService {

 @Autowired
 CustomerDAO customerDAO;

 // Why i can't call DAO instead the service?
 public List<Customer> getAllCustomersByName(String name){
      return customerDAO.findAllCustomerILikeName(name);
 }

}

Это типичное для меня использование сервисного уровня ... Hibernate не зависит от БД, а Spring не зависит от технологии: так, мне это действительно нужно?

А как насчет уникального класса Service для управления всеми DAO ?? Я думаю, что это может быть хорошим компромиссом или плохой практикой?

Я знаю, что помещать @Transactional в DAO - плохой способ, но в данный момент мне приходится писать сервисы только для того, чтобы ставить @Transactional на него ...

РЕДАКТИРОВАТЬ

Больше информации о моем приложении.

Мое приложение представляет собой программное обеспечение для управления и управления регистрацией пользователей, продуктами, заказами и другими подобными вещами. На практике он содержит много операций чтения сущности-> редактировать-> сохранить сущность или создать-> редактировать-> сохранить, и, благодаря спящему режиму, эти операции в большинстве случаев управляются ОДНЫМ дао, потому что в спящем режиме с @manyto. .. collection и cascade.save_update позволяют сохранить два или более объекта в одной и той же персистентной операции.

Так, например, в моем элементе JFrame, где я могу вставить, отредактировать или создать элемент (продукт для продажи), есть:

public ItemFrame(){
 // the constructor
 itemService=springAppContext.getBeans(ItemService.class);
}

public boolean validateForm(){
 // test if the gui is correctly filled by user
}

public boolean save(){
 // create an Item entity taking value from swing gui(JTextField etc)
 Item item=new Item();
 item.setName(nameTextField.getText());
 item.setEtc...
 // ItemService ' save method is a wrap around itemDao.save(item)...
 itemService.save(item);
}

private void saveItemActionPerformed(ActionEvent evt){
 // When i press SAVE button
 if(validateForm()){
  save();
 }
}

Это то, что у меня есть в большинстве случаев, так что я думаю, что попал в анемичный домен-антипаттерн ...

Спасибо.

Ответы [ 4 ]

3 голосов
/ 24 ноября 2010

Если ваш сервисный уровень дублирует dao, вы вообще не используете сервисный уровень. Я допустил ту же ошибку в нескольких своих приложениях, и мне было интересно, «почему уровень обслуживания выглядит таким уродливым и дублирует DAO» ...

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

Выходом из этого является использование модели расширенного домена (бины, вводимые для моделирования через @Configurable). Вы можете сказать, что это нарушает структуру слоев, и вы, вероятно, будете правы. Но я убежден, что мы должны думать о нашем приложении (домен + служба Dao +) как о едином компоненте (см. Alistair Cockburn Шестиугольная архитектура / Порты и адаптеры ).

Ваше приложение Swing / веб-клиент будет тогда клиентом для вашего основного компонента, затем вы сможете переключать их без каких-либо ограничений (потому что все, что содержит данные модификации в ядре).

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

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

EDIT

на ваше редактирование: даже в простом приложении CRUD некоторые виды действий должны быть на уровне обслуживания - например, проверка (не проверка «это число», а некоторая проверка для конкретного бизнеса). Это не должно быть на ваш взгляд, потому что если вы измените его, вам придется скопировать и вставить его снова. Когда вы смотрите на свой код, вы должны спросить себя: «Если я решу написать тонкий клиент (просмотр в веб-браузере)», есть ли какой-нибудь код, который мне придется скопировать? Если ответ ДА, то вам следует создать сервисный метод для этого, возможно, удаленного вызова.

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

Пример кода (часть статьи Сервисный интерфейс в моем приложении (Spring security)):

@Secured("ROLE_EDITOR")
public void save(ArticleDTO selectedArticle, ArticleDetailsDTO selectedArticleDetails);

В службе комментариев каждый может сохранить свои комментарии к статьям ....

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

1 голос
/ 24 ноября 2010

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

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

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

0 голосов
/ 28 марта 2012

Вместо принудительного применения

ui -> service -> DAO

для каждой операции рассмотрите возможность использования обоих

ui -> DAO
ui -> service -> DAO

, причем последняя используется для более сложных операций

0 голосов
/ 24 ноября 2010

В конце концов вам нужно будет координировать поведение между несколькими DAO.Вы также можете внести некоторую сложность в свои бизнес-правила (например: не обновлять [это], если [это] находится в определенном состоянии).Вот где сервисный уровень пригодится.

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

...