Pergunta

Estou pensando que se eu realmente precisar de uma camada de serviço.

Estou usando o Spring + Hibernate para um aplicativo de balanço da área de trabalho e, neste momento, tenho GUI/Swing Cayer-> Serviço Camada-> Dao. Eu uso a primavera apenas para suporte @transactional e para injeção de COI

A melhor prática diz que tenho que escrever um serviço para usar meu DAOS e colocar todas as transações gerenciamento no serviço.

Mas estou percebendo que, com muita frequência, a camada de serviço replica apenas os métodos DAO, por exemplo:

// 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);
 }

}

Esta é uma mina de uso tipical da camada de serviço ... Hibernate é DB-Agnóstica, a primavera é a Tecnology-Agnóstica: Então, eu realmente preciso disso?

Que tal uma aula de serviço exclusiva para gerenciar todo o DAO ?? Eu acho que isso pode ser um bom compromisso, ou, é uma péssima prática?

Eu sei que Put @Transaction no Dao é uma maneira ruim, mas neste momento tenho que escrever serviços apenas para put @transactional nele ...

EDITAR

Mais Infos sobre meu aplicativo.

Meu aplicativo é um software de gerenciamento e gerencia registro, produtos, pedidos e outras coisas como essas. Na prática, ele contém muitas entidades de leitura-> editar-> salvar entidade ou criar-> editar-> salvar operações e, graças ao Hibernate, essas operações são gerenciadas por um DAO na maioria das vezes, Becouse Hibernate com @Manyto. .. Coleção e Cascade.Save_Update Permissões para salvar duas ou mais entidades na mesma operação persistente.

Assim, por exemplo, nos meus itens jframe, onde posso inserir, editar ou criar um item (um produto para vender), existem:

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();
 }
}

Isso é o que tenho na maioria dos casos, então acho que caí em um domínio anêmico ...

Obrigado.

Foi útil?

Solução

Se sua camada de serviço duplicar o DAO, você não estiver usando a camada de serviço. Eu cometi o mesmo erro em poucos dos meus aplicativos, fiquei me perguntando "por que a camada de serviço parece tão feia e é duplicaçãog Dao" ...

A camada de serviço deve ser uma interface para sua aplicação, isso significa que alguns métodos não são os mesmos no DAO e em serviço, mas a parte principal é significativamente diferente. Não posso dizer isso sem ver o resto do seu código, mas pela sua pergunta (que é quase a mesma que foram minhas perguntas há alguns meses), parece que você está usando Modelo de domínio anêmico Antipattern. No modelo de domínio anêmico, seu modelo contém apenas campos e getters, nenhum método real (comportamento), que viola princípios fundamentais orientados a objetos (objeto == dados + comportamento) ... Seu comportamento provavelmente está em algo que parece um script de transação no serviço camada, mas deve estar no seu modelo (camada de domínio).

A saída disso é usar o modelo de domínio rico (feijões injetados para modelar via @configurable). Você pode dizer que isso viola o padrão de camadas e você provavelmente estará correto. Mas estou convencido de que devemos pensar em nosso aplicativo (domínio+dao+serviço) como um único componente (ver Alistair Cockburn Arquitetura/portas hexagonais e adaptadores).

Seu aplicativo/cliente da Web swing será um cliente para o seu componente principal, você pode alterá -lo sem limitações (faráusas tudo o que os dados de modeidades estão no núcleo).

Mas há uma limitação/desvantagem com essa abordagem. Se você usará algum tipo de segurança (segurança da primavera) ou registros ativos via Hibernate, você deve se comunicar com todos os clientes via DTO (não as próprias entidades), porque quando você entra em contato com a entidade, ele pode chamar o serviço, que ativo em si próprio via transacional e pode modificar o banco de dados (ignorar sua segurança).

Espero que eu tenha adivinhado sua arquitetura, se não, sinto muito por inventar a roda aqui, mas este post pode ajudar alguém que não sabe disso (como eu havia poucos traças atrás).

EDITAR

Para sua edição: Mesmo no aplicativo CRUD simples, algum tipo de ação deve estar na camada de serviço - por exemplo, validação (não a validação "Este é um número", mas alguma validação específica de negócios). Isso não deve estar na sua opinião, porque se você alterá -lo, você terá copiar e colar novamente. Quando você olha para o seu código, você deve perguntar a um Qeusting "Se eu decidir escrever Thin Client (veja no navegador da Web)", existe algum código, que terei que copiar? Se for a resposta que sim, você deve criar um método de serviço para essa chamada possivelmente remota.

A outra coisa que você deve/pode fazer na camada de serviço é a autorização (é o usuário nessa função permitir excluir esta entrada). O que você terá que ter uma camada de serviço para quase todas as suas entidades, porque o usuário simples deve poder editar (excluir) suas entradas, mas provavelmente não deve excluir outros usuários. Mas o usuário na função Admin pode fazer isso.

Exemplo Código (parte da interface de serviço do artigo no meu aplicativo (segurança da primavera)):

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

No serviço de comentários, todos podem salvar seus comentários em artigos ....

E uma última nota: você provavelmente deve considerar, se você precisar camada de serviço. Quando escrito de uma maneira agradável, seu aplicativo ganhará muitas qualidades em sua flexibilidade, reutilização e manutenção. Mas é muito difícil e demorado escrever. Se você não quiser fazer isso tudo isso (segurança, modelo de domínio rico, chamando de mais interfaces (alterando a implementação da visualização), você pode viver sem ele :-)

Outras dicas

Em algum momento, seu aplicativo desejará alguma lógica de negócios. Além disso, você pode validar a entrada para garantir que não haja algo de mau ou não desempenho solicitado. Essa lógica pertence à sua camada de serviço.

Além disso, pode ser possível tornar seu DAO bastante genérico, para que você tenha apenas um ou dois métodos que não mudam muito. Isso reduz o risco de fazer algo terrivelmente errado às suas aulas DAO toda vez que você deseja adicionar/alterar a funcionalidade do aplicativo.

O DAO é para dados de acesso. O serviço é para a lógica de negócios. Mantenha -os separados e você ficará mais feliz a longo prazo.

Eventualmente, você precisará coordenar o comportamento entre os vários dao. Você também pode introduzir alguma complexidade às suas regras de negócios (ex: não atualize [isso], se [isso] estiver em um estado específico). É aqui que a camada de serviço é útil.

Dito isto, não há "tecnicamente nada de errado em eliminar completamente a camada de serviço. Será apenas um pouco mais doloroso quando você decidir que precisa de um.

Em vez de aplicar

ui -> service -> DAO

Para cada operação, considere permitir ambos

ui -> DAO
ui -> service -> DAO

este último sendo usado para operações mais complexas

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top