Comentários XML são documentação necessária?

10

Eu costumava gostar de exigir comentários XML para documentação. Desde então, mudei de idéia por dois motivos principais:

  1. Como um bom código, os métodos devem ser auto-explicativos.
  2. Na prática, a maioria dos comentários XML são ruídos inúteis que não fornecem valor adicional.

Muitas vezes, simplesmente usamos o GhostDoc para gerar comentários genéricos, e é isso que quero dizer com ruído inútil:

    /// <summary>
    /// Gets or sets the unit of measure.
    /// </summary>
    /// <value>
    /// The unit of measure.
    /// </value>
    public string UnitOfMeasure { get; set; }

Para mim, isso é óbvio. Dito isto, se houver instruções especiais a serem incluídas, devemos usar absolutamente comentários XML.

Eu gosto deste trecho deste artigo :

Às vezes, você precisará escrever comentários. Mas, deve ser a exceção, não a regra. Os comentários devem ser usados ​​apenas quando expressam algo que não pode ser expresso em código. Se você deseja escrever um código elegante, lute para eliminar comentários e, em vez disso, escreva um código de auto-documentação.

Estou errado ao pensar que só devemos usar comentários XML quando o código não é suficiente para se explicar por conta própria?

Acredito que este seja um bom exemplo em que os comentários XML tornam o código bastante feio. É preciso uma aula como esta ...

public class RawMaterialLabel : EntityBase
{
    public long     Id                      { get; set; }
    public string   ManufacturerId          { get; set; }
    public string   PartNumber              { get; set; }
    public string   Quantity                { get; set; }
    public string   UnitOfMeasure           { get; set; }
    public string   LotNumber               { get; set; }
    public string   SublotNumber            { get; set; }
    public int      LabelSerialNumber       { get; set; }
    public string   PurchaseOrderNumber     { get; set; }
    public string   PurchaseOrderLineNumber { get; set; }
    public DateTime ManufacturingDate       { get; set; }
    public string   LastModifiedUser        { get; set; }
    public DateTime LastModifiedTime        { get; set; }
    public Binary   VersionNumber           { get; set; }

    public ICollection<LotEquipmentScan> LotEquipmentScans { get; private set; }
}

... E transforma isso:

/// <summary>
/// Container for properties of a raw material label
/// </summary>
public class RawMaterialLabel : EntityBase
{
    /// <summary>
    /// Gets or sets the id.
    /// </summary>
    /// <value>
    /// The id.
    /// </value>
    public long Id { get; set; }

    /// <summary>
    /// Gets or sets the manufacturer id.
    /// </summary>
    /// <value>
    /// The manufacturer id.
    /// </value>
    public string ManufacturerId { get; set; }

    /// <summary>
    /// Gets or sets the part number.
    /// </summary>
    /// <value>
    /// The part number.
    /// </value>
    public string PartNumber { get; set; }

    /// <summary>
    /// Gets or sets the quantity.
    /// </summary>
    /// <value>
    /// The quantity.
    /// </value>
    public string Quantity { get; set; }

    /// <summary>
    /// Gets or sets the unit of measure.
    /// </summary>
    /// <value>
    /// The unit of measure.
    /// </value>
    public string UnitOfMeasure { get; set; }

    /// <summary>
    /// Gets or sets the lot number.
    /// </summary>
    /// <value>
    /// The lot number.
    /// </value>
    public string LotNumber { get; set; }

    /// <summary>
    /// Gets or sets the sublot number.
    /// </summary>
    /// <value>
    /// The sublot number.
    /// </value>
    public string SublotNumber { get; set; }

    /// <summary>
    /// Gets or sets the label serial number.
    /// </summary>
    /// <value>
    /// The label serial number.
    /// </value>
    public int LabelSerialNumber { get; set; }

    /// <summary>
    /// Gets or sets the purchase order number.
    /// </summary>
    /// <value>
    /// The purchase order number.
    /// </value>
    public string PurchaseOrderNumber { get; set; }

    /// <summary>
    /// Gets or sets the purchase order line number.
    /// </summary>
    /// <value>
    /// The purchase order line number.
    /// </value>
    public string PurchaseOrderLineNumber { get; set; }

    /// <summary>
    /// Gets or sets the manufacturing date.
    /// </summary>
    /// <value>
    /// The manufacturing date.
    /// </value>
    public DateTime ManufacturingDate { get; set; }

    /// <summary>
    /// Gets or sets the last modified user.
    /// </summary>
    /// <value>
    /// The last modified user.
    /// </value>
    public string LastModifiedUser { get; set; }

    /// <summary>
    /// Gets or sets the last modified time.
    /// </summary>
    /// <value>
    /// The last modified time.
    /// </value>
    public DateTime LastModifiedTime { get; set; }

    /// <summary>
    /// Gets or sets the version number.
    /// </summary>
    /// <value>
    /// The version number.
    /// </value>
    public Binary VersionNumber { get; set; }

    /// <summary>
    /// Gets the lot equipment scans.
    /// </summary>
    /// <value>
    /// The lot equipment scans.
    /// </value>
    public ICollection<LotEquipmentScan> LotEquipmentScans { get; private set; }
}
Bob Horn
fonte
2
Eu diria que XML é uma péssima escolha para esse fim. É muito detalhado e geral para o uso em questão. Confira reStructuredText e sphinx para obter uma linguagem de marcação incorporada nos comentários sem torná-los ilegíveis.
Latty
2
@ Lattyware: O VisualStudio suporta esse estilo por padrão, sem necessidade de plugins ou ferramentas extras. Os comentários gerados dessa maneira são imediatamente visíveis nas dicas de ferramentas pop-up.
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner Eu diria que obter um plugin vale a pena para tornar seu código muito mais legível. O suporte interno ao reST com dicas de ferramentas como essa está no PyCharm, portanto, tenho certeza de que existem plugins para outros idiomas em outros IDEs. Obviamente, se você tem um projeto em que tudo está documentado dessa maneira, não estou sugerindo que você comece a dividir da maneira como é feito, mas para novos projetos, acho que é horrível ler e manter.
Latty

Respostas:

21

Se seus comentários forem assim apenas:

/// <summary>
/// Gets or sets the sublot number.
/// </summary>
/// <value>
/// The sublot number.
/// </value>

Então sim, eles não são tão úteis. Se eles lerem algo como isto:

/// <summary>
/// Gets or sets the sublot number.
/// Note that the sublot number is only used by the legacy inventory system.
/// Latest version of the online inventory system does not use this, so you can leave it null. 
/// Some vendors require it but if you don't set it they'll send a request for it specifically.
/// </summary>
/// <value>
/// The sublot number.
/// </value>

Então eu diria que eles têm valor. Portanto, para responder à sua pergunta: Os comentários são necessários quando eles dizem algo que o código não diz.

Uma exceção: é bom ter comentários sobre qualquer coisa que seja acessível ao público se você estiver escrevendo uma biblioteca / API que estará disponível para o público. Eu odeio usar uma biblioteca e ver uma função nomeada getAPCDGFSocket()sem explicação do que é um APCDGFSocket (eu ficaria feliz com algo tão simples quanto This gets the Async Process Coordinator Data Generator File Socket). Portanto, nesse caso, eu diria que use alguma ferramenta para gerar todos os comentários e, em seguida, ajuste manualmente os que precisam (e verifique se seus acrônimos criptográficos são explicados).

Além disso, getters / setters geralmente são maus exemplos para "os comentários são necessários?" porque geralmente são bastante óbvios e comentários não são necessários. Os comentários são mais importantes em funções que executam algum algoritmo, onde algumas explicações de por que as coisas estão sendo feitas da maneira como estão podem tornar o código muito mais compreensível e também facilitar o trabalho de futuros programadores.

... e, finalmente, tenho certeza de que essa pergunta é relevante para todos os estilos de comentários, não apenas para aqueles que são formatados usando XML (que você está usando porque está trabalhando em um ambiente .NET).

FrustratedWithFormsDesigner
fonte
2
+1 - O GhostDoc é um ponto de partida para transformar a primeira versão, que é padronizada, na segunda versão, que contém conhecimento detalhado do domínio.
Jesse C. Slicer
4
+1 para a parte porquê . O princípio DRY aplica - não repetir-se, e se o código já faz um trabalho muito bom de descrever o que parte, seus comentários devem se concentrar em explicar outra coisa (normalmente o porquê ).
Daniel B
@ DanielB ou talvez você não precise de comentários;) Eu concordo em grande parte com esta resposta, exceto a palavra necessária em "Comentários são necessários quando dizem algo que o código não diz". Acho que se o código diz tudo o que é necessário, você não precisa de mais informações nos comentários, mesmo que os comentários dêem informações que não estão no código.
Jimmy Hoffa
11
@DanielB - XML ​​Os comentários no .NET destinam-se principalmente a situações em que o programador do usuário final de uma biblioteca ou serviço não tem o código-fonte disponível para eles.
Jfrankcarr 22/10/12
2
@Lattyware - os comentários XML se integram perfeitamente ao Intellisense do Visual Studio, economizando muito tempo em comparação com a pesquisa de itens em um documento separado.
jfrankcarr
5

Os comentários que parecem inúteis para usuários que podem ler o código se tornam bastante úteis para usuários que não têm acesso à fonte. Isso acontece quando a classe é usada como API externa por pessoas de fora da sua organização: os HTMLs gerados a partir de seus documentos XML são a única maneira de aprender sobre suas aulas.

Dito isto, um comentário que reitera o nome do método com espaços adicionais entre as palavras permanece inútil. Se sua turma for usada fora de sua organização, é necessário documentar para que os intervalos válidos para seus valores não sejam válidos. Por exemplo, você deve dizer que a configuração UnitOfMeasurepara nullé ilegal, que o valor fornecido ao setter não deve conter espaços no início ou no final da string e assim por diante. Você também deve documentar o intervalo de LabelSerialNumberse difere do de uma planície Int32: talvez não permita números negativos *, ou não permite mais de sete dígitos. Seus usuários internos podem considerar isso um dado adquirido, porque analisam os números de série dia após dia, mas os usuários externos podem ficar genuinamente surpresos ao ver uma exceção do que parece um setter inocente.


* ... nesse caso, uintpode ser uma escolha melhor

dasblinkenlight
fonte
11
Não é apenas para quando você não tem a fonte. Se o seu editor puder analisá-los (como o Visual Studio faz com Comentários Xml), ele poderá fornecer informações como mouseover / pop-ups sem exigir que você navegue para um arquivo diferente. Um validador de intervalo de 1 linha que limita um int a um intervalo mais estreito é óbvio quando você acessa o arquivo em que o setter está implementado; mas ter "FrobableID deve estar entre 0 e 1000" aparece quando você começa a digitar "myFrobable.Fro ..." e o preenchimento automático nos fornece um lembrete útil.
Dan Is Fiddling Por Firelight
1

Você está absolutamente certo em evitar esses comentários inúteis. Eles tornam a leitura do código mais difícil, em vez de facilitar, e estão ocupando muito espaço.

Na minha prática, as pessoas que escrevem comentários com getters / setters, tendem a omitir comentários quando são realmente necessários (como construir uma consulta sql de 20 linhas para um componente sem documentação).

Escrevo comentários quando existem outras soluções óbvias - indico por que exatamente essa abordagem foi usada. Ou quando é difícil entender a ideia sem conhecer todos os detalhes - listo brevemente os detalhes necessários para entender o código.

O exemplo que você dá é mais sobre escrever comentários para dizer que alguém escreve comentários do que para facilitar a vida dos outros (e deles também).

BTW, você pode melhorar sua capacidade de escrever comentários retornando ao seu código antigo e tentando compreendê-lo (você pode até não reconhecer seu próprio código em 2 a 3 meses - é absolutamente como ler o código de outra pessoa). Se você fizer isso sem dor, tudo estará bem.

superM
fonte
Não conheço mais ninguém que se esforce para escrever comentários sobre getters / setters. Se você estiver usando quase qualquer IDE moderno (e até editores de texto avançados podem suportar isso por meio de plugins), os getters e setters geralmente podem ser documentados com muita facilidade com um clique do mouse ou dois, ou com o pressionamento de tecla correto (se estiver configurado). Às vezes, eles são gerados automaticamente quando você gerar o código baseado em um esquema de banco de dados ou WSDL ...
FrustratedWithFormsDesigner
@FrustratedWithFormsDesigner, a pessoa que eu estava falando era deixar a empresa, e eu acredito que todos esses comentários sobre getters / setters foram feitas por essa pessoa para mostrar que ele / ela fez algum esforço para deixar alguma documentação
SuperM
Todos os comentários do bogo foram inseridos depois que a pessoa notificou? Eu já vi pessoas criarem comentários xml vazios / inúteis em todo o lugar, como uma maneira complicada de impedir o VS de gerar avisos "Comentário xml ausente em Foo publicamente visível".
Dan Is Fiddling Por Firelight
@ Dan Neely, acho que essa pessoa realmente não se importava e acabou de adicionar comentários para dizer que eles foram adicionados. Normalmente, não prestamos muita atenção aos comentários, mas se alguém sair e estiver trabalhando em um componente, é necessário escrever um código legível claro.
SuperM