A camada de serviço deve capturar todas as exceções dao e envolvê-las como exceções de serviço?

23

Eu tenho o aplicativo Web Spring de três camadas: dao, service e controllers. Um controlador nunca chama diretamente o dao, ele faz isso através da camada de serviço. No momento, na maioria das vezes, se houver uma exceção dao (tempo de execução) que não for tratada, ela será capturada por um JSP mostrando uma mensagem de erro para o usuário final. A camada de serviço deve capturar todas as exceções dao e envolvê-las como exceções de serviço?

try {
   daoInstance.someDaoMethod();
} catch(DataAccessException dae) {
   throw new ServiceException("message", dae);
}

Vamos supor que o ServiceException também seja em tempo de execução e também não seja tratado. Existe alguma diferença em lançar apenas o DataAccessException em vez do ServiceException? Eu apenas pensei que a camada de apresentação não deveria saber sobre a exceção de acesso a dados. Mas não vejo o objetivo de capturar exceções irrecuperáveis ​​apenas para envolvê-las.

Oscar
fonte

Respostas:

18

Eu acho que um fator importante é quem são seus clientes de serviço.

Se a sua camada de serviço é apenas um limite arquitetural entre as camadas em seu próprio projeto, e o cliente do serviço está no mesmo domínio de confiança, tudo bem para relaxar as coisas e deixar que exceções não verificadas borbulhem na camada do controlador ou no cliente de serviço.

No entanto, para código público; serviço que é consumido por terceiros ou cliente, acho que é mais fácil agrupar todas as exceções não verificadas com uma exceção orientada a serviços, principalmente por questões de segurança, segundo por acoplamento solto e abstração limpa.

Uma exceção da camada de dados nunca deve fazê-la diretamente até o usuário final de um aplicativo da web . Ele potencialmente contém informações internas sobre o seu esquema, suas consultas, informações sobre o número da linha, nomes de variáveis ​​ou funções, etc. As exceções do usuário final podem ser higienizadas em uma configuração segura.

Um cliente de serviço externo não está preocupado com os detalhes da sua implementação e, de qualquer maneira, não pode lidar com exceções não verificadas, pois são problemas de bug ou ambientais. Em aplicativos seguros, os erros do banco de dados simplesmente não são seguros o suficiente para propagar, o OracleException - ORA-01234 - ...que pode ser a terceira tabela inserida. O cliente deve ter permissão para lidar com quaisquer exceções verificadas / esperadas com as quais ele possa lidar e tratar todo o resto como um possível relatório de erro. Seu contrato de serviço deve ser uma abstração atômica, consistente e transacional. Se não puder fazer nada sobre a exceção, a única coisa útil que resta é fornecer um relatório de erro. Você já tem a capacidade de registrar a exceção. Por que sobrecarregar o usuário final com os detalhes? Seu aplicativo pode ser monitorado para que você já saiba sobre as exceções não verificadas antes que os usuários as denunciem.

Nunca é bom comer exceções, nem sou fã de exceções verificadas, mas prefiro ter um plano apropriado à natureza do produto em geral.

codenheim
fonte
13

Não, você não deve quebrar exceções do DAO em um aplicativo Web

É muito barulho no código para benefício zero. As exceções do DAO são exceções desmarcadas por um bom motivo. O código do aplicativo não pode fazer nada útil para recuperar uma exceção do DAO. O verdadeiro problema está aqui:

... será capturado por um JSP mostrando uma mensagem de erro para o usuário final.

Corrija esse problema em um só lugar, em vez de cagar toda a base de código.

Você controla como uma exceção não capturada é exibida para o usuário. Exceções não capturadas são devidas a erros de aplicativo ou a uma falha no sistema subjacente. Não há motivo para fornecer ao usuário qualquer informação sobre o motivo pelo qual sua solicitação não pôde ser atendida. Não há nada que o usuário possa fazer. Tudo o que você deve fazer é exibir uma página de erro amigável.

NB: se você está escrevendo um monte de código tedioso, por exemplo, criando um monte de blocos catch que simplesmente quebram e jogam novamente, quase sempre existe uma solução melhor.

Kevin Cline
fonte
Obrigado pela sua resposta. E sim, o jsp mostra uma mensagem personalizada: "Ops, algo deu errado". Ele não mostra qualquer informação sobre a exceção
Oscar
7

O principal motivo pelo qual um agrupamento de exceções seria usado é impedir que o código na camada de negócios precise conhecer todas as exceções possíveis no sistema . Há duas razões principais para isso:

  • Consistência: exceções declaradas agregadas na parte superior da pilha de chamadas. Se você não quebrar exceções, mas transmiti-las declarando seus métodos para lançá-las, poderá acabar com métodos de nível superior que declaram muitas exceções diferentes. Declarar todas essas exceções em cada método de backup da pilha de chamadas se torna entediante.

  • Encapsulamento: talvez você não queira que seus componentes de nível superior saibam algo sobre os componentes de nível inferior, nem sobre as exceções que lançam. Por exemplo, o objetivo das interfaces e implementações do DAO é abstrair os detalhes do acesso a dados do restante do aplicativo. Agora, se seus métodos DAO lançarem SQLException, o código usando os DAO precisará capturá-los. E se você mudar para uma implementação que lê os dados de um serviço da Web em vez de um banco de dados? Em seguida, os métodos DAO precisarão lançar RemoteException e SQLException. E, se você tiver um DAO que lê dados de um arquivo, também precisará lançar IOException. São três exceções diferentes, cada uma vinculada à sua própria implementação do DAO.

Então, em suma, a resposta é sim!

fabienbk
fonte
3
As implementações de JPA (por exemplo, Hibernate) lançam exceções não verificadas. Eles não precisam ser declarados ou capturados.
Kevin cline