Por que devo escrever todas as instruções no Try-Catch?

12

O chefe da minha empresa diz que devo escrever tudo, ou seja, TODO meu código nas instruções Try-catch. Agora, eu posso entender a abordagem 'é melhor prevenir do que remediar' aqui, mas não é muito corajoso pensar que haverá uma exceção quando os Rótulos forem criados, a posição do formulário for definida. houve casos em que Exceções em tais operações simples.

Chipre
fonte
4
Isso soa como termos de alerta pelas mesmas pessoas que dizem que todo o SQL deve ser escrito como procedimentos armazenados para um melhor desempenho.
Spong
5
Você prefere: "Se o seu código criar um erro em tempo de execução, você será demitido". O jogo do frango é divertido até ver seu oponente jogar o volante e travar o pedal pela janela.
Jeffo
4
@ Jeff O - Na verdade, acredito que no desenvolvimento de software o oponente é um trem de carga.
Joris Timmermans
5
A melhor expressão que ouvi para esse estilo de tratamento de exceção é "Pregar o cadáver na posição vertical", ou seja, deixa o aplicativo em um estado inesperado. Fail Fast, Fail Loudly é uma abordagem muito mais moderna, para que você possa realmente resolver todos os problemas.
Brook
2
O assunto da solicitação é irrelevante ... apenas dizer "o chefe da minha empresa diz que eu devo codificar ..." é uma grande bandeira vermelha. É microgestão ... esse não é o trabalho dele.
JoelFan

Respostas:

14

O chefe da minha empresa diz que devo escrever tudo, ou seja, TODO meu código nas instruções Try-catch.

Bem, isso é um pouco exagerado e apenas leva a códigos barulhentos. Quais são os benefícios de ter todo o código (cada método, por exemplo) escrito com um manipulador try catch? Apenas informa que há um erro a ser corrigido na maioria dos casos. Muitas vezes, a exceção pode e deve ser evitada em primeiro lugar.

Uma olhada no rastreamento da pilha é suficiente para revelar a causa no seu código, mesmo que o método com falha não execute a captura propriamente dita. Há momentos em que os desenvolvedores corrompem rastreamentos de pilha em exceções, mas esse é muito mais frequentemente o caso quando você tem muitos e muitos manipuladores de exceção. Como qualquer coisa: um pouco é bom, mas muito é veneno.

O tratamento de exceções é realmente muito simples:

Exceções de captura

  • sempre que você precisar de uma ação especial como reação à exceção
  • sempre que uma exceção deixar o programa em um estado inconsistente se não for tratado

Se você pensar bem, sempre há apenas um lugar que é bom para lidar com uma exceção que ocorre. E assim o manipulador deve estar naquele lugar.

Muitas exceções nem deveriam ser lançadas em primeiro lugar; portanto, não construa suas estruturas de controle em torno do tratamento de exceções, tente evitar a possível ocorrência de exceções sempre e sempre que possível.

Lembre-se de travar cedo quando as coisas derem errado (irreparavelmente). Colocar todo o código nas instruções try-catch é um absurdo, mas não se esqueça de relatar e registrar TODAS as exceções.

Falcão
fonte
O +1 não leva apenas a códigos ruidosos, mas a um desempenho ainda pior. Quando você coloca instruções em um bloco try, o HotSpot Compiler não poderá aplicar otimizações que ele faria.
Oliver Weiler
@ Oliver Weiler: Você tem uma citação que explica quais otimizações o compilador HotSpot não faz nos blocos try / catch?
Kaypro II
16

mas não é muito corajoso pensar que haverá uma exceção quando os Rótulos forem criados, a posição do formulário estiver definida. houve casos em que Exceções em tais operações simples.

Absolutamente sim! Há sempre uma maneira de as coisas darem errado que você não previu. E "coração de galinha" é uma expressão ridícula para usar neste contexto; desenvolvimento de software não significa provar seu machismo ignorando possíveis problemas.

O que é uma pergunta válida é se é útil que as exceções sejam detectadas no ponto em que seus padrões de codificação dizem que precisam. Sua declaração diz que você precisa ter o bloco try / catch em todo corpo do método, e isso é realmente um absurdo, porque muitas vezes você não pode fazer algo imediatamente útil com uma exceção, e esse é realmente o ponto principal das exceções: você pode optar por deixá-los propagar a pilha de chamadas a ser tratada no ponto apropriado.

Michael Borgwardt
fonte
13
Meus aplicativos sabem melhor do que lançar exceções ou sofrerão o surto de sua vida. Uma vez que eles pensam que você tem coração de galinha, eles caem sobre você.
JeffO 2/08
@ Michael Borgwardt: hehe, então você me criticou. Você votou negativamente nesta questão e o único voto negativo está no meu post. Você parece ter um problema sério com seu ego ou sua auto-estima. Notei isso em outras perguntas também. Você sabe, outros programadores também têm boas respostas.
Falcon
@ Falcon: Eu não diminuí o voto sobre esta questão. Não tenho idéia do que leva você a acreditar de outra forma, mas se alguém tem um sério problema de ego, é você.
Michael Borgwardt
@ Michael Borwardt: Talvez eu esteja errado. Nesse caso, peço desculpas. Pode ser que seja apenas o voto negativo em sua própria pergunta que me fez pensar que você votou aqui. Desculpe.
Falcon
8

Eu mudaria isso ao contrário. Sim, como regra geral, o tratamento de exceções é uma coisa boa, mas você pode realmente lidar com todas as exceções possíveis de maneira sensata no ponto em que é capturado? Às vezes, principalmente se você não está escrevendo software de missão crítica, é melhor simplesmente travar e queimar de alguma maneira controlada pela metade quando as coisas dão terrivelmente errado.

Se você não pode estar 100% certo de que pode lidar com todas as exceções que possam ser capturadas, provavelmente é melhor escrever algum tipo de manipulador de exceção geral, envolvendo o loop principal do programa - a mecânica exata de como fazer isso obviamente depende o idioma que você está trabalhando em Não, ingresse o máximo de detalhes sobre a exceção como você pode, salvo estado do programa (em algum lugar. outro do que para qualquer dado armazenar o usuário está trabalhando contra - lembre-se, tudo pode ser corrompido, neste ponto ), e assim por diante. Em seguida, repita a exceção e deixe o SO lidar com ela da maneira que achar melhor. Neste manipulador de exceção abrangente, esteja preparado para falhas catastróficas. Então, quando o programa for reiniciado, verifique se esse estado é de alguma forma útil e restaure o que pode ser recuperado, se for; e possivelmente ofereça ao usuário o envio de um relatório de bug para você.

um CVn
fonte
5
+1: nunca pegue uma exceção se não conseguir lidar com ela imediatamente corretamente. (Infelizmente, às vezes você tem que prendê-lo apenas para deixá-lo vaguear livre novamente, mas marcado como um tipo diferente, como parte de coagir API: Eu odeio isso.)
Donal Fellows
6

No geral, o uso de try / catch é obsoleto, porque o bloco de catch é muito caro do ponto de vista dos recursos. O uso try / catch me lembra o gerenciamento de riscos . O gerenciamento de riscos tem duas dimensões:

  1. A probabilidade de risco acontecer
  2. O dano que isso pode ter

Agora, se você sair de casa, um piano caindo sobre sua cabeça em algum lugar é muito improvável que isso aconteça (talvez 0,001%), mas pode matá-lo.

O tratamento de exceções é assim. Tente bloco não é caro. Mas o bloco catch é realmente caro, porque precisa criar uma tabela de rastreamento de pilha e fazer outras coisas. Portanto, ao tomar uma decisão sobre os blocos try / catch, considere quantas vezes você provavelmente bate no bloco catch. Se entre 10.000 usos, você o acertar apenas 1 vez, use-o. Mas, se for um formulário, e o usuário provavelmente não o preencher corretamente 50% vezes, evite colocar um bloco try / catch em ação lá.

Em locais onde a probabilidade de ocorrência de exceções é alta, é recomendável usar if {} else {}blocos para evitar a ocorrência de exceções. Por exemplo, onde você deseja dividir dois números, em vez de escrever:

try
{
    int result = a/b;
}
catch (DivisionByZeroException ex)
{
    // Showing a message here, and logging of course.
}

você deve escrever:

if (b == 0)
{
    int result = a/b;
}
else
{
    // Showing a message to user to change the value of b, etc.
}
Saeed Neamati
fonte
2
+1 para usar if / else para lidar com "exceções" que são basicamente apenas lógica de aplicativo.
Morgan Herlocker
Se for relacionado ao usuário, lembre-se de que os computadores são muito mais rápidos que as pessoas. Uma exceção lançada em 50% dos envios de formulários ainda provavelmente ocorrerá algumas vezes por segundo, mesmo com muitos usuários.
Donal Fellows
1
Não concordo com você em evitar blocos try / catch. Constantemente tentar antecipar exceções é propenso a erros, caro no tempo do desenvolvedor e dificulta a leitura do código. Um loop que lança um milhão de exceções e as captura leva 500ms para executar na minha máquina (vs. 1ms para um loop vazio), que não é a diferença de desempenho do mundo real em 99,99% dos casos (e todo o código da interface do usuário). Você deve usar exceções, exceto nos casos em que você sabe que a penalidade de desempenho é importante, porque elas tornam seu código mais confiável e permitem que você assuma que o código anterior foi executado com êxito.
Kaypro II
@ cosmic.osmo, você recupera o stacktrace ou apenas o captura?
3

Você deve usar o try-catch quando apropriado, mas, por favor, não pegue todas as exceções e nem registre-as. Nesse ponto, é o cheiro do código e o trabalho de má qualidade.

ist_lion
fonte
1
+1 para log. Programas na natureza são caixas pretas. Quando eles falham, um log dizendo "Eis o que aconteceu" ajuda bastante na solução do problema. Houve erros nos meus programas que não foram relatados e foram descobertos somente depois que os encontrei no log.
Andrew Neely
2

Pessoalmente, não suporto exceções, são MUITO, MUITO, MUITO difíceis de manipular corretamente. E tentar corromper os dados corrompidos é MUITO, MUITO, MUITO difícil!

http://blogs.msdn.com/b/mgrier/archive/2004/02/18/75324.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2004/04/22/118161.aspx

http://blogs.msdn.com/b/oldnewthing/archive/2005/01/14/352949.aspx

http://www.joelonsoftware.com/items/2003/10/13.html

Se você não chamar todas as funções como:

try
{
    TrivialFunction();
}
catch(TypeAException)
{
    //MaybeFix
}
catch(TypeBException)
{
    //MaybeFix
}
catch(TypeCException)
{
    //NO FIX - CORRUPT DATA
}
catch(TypeDException)
{
    //NO FIX - UNKNOWN STATE
}
catch(OutOfMemoryException)
{
    //Try to fix this one! Destructors might allocate on their own ;)
}
catch(Exception)
{
    //Nothing to see here, move on, everything is OK ;)
}

Não há como limpar corretamente todos os pontos de saída. Exceções são DIFÍCIL!

A única coisa boa das exceções é que, se você não as capturar, o aplicativo trava devido a um comportamento inesperado.

Codificador
fonte