Pergunta

Qual é o melhor lugar para lidar com as exceções? Bll, dal ou pl?

Devo permitir que os métodos no DAL e BLL lançassem as exceções na corrente e deixe o PL lidar com eles? Ou devo lidar com eles no BLL?

por exemplo

Se eu tiver um método no meu dal, que emite "executEnonQuery" e atualiza alguns registros e, devido a um ou mais motivos, 0 linhas serão afetadas. Agora, como devo deixar meu PL saber que se uma exceção aconteceu ou realmente não havia linhas correspondentes à condição. Devo usar "Experimente a captura" no meu código PL e avise-o por meio de uma exceção, ou devo lidar com a exceção em dal e retornar algum código especial como (-1) para deixar o PL diferenciar entre a (exceção) e (não As linhas correspondem à condição, ou seja, linhas zero afetadas)?

Foi útil?

Solução

Não faz sentido deixar uma exceção que é lançada na bolha dal até o PL - como o usuário deve reagir se a conexão do banco de dados não puder ser estabelecida?

Pegue e lide com exceções mais cedo, E se Você pode lidar com eles. Não apenas os engula sem emitir uma dica ou uma mensagem de log - isso levará a sérias dificuldades e bugs difíceis de rastrear.

Outras dicas

Este é um tópico enorme, com muita controvérsia desnecessária (pessoas com vozes altas dando informações ruins!) Se você estiver disposto a lidar com isso, siga os conselhos do S1MM0T, é principalmente agradável.

No entanto, se você quiser uma resposta de uma palavra, Coloque -os no pl. Sério. Se você puder se safar, coloque seu manuseio de erros em um manipulador de exceção global (todos os erros devem registrar e dar um código para procurar a produção por razões de segurança (ESP se web), mas devolva todos os detalhes durante o desenvolvimento para o desenvolvimento para razões de velocidade).

Editar: (esclarecimento) Você precisa lidar com alguns erros em todos os lugares - mas essa não é uma norma de 'todas as funções'. Na maioria das vezes, deixe -os borbulhar até o PL e manipular o erro global do .NET com seu próprio código: registre a pilha de chamadas completa a partir daí através de uma rotina comum que é acessível a partir de todas as três camadas por meio de manipuladores de eventos (consulte Editar na parte inferior da mensagem ). Isso significa que você vai não Tente/pegue aspersadas através de todo o seu código; Apenas seções que você espera e erro e pode lidar com isso ali mesmo, ou seções não críticas, com as quais registra o erro e informa o usuário de funcionalidade indisponível (isso é ainda mais raro e para programas super relacionados/críticos)

Além disso, ao trabalhar com itens de recursos limitados, costumo usar a palavra-chave 'usando' ou tentar/finalmente/final, tente sem a captura. Para bloqueio multithreading/sinalizadores de prevenção mutex/reentrada/etc. Você também precisa tentar/finalmente em todos os casos, para que seu programa ainda funcione (especialmente aplicativos com estado).

Se você estiver usando exceções de forma inadequada (por exemplo, para lidar com não-bugs quando você deve usar a instrução IF ou verificar uma operação duvidosa funcionará antes de experimentá-la), essa filosofia desmoronará mais.

Uma nota lateral, em aplicativos de clientes grossos, especialmente quando existe a possibilidade de perder quantidades significativas ou a entrada dos usuários, você pode ser melhor com mais tentativas/capturas onde tenta salvar os dados (marcados como ainda não válidos, é claro ).

EDITAR: outra necessidade de pelo menos ter o rotina de registro no PL - Isso funcionará de maneira diferente, dependendo da plataforma. Um aplicativo que estamos trabalhando em ações do BLL/DAL com 3 versões PL: uma versão do ASP.NET, uma versão WinForms e uma versão de teste de regressão do Modo de Modo de Modo de App Console. A rotina de registro que é chamada está na verdade no BLL (o DAL apenas lança erros ou lida totalmente com os que recebe ou o re-lança). No entanto, isso levanta um evento que é tratado pelo PL; Na Web, ele o coloca no log do servidor e faz exibição de mensagens de erro no estilo da Web (mensagem amigável para produção); No WinForms, uma janela de mensagem especial aparece com informações de suporte técnico, etc. e registra o erro nos bastidores (os desenvolvedores podem fazer algo 'secreto' para ver as informações completas). E, é claro, na versão de teste, é um processo muito mais simples, mas também diferente.
Não tenho certeza de como eu teria feito isso no BLL, exceto por passar um parâmetro 'qual plataforma', mas como não inclui bibliotecas WinForms ou ASP de que o registro depende, isso ainda seria um truque.

A resposta curta é que depende!

Você só deve lidar com uma exceção se puder fazer algo útil com isso. O 'algo útil' depende novamente do que você está fazendo. Você pode registrar os detalhes da exceção, embora isso não esteja lidando com isso e você deva realmente reprimir a exceção após o registro na maioria das circunstâncias. Você pode encerrar a exceção em outra exceção (possivelmente personalizada) para adicionar mais informações à exceção. Como @mbeckish toques, você pode tentar se recuperar da exceção, novamente novamente, novamente, por exemplo - você deve ter cuidado para não tentar novamente para sempre. Finalmente (desculpe o trocadilho) Você pode usar um bloco finalmente para limpar quaisquer recursos, como uma conexão aberta. O que você escolhe fazer com a exceção influenciará onde você lida com isso. É provável que não haja muitas coisas úteis que possam ser feitas com muitas exceções além de relatar ao usuário que ocorreu um erro, nesse caso, seria mais do que aceitável lidar com a exceção na camada da interface do usuário e relate o problema ao usuário (você provavelmente deve registrar a exceção também, mais abaixo suas camadas).

Ao lançar exceções, você só deve jogar exceções em curvas excepcionais, pois há uma grande sobrecarga na realização de exceções. No seu exemplo, você sugere que pode estar pensando em lançar uma exceção se nenhum registro for atualizado por sua operação. Isso é realmente excepcional? Uma coisa melhor a fazer nessa situação seria retornar o número de registros atualizados - essa ainda pode ser uma condição de erro que precisa ser relatada ao usuário, mas não é excepcional como o comando falhando porque a conexão com o banco de dados tem fui abaixo.

este é um artigo razoável sobre as práticas recomendadas de manuseio de exceções.

A camada que sabe o que fazer para acertar as coisas deve ser a camada que lida com a exceção. Por exemplo, se você decidir lidar com erros de deadlock, repetindo a consulta um certo número de vezes, poderá construir isso em seu dal. Se continuar falhando, você poderá deixar a exceção bolha até a próxima camada, o que pode decidir se sabe como lidar adequadamente com essa exceção.

Todas as camadas em seu aplicativo devem gerenciar exceções graciosamente. Isso é conhecido como um milho de corte cruzado, porque aparece em todas as suas camadas. Eu acredito que, usando uma estrutura como o bloco de exceção corporativo com a Unity, você acabará com um código melhor em geral. Dê uma olhada neste post

http://msdn.microsoft.com/en-us/library/ff664698(v=pandp.50).aspx

Levará algum tempo para dominá -lo, mas há muitos exemplos e screencast por lá.

Como lidar com exceções depende das necessidades técnicas e comerciais. Para atualizações de banco de dados complexas ou altamente importantes, incluo params que passam em uma pequena lista de erros conhecidos backup para o DL. Dessa forma, cenários de erro conhecidos podem ser resolvidos programaticamente em alguns casos. Em outros casos, o erro precisa ser registrado e o usuário deve ser notificado de um erro.

Eu faço uma prática de notificar um ser humano de erros. Claro, o registro nos fornecerá informações detalhadas, mas não substitui o tempo de resposta de um ser humano. Não apenas isso, mas por que forçar os desenvolvedores a assistir aos registros do sistema apenas para ver se as coisas estão indo para o sul? Fale sobre custo desnecessário.

Se você tiver tempo para definir possíveis erros/exceções e resolvê -los programaticamente, faça -o. Muitas vezes erros/exceções são inesperados. É por isso que é importante estar preparado para isso inesperado e que melhor maneira de fazer isso do que envolver um ser humano.

No geral, deve -se estar na defensiva ao planejar o manuseio de exceções. Os programas crescem ou morrem. Uma parte do crescimento está introduzindo bugs. Portanto, não gire suas rodas tentando matar todas elas.

A pergunta para você é onde a exceção é relevante? Se for uma exceção de acesso a dados, ele deve ser capturado no DAL. Se for uma exceção lógica, ela deve ser capturada no BLL. Se for uma exceção de apresentação, então no pl.

Por exemplo, se o seu dal lançar uma exceção, ele deve retornar um nulo ou um falso ou qualquer que seja o caso para o seu BLL. Seu BLL deve saber o que fazer se o dal retornar um nulo, talvez o passe, talvez tente chamar outra função, etc. O mesmo acompanha o seu PL se o BLL passar por um nulo do dal ou retornar algo específico Por conta própria, a camada de apresentação deve ser capaz de notificar o usuário final de que havia um problema.

É claro que você não receberá as mensagens de exceção detalhadas, mas isso é uma coisa boa no que diz respeito aos seus usuários. Você deve ter um sistema de registro flexível para capturar essas exceções e relatá -las a um banco de dados ou um IP: porta ou o que você decidir.

Essencialmente você precisa pensar em termos de separação de preocupações Se a preocupação for um problema de dados ou um problema lógico, ela deve ser tratada de acordo.

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