Como documentar exceções lançadas em c # / .net

139

Atualmente, estou escrevendo uma pequena estrutura que será usada internamente por outros desenvolvedores da empresa.

Desejo fornecer boas informações do Intellisense, mas não sei como documentar exceções lançadas.

No exemplo a seguir:

public void MyMethod1()
{
    MyMethod2();

    // also may throw InvalidOperationException
}

public void MyMethod2()
{
    System.IO.File.Open(somepath...); // this may throw FileNotFoundException

    // also may throw DivideByZeroException
}

Eu sei que a marcação para documentar exceções é:

/// <exception cref="SomeException">when things go wrong.</exception>

O que eu não entendo é como documentar exceções geradas pelo código chamado por MyMethod1() ?

  • Devo documentar exceções geradas por MyMethod2()
  • Devo documentar exceções geradas por File.Open()?

Qual seria a melhor maneira de documentar possíveis exceções?

Arnold Zokas
fonte
4
Eu sei que isso não é exatamente o que você estava perguntando (e essa é uma pergunta muito antiga), mas Eric Lippert (desenvolvedor principal nas equipes de compilador e design de C # da Microsoft) escreveu uma postagem no blog sobre os 4 tipos de exceções que eu acho que todo desenvolvedor deve estar pensando ao escrever o código de tratamento de exceções: blogs.msdn.com/b/ericlippert/archive/2008/09/10/…
javajavajavajavajava
@javajavajavajavajava Obrigado pelo link - definitivamente vale a pena ler.
Arnold Zokas
Eu acho que essa é uma pergunta válida, porque não é óbvio como documentar corretamente as exceções em C # e as visualizações de 50K mostram que também não é óbvio para muitas pessoas. A segunda resposta mais votada é muito útil, pois mostra o uso dos xmldocs existentes para documentar isso. Votação para reabrir. Esse motivo próximo "baseado em opiniões" está matando muitas questões de programação realmente muito úteis.
Alexei

Respostas:

110

Você deve documentar todas as exceções que possam ser lançadas pelo seu código, incluindo aquelas em qualquer método que possa chamar.

Se a lista ficar um pouco grande, convém criar seu próprio tipo de exceção. Pegue todas as que você encontrar no seu método, envolva-as em sua exceção e jogue-as.

Outro lugar que você pode querer fazer dessa maneira é se o seu método estiver na face da sua API. Assim como uma fachada simplifica várias interfaces em uma única interface, sua API deve simplificar várias exceções em uma única exceção. Facilita o uso do seu código para os chamadores.


Para responder a algumas das preocupações de Andrew (dos comentários), existem três tipos de exceções: aqueles que você não conhece, aqueles que você conhece e não pode fazer nada e aqueles que você conhece e pode fazer algo sobre.

Aqueles que você não conhece sobre você querem deixar ir. É o principal a falha rápida - é melhor que seu aplicativo falhe do que entrar em um estado em que você pode acabar corrompendo seus dados. A falha informará o que aconteceu e por quê, o que pode ajudar a mover essa exceção para fora da lista "aqueles que você não conhece".

Os que você conhece e não pode fazer nada são exceções como OutOfMemoryExceptions. Em casos extremos, convém lidar com exceções como essa, mas, a menos que você tenha alguns requisitos bastante notáveis, trate-os como a primeira categoria - deixe-os ir. Você precisa documentar essas exceções? Você pareceria um tolo documentando OOMs em todos os métodos que lançam um objeto.

Os que você conhece e pode fazer algo são os que você deve documentar e agrupar.

Você pode encontrar mais algumas diretrizes sobre tratamento de exceções aqui.


fonte
3
Devo admitir que isso não parece muito prático. Não consigo imaginar quantas exceções possíveis podem ser geradas por qualquer código que eu possa chamar, além de outras coisas como OutOfMemoryException que você não gostaria de capturar e quebrar.
187 Andrew Andrew Hare
3
Sua resposta é boa, mas na verdade são duas respostas que se contradizem. "documenta todas as exceções que possam ser lançadas pelo seu código" e "As que você conhece e pode fazer alguma coisa são as que você deve documentar".
tymtam
2
@Tymek: Não. A primeira metade respondeu à pergunta "como devo documentar exceções"? A segunda parte apontou a resposta óbvia para "quais exceções devo documentar". A primeira não implica que você documente todas as exceções que possam ocorrer. Algumas pessoas são literais demais, o que exigiu a segunda metade.
5
@ Tymek Acho que seu argumento pode ser que, se você pode fazer algo a respeito, por que não fazer algo a respeito, em vez de refazê-lo e documentá-lo? Pode ser mais veraz dizer "Os que você conhece sobre os quais o código do cliente pode fazer algo". Isso remove a contradição, porque essas são as exceções ideais para o documento.
mo.
Quanto às exceções que você 'soltou', sempre é possível capturá-las em algum nível inferior que as registre ou algo assim. Você sabe; apenas criando uma maneira fácil de deixar o programa travar.
Nyerguds
96

Você deve usar a documentação xml padrão .

/// <exception cref="InvalidOperationException">Why it's thrown.</exception>
/// <exception cref="FileNotFoundException">Why it's thrown.</exception>
/// <exception cref="DivideByZeroException">Why it's thrown.</exception>
public void MyMethod1()
{
    MyMethod2();
    // ... other stuff here
}

/// <exception cref="FileNotFoundException">Why it's thrown.</exception>
/// <exception cref="DivideByZeroException">Why it's thrown.</exception>
public void MyMethod2()
{
    System.IO.File.Open(somepath...);
}

/// <exception cref="FileNotFoundException">Why it's thrown.</exception>
public void MyMethod3()
{
    try
    {
        MyMethod2();
    }
    catch (DivideByZeroException ex)
    {
        Trace.Warning("We tried to divide by zero, but we can continue.");
    }
}

O valor de fazer dessa maneira é que você está fornecendo documentação das exceções conhecidas que podem ocorrer. Esta documentação está disponível no intellisense se você estiver usando o visual studio e pode lembrá-lo (ou outros) posteriormente das exceções que você pode esperar.

Você deseja especificar os tipos de exceção específicos, porque pode lidar com um tipo de exceção, enquanto outros são o resultado de um problema sério e não podem ser corrigidos.

calafrios42
fonte
1
Como isso agrega algum valor? Por exemplo, todas essas exceções são derivações do tipo Exception. Pela minha experiência, não será prático pensar em todos os outros tipos de exceção que possam ser lançados de outras APIs chamadas nos seus métodos. Meu argumento é que não devemos nos preocupar com nenhuma exceção lançada a partir de um método do que aqueles que carregam informações comerciais.
Illuminati
7
@ShiranGinige sua experiência está errada.
Grozz 22/02
35

Você pode facilitar o processo de documentação usando vários ótimos suplementos. Um deles é o GhostDoc , um suplemento gratuito para o Visual Studio que gera comentários em documentos XML. Além disso, se você usa o ReSharper , consulte o excelente Agent Johnson Plugin for ReSharper, que adiciona uma opção para gerar comentários XML para exceções geradas.

Atualização: parece que Agen Johnson não está disponível para o R # 8, checkout Exceptional for ReSharper como uma alternativa ...

Etapa 1: o GhostDoc gera o comentário XML (Ctrl-Shift-D), enquanto o plug-in Agent Johnson para ReSharper sugere documentar a exceção também:

passo 1

Etapa 2: Use a tecla de atalho do ReSharper (Alt-Enter) para adicionar também a documentação da exceção:

etapa 2 http://i41.tinypic.com/osdhm

Espero que ajude :)

Igal Tabachnik
fonte
Os links tinypic estão quebrados.
ANeves 12/02/19
11

Pelo que entendi, a intenção de usar o elemento <exception> é usá-lo ao decorar métodos, não exceções:

/// <summary>Does something!</summary>
/// <exception cref="DidNothingException">Thrown if nothing is actually done.</exception>
public void DoSomething()
{
// There be logic here
}

Exceções que podem ser lançadas por outros métodos chamados devem ser capturadas, manipuladas e documentadas nesses métodos. Exceções que poderiam ser lançadas pelo .NET ou exceções explicitamente lançadas pelo seu próprio código devem ser documentadas.

Quanto mais específico, talvez você possa capturar e lançar suas próprias exceções personalizadas?

Daniel Schaffer
fonte
4

Parte do contrato do seu método deve ser verificar se as pré-condições são válidas, portanto:

public void MyMethod2()
{
    System.IO.File.Open(somepath...); // this may throw FileNotFoundException
}

torna-se

/// <exception cref="FileNotFoundException">Thrown when somepath isn't a real file.</exception>
public void MyMethod2()
{
    FileInfo fi = new FileInfo( somepath );
    if( !fi.Exists )
    {
        throw new FileNotFoundException("somepath doesn't exists")
    }
    // Maybe go on to check you have permissions to read from it.

    System.IO.File.Open(somepath...); // this may still throw FileNotFoundException though
}

Com essa abordagem, é mais fácil documentar todas as exceções que você lança explicitamente sem precisar também documentar que uma OutOfMemoryException pode ser lançada etc.

Rowland Shaw
fonte
1
Não sei ao certo qual é o objetivo dessa verificação se você duplicará a exceção de que a Openchamada geraria de qualquer maneira (sem mencionar, como você observa, que há uma corrida e a verificação não garante sucesso Open) .. .
Matt Enright
1
@MattEnright Concedido, mas eu fiz isso um pouco inventado para ilustrar o ponto ...
Rowland Shaw
1

Você deve documentar todas as exceções que possam ser lançadas pelo seu método.

Para ocultar os detalhes da implementação, eu tentaria lidar com algumas exceções do MyMethod2.

Você pode recuperá-los, se não conseguir manipular ou resolver a exceção. Principalmente empacotado / envolto em uma exceção mais significativa para o chamador.

GvS
fonte
1

De fato, como já foi respondido, a maneira de documentar as exceções é usando Comentários XML.

Além dos plugins, você também pode usar ferramentas de análise estática que podem ser integradas ao TFS para garantir que você tenha as exceções documentadas.

Nos links abaixo, você pode ver como criar uma regra personalizada para o StyleCop validar que as exceções geradas pelos seus métodos estão sendo documentadas.

http://www.josefcobonnin.com/post/2009/01/11/Xml-Documentation-Comments-Exceptions-I.aspx http://www.josefcobonnin.com/post/2009/01/15/Xml-Documentation -Comments-Exceptions-II.aspx

Saudações.


fonte
0

Documente as exceções esperadas no seu método; no seu exemplo, eu informaria ao usuário que esse método pode gerar uma exceção de arquivo não encontrado.

Lembre-se de que é para informar o chamador do que esperar, para que ele possa escolher como lidar com isso.

Damien
fonte