it-swarm-pt.tech

Quando lançar uma exceção?

Eu tenho exceções criadas para todas as condições que meu aplicativo não espera. UserNameNotValidException, PasswordNotCorrectException etc.

No entanto, disseram-me que não deveria criar exceções para essas condições. Na minha UML, essas são exceções para o fluxo principal, então por que não deveria ser uma exceção?

Alguma orientação ou melhores práticas para criar exceções?

402
Kwan Cheng

Minha orientação pessoal é: uma exceção é lançada quando uma suposição fundamental do bloco de código atual é considerada falsa.

Exemplo 1: digamos que eu tenha uma função que deve examinar uma classe arbitrária e retornar true se essa classe herdar de List <>. Esta função faz a pergunta: "Este objeto é um descendente de List?" Esta função nunca deve lançar uma exceção, porque não há áreas cinzas em sua operação - cada classe herda ou não da List <>, então a resposta é sempre "yes" ou "no".

Exemplo 2: digamos que eu tenha outra função que examine uma List <> e retorne true se seu comprimento for maior que 50, e false se o comprimento for menor. Esta função faz a pergunta: "Esta lista tem mais de 50 itens?" Mas esta questão faz uma suposição - assume que o objeto que é dado é uma lista. Se eu entrego um NULL, então essa suposição é falsa. Nesse caso, se a função retornar ou verdade ou falso, então está quebrando suas próprias regras. A função não pode retornar qualquer coisa e afirma que respondeu a pergunta corretamente. Por isso, não retorna - lança uma exceção.

Isso é comparável à falácia lógica "pergunta carregada" . Cada função faz uma pergunta. Se a entrada que é dada faz com que essa pergunta seja uma falácia, então lance uma exceção. Esta linha é mais difícil de desenhar com funções que retornam void, mas a linha inferior é: se as suposições da função sobre suas entradas forem violadas, ela deve lançar uma exceção em vez de retornar normalmente.

O outro lado dessa equação é: se você encontrar suas funções emitindo exceções com frequência, provavelmente precisará refinar suas suposições.

577
The Digital Gabeg

Porque são coisas que acontecem normalmente. Exceções não são mecanismos de fluxo de controle. Os usuários costumam ter senhas erradas, não é um caso excepcional. Exceções devem ser realmente raras, situações do tipo UserHasDiedAtKeyboard.

279
blowdart

Minhas pequenas diretrizes são fortemente influenciadas pelo ótimo livro "Código completo":

  • Use exceções para notificar sobre coisas que não devem ser ignoradas.
  • Não use exceções se o erro puder ser manipulado localmente
  • Certifique-se de que as exceções estejam no mesmo nível de abstração que o resto de sua rotina.
  • Exceções devem ser reservadas para o que é verdadeiramente excepcional.
61
Commander Keen

NÃO é uma exceção se o nome de usuário não for válido ou a senha não estiver correta. Essas são coisas que você deve esperar no fluxo normal de operação. Exceções são coisas que não fazem parte da operação normal do programa e são bastante raras.

EDIT: Eu não gosto de usar exceções porque você não pode dizer se um método lança uma exceção apenas olhando para a chamada. É por isso que as exceções só devem ser usadas se você não puder lidar com a situação de uma maneira decente (pense "sem memória" ou "computador está pegando fogo").

34
EricSchaefer

Uma regra prática é usar exceções no caso de algo que você não poderia prever normalmente. Os exemplos são conectividade do banco de dados, arquivo ausente no disco, etc. Para cenários que você pode prever, ou seja, usuários que tentam efetuar login com uma senha incorreta, você deve usar funções que retornam booleanos e saber como lidar com a situação normalmente. Você não quer encerrar abruptamente a execução, lançando uma exceção apenas porque alguém digitou incorretamente sua senha.

25
japollock

Outros propõem que as exceções não devem ser usadas porque o login incorreto é esperado em um fluxo normal se o usuário digitar incorretamente. Eu discordo e não entendo o raciocínio. Compare-o com a abertura de um arquivo. Se o arquivo não existir ou não estiver disponível por algum motivo, uma exceção será lançada pela estrutura. Usando a lógica acima, isso foi um erro da Microsoft. Eles deveriam ter retornado um código de erro. O mesmo para análise, webrequests, etc., etc.

Eu não considero um login incorreto parte de um fluxo normal, é excepcional. Normalmente, o usuário digita a senha correta e o arquivo existe. Os casos excepcionais são excepcionais e é perfeitamente correto usar exceções para eles. Complicar seu código propagando valores de retorno através de n níveis acima da pilha é um desperdício de energia e resultará em um código confuso. Faça a coisa mais simples que poderia funcionar. Não otimize prematuramente usando códigos de erro, coisas excepcionais por definição raramente acontecem, e as exceções não custam nada a menos que você as jogue.

23
Bjorn Reppen

Exceções são um efeito um pouco caro, se, por exemplo, você tiver um usuário que forneça uma senha inválida, geralmente é melhor enviar um sinalizador de falha ou algum outro indicador de que ele é inválido.

Isso se deve à maneira como as exceções são tratadas, a entrada incorreta real e os itens de parada crítica exclusivos devem ser exceções, mas não as informações de login com falha.

16
Mitchel Sellers

Eu acho que você só deveria lançar uma exceção quando não há nada que você possa fazer para sair do seu estado atual. Por exemplo, se você está alocando memória e não há nenhum para alocar. Nos casos que você mencionou, você pode se recuperar claramente desses estados e pode retornar um código de erro de volta ao seu chamador.


Você verá muitos conselhos, inclusive em respostas a essa pergunta, de que deve lançar exceções apenas em circunstâncias "excepcionais". Isso parece superficialmente razoável, mas é um conselho falho, porque substitui uma questão ("quando devo lançar uma exceção") com outra questão subjetiva ("o que é excepcional"). Em vez disso, siga o conselho de Herb Sutter (para C++, disponível no Artigo do Dr. Dobbs Quando e Como Usar Exceções , e também em seu livro com Andrei Alexandrescu, C++ Coding Standards ): lançar uma exceção se, e somente se

  • uma pré-condição não é cumprida (o que normalmente impossibilita um dos seguintes) ou
  • a alternativa falharia em atender a uma condição
  • a alternativa não conseguiria manter uma invariante.

Por que isso é melhor? Não substitui a pergunta por várias perguntas sobre pré-condições, pós-condições e invariantes? Isso é melhor por vários motivos conectados.

  • Pré-condições, pós-condições e invariantes são design características de nosso programa (sua API interna), enquanto que a decisão para throw é um detalhe de implementação. Isso nos obriga a ter em mente que devemos considerar o projeto e sua implementação separadamente, e nosso trabalho ao implementar um método é produzir algo que satisfaça as restrições do projeto.
  • Isso nos força a pensar em termos de condições prévias, pós-condições e invariantes, que são as suposições somente que os chamadores de nosso método devem fazer, e são expressas com precisão, permitindo um baixo acoplamento entre os componentes do nosso programa.
  • Esse acoplamento solto nos permite refatorar a implementação, se necessário.
  • As pós-condições e invariantes são testáveis; resulta em código que pode ser facilmente testado em unidade, porque as pós-condições são predicados que nosso código de teste de unidade pode verificar (assert).
  • Pensar em termos de pós-condições naturalmente produz um design que tem sucesso como uma pós-condição , que é o estilo natural para usar exceções. O caminho de execução normal ("feliz") do seu programa é apresentado linearmente, com todo o código de manipulação de erros movido para as cláusulas catch.
14
Jon

Eu diria que não há regras rígidas e rápidas sobre quando usar exceções. No entanto, existem boas razões para usar ou não usá-las:

Razões para usar exceções:

  • O fluxo de código para o caso comum é mais claro
  • Pode retornar informações de erro complexas como um objeto (embora isso também possa ser obtido usando o parâmetro "out" do erro passado por referência)
  • Os idiomas geralmente fornecem algum recurso para gerenciar a limpeza de limpeza em caso de exceção (tente/finalmente em Java, usando em C #, RAII em C++)
  • No caso de nenhuma exceção ser lançada, a execução pode às vezes ser mais rápida do que verificar os códigos de retorno
  • Em Java, as exceções verificadas devem ser declaradas ou capturadas (embora isso possa ser um motivo contrário)

Razões para não usar exceções:

  • Às vezes é um exagero se o tratamento de erros é simples
  • Se as exceções não forem documentadas ou declaradas, elas podem não ser identificadas pelo código de chamada, o que pode ser pior do que se o código de chamada ignorasse um código de retorno (saída do aplicativo vs falha silenciosa - o que é pior pode depender do cenário)
  • Em C++, o código que usa exceções deve ser seguro contra exceções (mesmo que você não as atire ou capture, mas chame indiretamente uma função de lançamento)
  • Em C++, é difícil dizer quando uma função pode ser lançada, portanto, você deve ser paranóico quanto à segurança de exceção se usá-las
  • Geralmente, lançar e capturar exceções é significativamente mais caro em comparação com a verificação de um sinalizador de devolução

Em geral, eu estaria mais inclinado a usar exceções em Java do que em C++ ou C #, porque eu sou da opinião que uma exceção, declarada ou não, é fundamentalmente parte da interface formal de uma função, desde mudar a sua garantia de exceção pode quebrar o código de chamada. A maior vantagem de usá-los em Java IMO, é que você sabe que seu chamador deve lidar com a exceção, e isso melhora a chance de um comportamento correto.

Por causa disso, em qualquer idioma, sempre derivaria todas as exceções em uma camada de código ou API de uma classe comum, de modo que o código de chamada sempre garanta a captura de todas as exceções. Também consideraria ruim lançar classes de exceção que são específicas da implementação, ao gravar uma API ou biblioteca (ou seja, agrupar exceções de camadas inferiores para que a exceção recebida pelo responsável pela chamada seja compreensível no contexto de sua interface).

Observe que Java faz a distinção entre exceções gerais e de tempo de execução, em que as últimas não precisam ser declaradas. Eu só usaria classes de exceção Runtime quando você sabe que o erro é resultado de um bug no programa.

10
Robert

Classes de exceção são como classes "normais". Você cria uma nova classe quando "é" um tipo diferente de objeto, com campos diferentes e operações diferentes.

Como regra geral, você deve tentar equilibrar o número de exceções e a granularidade das exceções. Se o seu método lançar mais de 4-5 exceções diferentes, provavelmente você poderá mesclar algumas delas em mais exceções "gerais" (por exemplo, no seu caso "AuthenticationFailedException") e usar a mensagem de exceção para detalhar o que deu errado. A menos que seu código manipule cada um deles de maneira diferente, você não precisa criar muitas classes de exceção. E se isso acontecer, talvez você deva retornar um enum com o erro que ocorreu. É um pouco mais limpo assim.

5
Shachar

Se o código é executado dentro de um loop que provavelmente causará uma exceção repetidamente, lançar exceções não é uma boa coisa, porque elas são muito lentas para N. grande Mas não há nada errado em lançar exceções personalizadas se o desempenho não for um problema. Apenas certifique-se de que você tem uma exceção base que todos eles herdam, chamado BaseException ou algo parecido. BaseException herda System.Exception, mas todas as suas exceções herdam BaseException. Você pode até ter uma árvore de tipos de Exceção para agrupar tipos semelhantes, mas isso pode ou não ser um exagero.

Portanto, a resposta curta é que, se ela não causar uma penalidade de desempenho significativa (o que não deveria ocorrer, a menos que você esteja lançando muitas exceções), vá em frente.

5
Charles Graham

Eu concordo com o japollock lá em cima - lance uma aceitação quando você está incerto sobre o resultado de uma operação. Chamadas para APIs, acesso a sistemas de arquivos, chamadas de banco de dados, etc. Sempre que você estiver passando dos "limites" de suas linguagens de programação.

Eu gostaria de adicionar, fique à vontade para lançar uma exceção padrão. A menos que você vá fazer algo "diferente" (ignorar, enviar e-mail, logar, mostrar aquela imagem da baleia no Twitter, etc), então não se preocupe com exceções personalizadas.

3
dclaysmith

a regra geral para lançar exceções é bem simples. você faz isso quando seu código entrou em um estado INVÁLIDO INCONVENÁVEL. Se os dados forem comprometidos ou você não puder retroceder o processamento que ocorreu até o ponto, será necessário finalizá-lo. Na verdade, o que mais você pode fazer? sua lógica de processamento eventualmente falhará em outro lugar. Se você pode recuperar de alguma forma, faça isso e não jogue exceção.

no seu caso particular, se você fosse forçado a fazer algo bobo, como aceitar a retirada do dinheiro e só então verificar o usuário/senha, você deveria terminar o processo lançando uma exceção para notificar que algo ruim aconteceu e evitar mais danos.

3
goran

Eu diria que geralmente todo fundamentalismo leva ao inferno.

Você certamente não desejaria acabar com o fluxo acionado por exceção, mas evitar exceções também é uma má ideia. Você tem que encontrar um equilíbrio entre as duas abordagens. O que eu não faria é criar um tipo de exceção para cada situação excepcional. Isso não é produtivo.

O que eu geralmente prefiro é criar dois tipos básicos de exceções que são usadas em todo o sistema: LogicalException e TechnicalException. Estes podem ainda ser distinguidos por subtipos, se necessário, mas geralmente não é necessário.

A exceção técnica denota a exceção realmente inesperada, como o servidor de banco de dados estar inativo, a conexão com o serviço da web lançou o IOException e assim por diante.

Por outro lado, as exceções lógicas são usadas para propagar a situação errônea menos grave para as camadas superiores (geralmente algum resultado de validação).

Observe que mesmo a exceção lógica não deve ser usada regularmente para controlar o fluxo do programa, mas sim para realçar a situação em que o fluxo deve realmente terminar. Quando usados ​​em Java, os dois tipos de exceção são RuntimeException subclasses e o tratamento de erros é altamente orientado a aspectos.

Então, no exemplo de login, pode ser sábio criar algo como AuthenticationException e distinguir as situações concretas por valores enum como sernameNotExisting, PasswordMismatch etc. Então você não vai acabar tendo uma enorme hierarquia de exceções e pode manter os blocos de captura em nível de manutenção. Você também pode empregar facilmente algum mecanismo genérico de tratamento de exceções, desde que tenha as exceções categorizadas e saiba muito bem o que propagar para o usuário e como.

Nosso uso típico é lançar a LogicalException durante a chamada do Serviço da Web quando a entrada do usuário é inválida. A Exceção é organizada para o detalhe SOAPFault e, em seguida, fica desmarcada para a exceção novamente no cliente, o que resulta na exibição do erro de validação em um determinado campo de entrada da página da Web, pois a exceção possui o mapeamento adequado para esse campo.

Essa certamente não é a única situação: você não precisa acessar o serviço da Web para lançar a exceção. Você é livre para fazê-lo em qualquer situação excepcional (como no caso de você precisar falhar rápido) - é tudo a seu critério.

2
Petr Macek

As exceções são destinadas a eventos que são comportamentos anormais, erros, falhas e outros. Comportamento funcional, erro do usuário, etc., devem ser manipulados pela lógica do programa. Como uma conta ou senha incorreta é uma parte esperada do fluxo lógico em uma rotina de login, ela deve ser capaz de lidar com essas situações sem exceções.

2
Joe Skora

Em geral, você quer lançar uma exceção para qualquer coisa que possa acontecer em seu aplicativo que seja "Excepcional"

No seu exemplo, ambas as exceções parecem que você está chamando-as por meio de uma validação de senha/nome de usuário. Nesse caso, pode-se argumentar que não é realmente excepcional que alguém digitaria um nome de usuário/senha incorretamente.

Eles são "exceções" para o fluxo principal de sua UML, mas são mais "ramificações" no processamento.

Se você tentasse acessar seu arquivo ou banco de dados passwd e não poderia, isso seria um caso excepcional e autorizaria uma exceção.

2
Gord

Em primeiro lugar, se os usuários de sua API não estiverem interessados ​​em falhas específicas e refinadas, então, ter exceções específicas para eles não terá qualquer valor.

Como muitas vezes não é possível saber o que pode ser útil para seus usuários, uma abordagem melhor é ter as exceções específicas, mas garantir que eles herdem de uma classe comum (por exemplo, std :: exception ou suas derivadas em C++). Isso permite que seu cliente detecte exceções específicas, ou a exceção mais geral, caso não se importe.

2
Jason Etheridge

Eu tenho problemas filosóficos com o uso de exceções. Basicamente, você está esperando que um cenário específico ocorra, mas, em vez de manipulá-lo explicitamente, você está empurrando o problema para ser tratado "em outro lugar". E onde esse "outro lugar" é, pode-se imaginar.

2
Dan

Eu tenho três tipos de condições que eu pego.

  1. Entrada incorreta ou ausente não deve ser uma exceção. Use tanto js do lado do cliente e regex do lado do servidor para detectar, definir atributos e voltar para a mesma página com mensagens.

  2. O AppException. Isso geralmente é uma exceção que você detecta e joga no seu código. Em outras palavras, essas são as que você espera (o arquivo não existe). Registre-o, defina a mensagem e retorne à página de erro geral. Esta página geralmente tem um pouco de informação sobre o que aconteceu.

  3. A exceção inesperada. Estes são os que você não conhece. Registre com detalhes e encaminhe-os para uma página de erro geral.

Espero que isto ajude

1
Michael

para mim Exceção deve ser lançada quando uma regra técnica ou comercial necessária falhar. por exemplo, se uma entidade de carro estiver associada a um arranjo de 4 pneus ... se um pneu ou mais for nulo ... uma exceção deve ser Disparado "NotEnoughTiresException", porque ele pode ser capturado em diferentes níveis do sistema e ter um impacto significativo significado através de registro. Além disso, se apenas tentarmos controlar o fluxo nulo e impedir o instanciamento do carro. nunca poderíamos nunca encontrar a fonte do problema, porque o pneu não deveria ser nulo em primeiro lugar.

1
Genjuro

A resposta simples é, sempre que uma operação é impossível (por causa de qualquer aplicativo OR porque violaria a lógica de negócios). Se um método for invocado e for impossível fazer o que o método foi escrito, faça uma exceção. Um bom exemplo é que os construtores sempre lançam ArgumentExceptions se uma instância não puder ser criada usando os parâmetros fornecidos. Outro exemplo é InvalidOperationException, que é lançado quando uma operação não pode ser executada devido ao estado de outro membro ou membros da classe.

No seu caso, se um método como Login (nome de usuário, senha) for invocado, se o nome de usuário não for válido, é realmente correto lançar uma UserNameNotValidException, ou PasswordNotCorrectException se a senha estiver incorreta. O usuário não pode estar logado usando o (s) parâmetro (s) fornecido (s) (isto é impossível porque violaria a autenticação), portanto, lance uma exceção. Embora eu possa ter suas duas exceções herdadas de ArgumentException.

Dito isto, se você deseja NÃO lançar uma Exceção porque uma falha de login pode ser muito comum, uma estratégia é criar um método que retorna tipos que representam falhas diferentes. Aqui está um exemplo:

{ // class
    ...

    public LoginResult Login(string user, string password)
    {
        if (IsInvalidUser(user))
        {
            return new UserInvalidLoginResult(user);
        }
        else if (IsInvalidPassword(user, password))
        {
            return new PasswordInvalidLoginResult(user, password);
        }
        else
        {
            return new SuccessfulLoginResult();
        }
    }

    ...
}

public abstract class LoginResult
{
    public readonly string Message;

    protected LoginResult(string message)
    {
        this.Message = message;
    }
}

public class SuccessfulLoginResult : LoginResult
{
    public SucccessfulLogin(string user)
        : base(string.Format("Login for user '{0}' was successful.", user))
    { }
}

public class UserInvalidLoginResult : LoginResult
{
    public UserInvalidLoginResult(string user)
        : base(string.Format("The username '{0}' is invalid.", user))
    { }
}

public class PasswordInvalidLoginResult : LoginResult
{
    public PasswordInvalidLoginResult(string password, string user)
        : base(string.Format("The password '{0}' for username '{0}' is invalid.", password, user))
    { }
}

A maioria dos desenvolvedores é ensinada a evitar exceções por causa da sobrecarga causada por lançamentos. É ótimo estar consciente dos recursos, mas geralmente não à custa do design do seu aplicativo. Essa é provavelmente a razão pela qual lhe disseram para não lançar suas duas Exceções. Se usar Exceções ou não, geralmente, reduz a frequência com que a Exceção ocorrerá. Se for um resultado bastante comum ou bastante esperado, é quando a maioria dos desenvolvedores evitará exceções e criará outro método para indicar falha, devido ao suposto consumo de recursos.

Aqui está um exemplo de evitar o uso de exceções em um cenário como o descrito acima, usando o padrão Try ():

public class ValidatedLogin
{
    public readonly string User;
    public readonly string Password;

    public ValidatedLogin(string user, string password)
    {
        if (IsInvalidUser(user))
        {
            throw new UserInvalidException(user);
        }
        else if (IsInvalidPassword(user, password))
        {
            throw new PasswordInvalidException(password);
        }

        this.User = user;
        this.Password = password;
    }

    public static bool TryCreate(string user, string password, out ValidatedLogin validatedLogin)
    {
        if (IsInvalidUser(user) || 
            IsInvalidPassword(user, password))
        {
            return false;
        }

        validatedLogin = new ValidatedLogin(user, password);

        return true;
    }
}
1
core

Em minha opinião, a questão fundamental deveria ser se alguém esperaria que o chamador desejasse continuar o fluxo normal do programa se uma condição ocorresse. Se você não sabe, tenha métodos doSomething e trySomething separados, em que o primeiro retorna um erro e o último não, ou tem uma rotina que aceita um parâmetro para indicar se uma exceção deve ser lançada se falhar). Considere uma classe para enviar comandos para um sistema remoto e relatar respostas. Determinados comandos (por exemplo, reiniciar) farão com que o sistema remoto envie uma resposta, mas não respondam por um determinado período de tempo. Portanto, é útil poder enviar um comando "ping" e descobrir se o sistema remoto responde em um período de tempo razoável sem ter que lançar uma exceção se isso não ocorrer (o chamador provavelmente esperaria que os primeiros "" as tentativas de "ping" falhariam, mas uma acabaria por funcionar. Por outro lado, se alguém tiver uma sequência de comandos como:

 exchange_command ("open tempfile"); 
 exchange_command ("escrever dados do tempfile {whatever}"); 
 exchange_command ("escrever dados do tempfile {whatever}"); 
 exchange_command ("write tempfile data {whatever}"); 
 exchange_command ("escreve os dados do tempfile {o que quer que}"); 
 exchange_command ("close tempfile"); 
 exchange_command ("copiar tempfile para realfile"); 

alguém poderia querer que a falha de qualquer operação abortasse toda a sequência. Embora seja possível verificar cada operação para garantir que ela seja bem-sucedida, é mais útil ter a rotina exchange_command () lançando uma exceção se um comando falhar.

Na verdade, no cenário acima, pode ser útil ter um parâmetro para selecionar vários modos de tratamento de falhas: nunca lançar exceções, lançar exceções apenas para erros de comunicação ou lançar exceções em qualquer caso em que um comando não retorne um "sucesso" "indicação.

1
supercat

a principal razão para evitar lançar uma exceção é que há muita sobrecarga envolvida em lançar uma exceção.

Uma coisa que o artigo abaixo afirma é que uma exceção é por condições e erros excepcionais.

Um nome de usuário incorreto não é necessariamente um erro de programa, mas um erro do usuário ...

Aqui está um ponto de partida decente para exceções no .NET: http://msdn.Microsoft.com/en-us/library/ms229030 (VS.80) .aspx

1
Sam

A segurança é combinada com o seu exemplo: você não deve dizer ao invasor que existe um nome de usuário, mas a senha está incorreta. São informações extras que você não precisa compartilhar. Basta dizer "o nome de usuário ou senha está incorreto".

1
anon

O lançamento de exceções faz com que a pilha seja desfeita, o que causa alguns impactos no desempenho (admitiu que os ambientes gerenciados modernos melhoraram isso). Ainda repetidamente jogando e pegando exceções em uma situação aninhada seria uma má idéia.

Provavelmente mais importante do que isso, as exceções são destinadas a condições excepcionais. Eles não devem ser usados ​​para fluxo de controle comum, porque isso prejudicará a legibilidade do seu código.

1
Arno

Algumas coisas úteis para pensar ao decidir se uma exceção é apropriada:

  1. qual nível de código você deseja executar após a ocorrência da exceção - ou seja, quantas camadas da pilha de chamadas devem ser desfeitas. Você geralmente deseja manipular uma exceção o mais próximo possível de onde ela ocorre. Para validação de nome de usuário/senha, você normalmente lida com falhas no mesmo bloco de código, em vez de permitir que uma exceção seja gerada. Então, uma exceção provavelmente não é apropriada. (OTOH, após três tentativas de login com falha, o fluxo de controle pode mudar para outro lugar, e uma exceção pode ser apropriada aqui.)

  2. Este evento é algo que você gostaria de ver em um log de erros? Nem todas as exceções são gravadas em um log de erros, mas é útil perguntar se essa entrada em um log de erros seria útil - ou seja, você tentaria fazer algo a respeito ou seria o lixo ignorado.

0
Mike Kantor

Existem duas classes principais de exceção:

1) Exceção do sistema (por exemplo, conexão do banco de dados perdida) ou 2) Exceção do usuário. (por exemplo, validação da entrada do usuário, 'senha incorreta')

Eu achei útil criar minha própria classe de exceção de usuário e quando eu quero lançar um erro de usuário eu quero ser tratado de forma diferente (ou seja, com erros de recursos exibidos para o usuário) então tudo que eu preciso fazer no meu manipulador de erro principal é verificar o tipo de objeto :

            If TypeName(ex) = "UserException" Then
               Display(ex.message)
            Else
               DisplayError("An unexpected error has occured, contact your help  desk")                   
               LogError(ex)
            End If
0
Crusty

"PasswordNotCorrectException" não é um bom exemplo para usar exceções. Usuários recebendo suas senhas errado é de se esperar, por isso é dificilmente uma exceção IMHO. Você provavelmente até se recupera dele, mostrando uma mensagem de erro legal, por isso é apenas uma verificação de validade.

Exceções não tratadas interromperão a execução eventualmente - o que é bom. Se você está retornando códigos falsos, nulos ou de erro, você terá que lidar com o estado do programa sozinho. Se você esquecer de verificar as condições em algum lugar, seu programa pode continuar correndo com dados errados, e você pode ter dificuldade em descobrir o que aconteceu e onde.

Naturalmente, você poderia causar o mesmo problema com instruções catch vazias, mas pelo menos localizá-las é mais fácil e não requer que você entenda a lógica.

Então, como regra geral:

Use-os onde quer que você não queira ou simplesmente não consiga se recuperar de um erro.

0
DanMan

Você pode usar algumas exceções genéricas para essas condições. Por exemplo, ArgumentException deve ser usado quando algo der errado com os parâmetros para um método (com exceção de ArgumentNullException). Geralmente você não precisaria de exceções como LessThanZeroException, NotPrimeNumberException etc. Pense no usuário do seu método. O número de condições que ela desejará manipular especificamente é igual ao número do tipo de exceções que seu método precisa lançar. Dessa forma, você pode determinar quantas exceções detalhadas você terá.

By the way, sempre tente fornecer algumas maneiras para os usuários de suas bibliotecas para evitar exceções. TryParse é um bom exemplo, existe para que você não precise usar int.Parse e capturar uma exceção. No seu caso, você pode querer fornecer alguns métodos para verificar se o nome de usuário é válido ou se a senha está correta para que seus usuários (ou você) não precisem fazer muitas manipulações de exceção. Espero que isso resulte em código mais legível e melhor desempenho.

0
Serhat Ozgel

Em última análise, a decisão se resume em saber se é mais útil lidar com erros em nível de aplicativo, como esse, usando o tratamento de exceções ou por meio de seu próprio mecanismo de rolagem inicial, como retornar códigos de status. Eu não acho que haja uma regra rígida sobre qual é o melhor, mas eu consideraria:

  • Quem está chamando seu código? Esta é uma API pública de algum tipo ou uma biblioteca interna?
  • Que linguagem você está usando? Se for Java, por exemplo, lançar uma exceção (marcada) coloca uma carga explícita em seu chamador para lidar com essa condição de erro de alguma forma, em oposição a um status de retorno que poderia ser ignorado. Isso pode ser bom ou ruim.
  • Como são tratadas outras condições de erro no mesmo aplicativo? Os chamadores não querem lidar com um módulo que manipula erros de maneira idiossincrática, diferente de qualquer outra coisa no sistema.
  • Quantas coisas podem dar errado com a rotina em questão e como elas seriam tratadas de forma diferente? Considere a diferença entre uma série de blocos catch que manipulam erros diferentes e um switch em um código de erro.
  • Você tem informações estruturadas sobre o erro que precisa retornar? Ao lançar uma exceção, você obtém um local melhor para colocar essas informações do que apenas retornar um status.
0
eli