Comentários sobre código limpo versus documentação da classe


83

Estou tendo algumas discussões com meus novos colegas sobre comentários. Nós dois gostamos de Clean Code , e estou perfeitamente bem com o fato de que os comentários de código em linha devem ser evitados e que os nomes de classe e métodos devem ser usados ​​para expressar o que eles fazem.

No entanto, sou um grande fã de adicionar pequenos resumos de classe que tentam explicar o objetivo da classe e o que realmente representa, principalmente para que seja fácil manter o padrão de princípio de responsabilidade única . Também estou acostumado a adicionar resumos de uma linha a métodos que explicam o que o método deve fazer. Um exemplo típico é o método simples

public Product GetById(int productId) {...}

Estou adicionando o seguinte resumo do método

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary

Acredito que o fato de o método retornar nulo deve ser documentado. Um desenvolvedor que deseja chamar um método não precisa abrir meu código para ver se o método retorna nulo ou gera uma exceção. Às vezes, faz parte de uma interface, para que o desenvolvedor nem saiba qual código subjacente está sendo executado?

No entanto, meus colegas pensam que esses tipos de comentários são " cheiro de código " e que "comentários são sempre falhas" ( Robert C. Martin ).

Existe uma maneira de expressar e comunicar esses tipos de conhecimento sem adicionar comentários? Como sou um grande fã de Robert C. Martin, estou ficando um pouco confuso. Os resumos são iguais aos comentários e, portanto, sempre falham?

Esta não é uma pergunta sobre comentários em linha.


38
Robert Martin disse que "os comentários são sempre falhas"? Bem, então ele é um extremista marginal e deve ser tomado com uma pitada de sal. (Sim, eu estou ciente de que ele escreve como esta para fins retóricos, para obter a sua mensagem através de meu ponto é,. Por isso você deve .)
Kilian Foth

18
Os livros do tio Bob devem vir com um saco de 1 kg de sal ...
AK_

6
Se você estiver seguindo Robert Martin, a documentação para o caso nulo deve ser um teste. Ou seja, você deve ter um teste mostrando nesse caso o método pode retornar nulo. Como alternativa, como esse é Java, uma anotação @Nullable também seria melhor que o comentário.
Martin Epsz

15
@Bjorn Eu possuo uma cópia do Código Limpo e a li para cobrir mais de uma vez. Sim, o tio Bob prefere que o código seja auto-documentado, mas existem vários exemplos de comentários em seu próprio código no livro . O ponto é que se você se sente compelido a escrever um comentário, tente muito mudar o código em vez de adicioná-lo, mas não desaprove completamente os comentários (mesmo os comentários in-line).

6
O método deve ser chamado TryGetById e o comentário deve ser removido.
usr

Respostas:


116

Como outros já disseram, há uma diferença entre comentários de documentação da API e comentários in-line. Na minha perspectiva, a principal diferença é que um comentário in-line é lido junto com o código , enquanto um comentário de documentação é lido junto com a assinatura do que você estiver comentando.

Diante disso, podemos aplicar o mesmo princípio DRY . O comentário está dizendo a mesma coisa que a assinatura? Vejamos o seu exemplo:

Recupera um produto por seu ID

Esta parte apenas repete o que já vemos no nome GetByIdmais o tipo de retorno Product. Também levanta a questão de saber qual é a diferença entre "obter" e "recuperar" e qual o significado do código versus comentário nessa distinção. Portanto, é desnecessário e um pouco confuso. Na verdade, está atrapalhando a segunda parte realmente útil do comentário:

retorna nulo se nenhum produto foi encontrado.

Ah! Isso é algo que definitivamente não podemos saber ao certo apenas da assinatura e fornece informações úteis.


Agora dê um passo adiante. Quando as pessoas falam sobre comentários com o cheiro do código, a questão não é se o código atual precisa de um comentário, mas se o comentário indica que o código poderia ser melhor escrito, para expressar as informações no comentário. É isso que "cheiro de código" significa - não significa "não faça isso!", Significa "se você estiver fazendo isso, pode ser um sinal de que há um problema".

Portanto, se seus colegas lhe disserem que esse comentário sobre nulo é um cheiro de código, você deve simplesmente perguntar a eles: "Ok, como devo expressar isso?" Se eles têm uma resposta viável, você aprendeu alguma coisa. Se não, provavelmente matará as queixas deles.


Em relação a esse caso específico, geralmente o problema nulo é bem conhecido por ser difícil. Há uma razão pela qual as bases de código estão repletas de cláusulas de guarda, por que as verificações nulas são uma pré-condição popular para contratos de código, por que a existência de nula foi chamada de "erro de bilhão de dólares". Não existem muitas opções viáveis. Um popular, porém, encontrado em C # é a Try...convenção:

public bool TryGetById(int productId, out Product product);

Em outros idiomas, pode ser idiomático usar um tipo (geralmente chamado de algo como Optionalou Maybe) para indicar um resultado que pode ou não estar lá:

public Optional<Product> GetById(int productId);

De certa forma, essa postura anti-comentário nos levou a algum lugar: pelo menos pensamos se esse comentário representa um cheiro e quais alternativas podem existir para nós.

Se devemos realmente preferir isso à assinatura original, existe outro debate, mas pelo menos temos opções para expressar o código em vez de comentar o que acontece quando nenhum produto é encontrado. Você deve discutir com seus colegas quais dessas opções eles acham que é melhor e por quê e, espero, ajudar a seguir além das declarações dogmáticas gerais sobre comentários.


9
Ou o Linq-equivalente de Try..., ...OrDefaultque voltar default(T)se a cláusula levaria a um resultado vazio.
Bart van Nierop

4
Eu realmente aprecio a sua distinção entre inline-code-observações e comentários de documentação, e os exemplos dados :)
Rachel

2
Os possíveis valores de retorno de uma função devem ser evidentes por sua assinatura. O TryGetValuepadrão é uma maneira razoável de fazer isso em C #, mas a maioria das linguagens funcionais tem uma maneira melhor de representar um valor ausente. Leia mais aqui
AlexFoxGill 4/15/16

2
@BenAaronson: Se alguém quiser ter uma interface genérica capaz de suportar covariância, poderá usá-lo T TryGetValue(params, ref bool success)para qualquer tipo T ou T TryGetValue(params), com nulo indicando falha, para o tipo T com restrição de classe, mas o TryGetXXpadrão retornado boolé incompatível com covariância.
precisa

6
No Java 8, você pode retornar um Optional<Product>para indicar que pode não haver um Produto retornado do método.
Wim Deblauwe

102

As citações de Robert C. Martin são retiradas do contexto. Aqui está a citação com um pouco mais de contexto:

Nada pode ser tão útil quanto um comentário bem colocado. Nada pode confundir um módulo mais do que comentários dogmáticos frívolos. Nada pode ser tão prejudicial como um comentário antigo que propaga mentiras e desinformação.

Comentários não são como a Lista de Schindler. Eles não são "puro bem". De fato, os comentários são, na melhor das hipóteses, um mal necessário. Se nossas linguagens de programação fossem expressivas o suficiente, ou se tivéssemos o talento de manejar sutilmente essas linguagens para expressar nossa intenção, não precisaríamos muito de comentários - talvez nem um pouco.

O uso adequado dos comentários é para compensar nossa falha em nos expressar em código. Observe que eu usei a palavra falha. Eu quis dizer isso. Os comentários são sempre falhas. Devemos tê-los, porque nem sempre podemos descobrir como nos expressar sem eles, mas o uso deles não é motivo de comemoração.

Portanto, quando você se encontrar em uma posição em que precisa escrever um comentário, pense bem e veja se não há uma maneira de virar a mesa e se expressar em código. Toda vez que você se expressa em código, deve dar um tapinha nas costas. Toda vez que você escreve um comentário, deve fazer uma careta e sentir o fracasso de sua capacidade de expressão.

(Copiado daqui , mas a citação original é de Código Limpo: Um Manual do Artesanato em Software Ágil )

Como essa citação é reduzida em "Comentários sempre são falhas" é um bom exemplo de como algumas pessoas tiram uma citação sensata do contexto e a transformam em dogma estúpido.


A documentação da API (como javadoc) deve documentar a API para que o usuário possa usá-la sem precisar ler o código-fonte . Portanto, neste caso, a documentação deve explicar o que o método faz. Agora você pode argumentar que "Recupera um produto por seu ID" é redundante porque já está indicado pelo nome do método, mas as informações que nullpodem ser retornadas são definitivamente importantes para o documento, pois isso não é de forma alguma óbvio.

Se você deseja evitar a necessidade do comentário, é necessário remover o problema subjacente (que é o uso nullcomo um valor de retorno válido), tornando a API mais explícita. Por exemplo, você pode retornar algum tipo de Option<Product>tipo, para que a própria assinatura de tipo comunique claramente o que será retornado caso o produto não seja encontrado.

Mas, em qualquer caso, não é realista documentar completamente uma API apenas por meio de nomes de métodos e assinaturas de tipo. Use doc-comments para qualquer informação adicional não óbvia que o usuário deva conhecer. Imagine a documentação da API DateTime.AddMonths()na BCL:

O método AddMonths calcula o mês e o ano resultantes, levando em consideração os anos bissextos e o número de dias em um mês e, em seguida, ajusta a parte do dia do objeto DateTime resultante. Se o dia resultante não for um dia válido no mês resultante, o último dia válido do mês resultante será usado. Por exemplo, 31 de março + 1 mês = 30 de abril. A parte da hora do dia do objeto DateTime resultante permanece a mesma que esta instância.

Não há como você expressar isso usando apenas o nome e a assinatura do método! É claro que a documentação da sua aula pode não exigir esse nível de detalhe, é apenas um exemplo.


Comentários embutidos também não são ruins.

Bad comentários são ruins. Por exemplo, comentários que explicam apenas o que pode ser visto trivialmente no código, sendo o exemplo clássico:

// increment x by one
x++;

Comentários que explicam algo que poderia ser esclarecido renomeando uma variável ou método ou reestruturando o código, é um cheiro de código:

// data1 is the collection of tasks which failed during execution
var data1 = getData1();

Esse é o tipo de comentário contra o qual Martin se opõe. O comentário é um sintoma de uma falha ao escrever um código claro - nesse caso, para usar nomes auto-explicativos para variáveis ​​e métodos. O comentário em si não é, obviamente, o problema, o problema é que precisamos do comentário para entender o código.

Mas os comentários devem ser usados ​​para explicar tudo o que não é óbvio no código, por exemplo, por que o código foi escrito de uma certa maneira não óbvia:

// need to reset foo before calling bar due to a bug in the foo component.
foo.reset()
foo.bar();

Comentários que explicam o que um código excessivamente complicado faz também são cheiros, mas a correção não é proibir comentários, a correção é a correção do código! Na palavra real, código complicado acontece (espero apenas temporariamente até um refator), mas nenhum desenvolvedor comum escreve código limpo perfeito na primeira vez. Quando o código complicado acontece, é muito melhor escrever um comentário explicando o que ele faz do que não escrever um comentário. Esse comentário também facilitará a refatoração mais tarde.

Às vezes, o código é inevitavelmente complexo. Pode ser um algoritmo complicado ou pode comprometer a clareza do código por razões de desempenho. Novamente, comentários são necessários.


13
Também existe o caso em que seu código lida com uma situação que é complicada e nenhum código simples pode lidar com isso.
precisa saber é o seguinte

6
Bom ponto, gnasher. Isso geralmente ocorre quando você precisa otimizar algum código para obter desempenho.
precisa saber é o seguinte

9
Mesmo um comentário x++pode ser bom se for algo como "incrementar x por um, contornando se for UINT32_MAX"; qualquer pessoa que conheça a especificação da linguagem saberá que incrementar um uint32_tempacotamento será, mas sem o comentário, talvez não se saiba se esse empacotamento era uma parte esperada do algoritmo sendo implementado.
precisa

5
@ l0b0: Espero que você esteja brincando!
precisa saber é o seguinte

9
@ l0b0 Não existe código temporário. O código nunca é refatorado porque a empresa ficou satisfeita com o resultado e não aprovará o financiamento para corrigi-lo. Daqui a cinco anos, algum desenvolvedor júnior verá esse código, você não está mais usando o WizBug 4.0 desde que o substituiu pelo Bugtrocity v9, então "Bug123" não significa nada para ele. Ele agora pensa que é assim que o código permanente deve ser e passa a ser um péssimo desenvolvedor durante toda a sua carreira. Pense nas crianças. Não escreva código temporário.
precisa saber é o seguinte

36

Há uma diferença entre comentar e documentar seu código .

  • Comentários são necessários para manter o código posteriormente, ou seja, altere o próprio código.

    Comentários podem de fato ser percebidos como problemáticos. O ponto extremo seria dizer que eles sempre indicam um problema, seja no seu código (código muito difícil de entender) ou no idioma (idioma incapaz de ser expressivo o suficiente; por exemplo, o fato de o método nunca retornar nullpode ser expresso através de contratos de código em C #, mas não há como expressá-lo através de código em, digamos, PHP).

  • É necessária documentação para poder usar os objetos (classes, interfaces) que você desenvolveu. O público-alvo é diferente: não são as pessoas que manterão seu código e o mudarão sobre o qual estamos falando aqui, mas as pessoas que mal precisam usá- lo.

    Remover a documentação porque o código é claro o suficiente é insano, pois a documentação está aqui especificamente para possibilitar o uso de classes e interfaces sem a necessidade de ler milhares de linhas de código .


Sim, mas pelo menos parte do argumento de Martin é que, com práticas modernas de desenvolvimento, os testes são a documentação, não o próprio código. Supondo que o código esteja sendo testado com um sistema de teste no estilo BDD, por exemplo, specflow, os testes em si são uma descrição diretamente legível do comportamento do método ("dado um banco de dados de produtos quando GetById é chamado com o ID de um produto válido e, em seguida, o objeto Product apropriado é retornado [...] quando GetById é chamado com um ID de produto inválido e é retornado nulo "ou algo parecido com isto).
Jules

13

Bem, parece que seu colega lê livros, absorve o que eles dizem e aplica o que aprendeu sem pensar e sem considerar o contexto.

Seu comentário sobre o que a função faz deve ser tal que você possa jogar fora o código de implementação, li o comentário da função e posso escrever o substituto para a implementação, sem que algo dê errado.

Se o comentário não me informar se uma exceção é lançada ou se nada é retornado, não posso fazer isso. Além disso, se o comentário não diz que você se uma exceção é lançada ou se nulo é retornado, então onde quer que você chamar a função, você deve se certificar que seu código funciona corretamente se uma exceção é lançada ou nulo é retornado.

Então, seu colega está totalmente errado. E vá em frente e leia todos os livros, mas pense por si mesmo.

PS. Eu vi sua linha "às vezes faz parte de uma interface, então você nem sabe qual código está em execução". Mesmo apenas com funções virtuais, você não sabe qual código está em execução. Pior, se você escreveu uma classe abstrata, não há nenhum código! Portanto, se você tem uma classe abstrata com uma função abstrata, os comentários adicionados à função abstrata são a única coisa que um implementador de uma classe concreta precisa para guiá-los. Esses comentários também podem ser a única coisa que pode orientar um usuário da classe, por exemplo, se tudo o que você tem é uma classe abstrata e uma fábrica retornando uma implementação concreta, mas você nunca vê nenhum código-fonte da implementação. (E é claro que eu não deveria estar olhando o código fonte de uma implementação).


Eu não comento código há 10 anos. Comentários são inchaço, lixo. Atualmente, ninguém comenta código. Nós nos concentramos em códigos bem formados e nomeados, pequenos módulos, dissociação, etc. Isso torna seu código legível, não comentários. Os testes garantem que, se você jogar fora o código, nada sairá errado, não fará comentários. Os testes mostram como você usa o código que escreve, como os chama e por que eles estão lá em primeiro lugar. Você é velha demais e precisa aprender sobre testes e códigos limpos, meu amigo.
PositiveGuy

12

Existem dois tipos de comentários a serem considerados - os visíveis para as pessoas com o código e os usados ​​para gerar documentação.

O tipo de comentário ao qual o tio Bob está se referindo é do tipo que só é visível para as pessoas com o código. O que ele está defendendo é uma forma de DRY . Para uma pessoa que está olhando para o código-fonte, o código-fonte deve ser a documentação necessária. Mesmo no caso em que as pessoas têm acesso ao código fonte, os comentários nem sempre são ruins. Às vezes, os algoritmos são complicados ou você precisa entender por que você está adotando uma abordagem não óbvia para que outras pessoas não acabem quebrando seu código se tentarem corrigir um bug ou adicionar um novo recurso.

Os comentários que você está descrevendo são documentação da API. São coisas visíveis para as pessoas que usam sua implementação, mas que podem não ter acesso ao seu código-fonte. Mesmo que eles tenham acesso ao seu código-fonte, eles podem estar trabalhando em outros módulos e não estar olhando para o seu código-fonte. Essas pessoas acham útil ter essa documentação disponível em seu IDE enquanto escrevem seu código.


Sinceramente, nunca pensei em DRY se aplicar a códigos + comentários, mas faz todo o sentido. Mais ou menos como o exemplo "incremento X" na resposta de @ JacquesB.

7

O valor de um comentário é medido no valor da informação fornecida menos o esforço necessário para lê-lo e / ou ignorá-lo. Então, se analisarmos o comentário

/// <summary>
/// Retrieves a product by its id, returns null if no product was found.
/// </summary>

por valor e custo, vemos três coisas:

  1. Retrieves a product by its idrepete o que o nome da função diz, portanto, é um custo sem valor. Deve ser excluído.

  2. returns null if no product was foundé uma informação muito valiosa. Provavelmente reduz o tempo que outros codificadores terão que observar a implementação da função. Estou certo de que economiza mais leitura do que o custo de leitura que se apresenta. Deveria ficar.

  3. As linhas

    /// <summary>
    /// </summary>
    

    não carregue nenhuma informação. Eles são um custo puro para o leitor do comentário. Eles podem ser justificados se o seu gerador de documentação precisar deles, mas nesse caso você provavelmente deve pensar em outro gerador de documentação.

    Essa é a razão pela qual o uso de geradores de documentação é uma idéia discutível: eles geralmente exigem muitos comentários adicionais que não trazem informações ou repetem coisas óbvias, apenas por causa de um documento polido.


Uma observação que não encontrei em nenhuma das outras respostas:

Mesmo comentários que não são necessários para entender / usar o código podem ser muito valiosos. Aqui está um exemplo:

//XXX: The obvious way to do this would have been ...
//     However, since we need this functionality primarily for ...
//     doing this the non-obvious way of ...
//     gives us the advantage of ...

Provavelmente muito texto, completamente desnecessário para entender / usar o código. No entanto, explica uma razão pela qual o código parece com a sua aparência. Ele interrompe as pessoas que olham para o código, se perguntam por que não é feito da maneira óbvia e começam a refatorar o código até perceberem por que o código foi escrito assim em primeiro lugar. E mesmo que o leitor seja esperto o suficiente para não pular para a refatoração direta, ele ainda precisará descobrir por que o código tem a aparência que ele tem antes de perceber que ele deve permanecer do jeito que está. Esse comentário poderia literalmente economizar horas de trabalho. Assim, o valor é superior ao custo.

Da mesma forma, os comentários podem comunicar as intenções de um código, em vez de apenas como ele funciona. E eles podem pintar o quadro geral que geralmente se perde nos mínimos detalhes do próprio código. Como tal, você tem razão em ser a favor dos comentários da classe. Eu valorizo ​​mais os comentários da classe se eles explicarem a intenção da classe, como ela interage com outras classes, como ela deve ser usada etc. etc. Infelizmente, eu não sou um grande autor de tais comentários ...


2
Uau - mude seu gerador de documentos porque requer algumas linhas extras de html para analisar? Não vamos.
precisa saber é o seguinte

2
@corsiKa YMMV, mas eu prefiro um gerador de documentação que reduz os custos nos comentários ao mínimo. Claro, eu também prefiro ler um arquivo de cabeçalho bem escrito do que uma documentação doxygen que está fora de sincronia com o código real. Mas, como eu disse, YMMV.
precisa saber é

4
Mesmo que o nome de um método descreva seu objetivo de maneira brilhante, repetir esse objetivo usando linguagem natural pode facilitar a leitura de alguém para associá-lo a quaisquer ressalvas a seguir. Uma reformulação do que está descrito no nome será breve o suficiente para que, mesmo que o valor seja baixo, o custo também seja baixo. Discordo, portanto, da primeira parte do seu post. +1, no entanto, para a segunda parte. A documentação de abordagens alternativas avaliadas e rejeitadas pode ser extremamente valiosa, mas essas informações raramente recebem a atenção que merecem.
precisa

GetByIdlevanta a questão, o que é id e também obtém o que de onde. O comentário da documentação deve permitir que o ambiente de desenvolvimento exiba resposta a essas perguntas. A menos que seja explicado em outro lugar nos comentários do documento do módulo, também seria um lugar para dizer por que alguém obteria o ID de qualquer maneira.
Hyde

Comentários, regras de código limpo (auto-descritivo), TDD (recebendo feedback frequentemente e feedback sobre o seu design) e regras de testes (dão confiança e comportamento ao documento)! TESTES pessoas TESTES. Ninguém aqui está falando sobre isso. acordar
PositiveGuy

4

Código não comentado é código incorreto. É um mito generalizado (se não universal) de que o código pode ser lido da mesma maneira que, digamos, em inglês. Ele deve ser interpretado e para qualquer código, exceto o mais trivial, que leva tempo e esforço. Além disso, todo mundo tem um nível diferente de capacidade de ler e escrever qualquer idioma. As diferenças entre o autor e os estilos e recursos de codificação do leitor são fortes barreiras à interpretação precisa. Também é um mito que você pode derivar a intenção do autor a partir da implementação do código. Na minha experiência, raramente é errado adicionar comentários extras.

Robert Martin et al. considere um "mau cheiro" porque pode ser que o código seja alterado e os comentários não. Eu digo que é uma coisa boa (exatamente da mesma maneira que um "mau cheiro" é adicionado ao gás doméstico para alertar o usuário sobre vazamentos). A leitura dos comentários fornece um ponto de partida útil para a interpretação do código real. Se eles corresponderem, você terá maior confiança no código. Se eles diferem, você detectou um cheiro de aviso e precisa investigar mais. A cura para um "mau cheiro" não é remover o cheiro, mas selar o vazamento.


2
Dado que você é um autor inteligente e o texto é para o benefício de um público inteligente; Você desenha a linha usando o bom senso. Obviamente, como está, o exemplo é idiota, mas isso não quer dizer que pode não haver uma boa razão para esclarecer com um comentário por que o código inclui um i ++ nesse ponto.
Vince O'Sullivan

8
i++; // Adjust for leap years.
Vince O'Sullivan

5
"Robert Martin et al. Consideram um" mau cheiro ", porque pode ser que o código seja alterado e os comentários não." Isso é apenas parte do cheiro. O pior do cheiro vem da idéia de que o programador decidiu não tentar escrever o código de maneira mais descritiva e, em vez disso, optou por "selar o vazamento" com um comentário. Sua afirmação é que, em vez de dar um tapa em um comentário "// ajuste para anos bissextos", é provável que você deva ter um método "AdjustForLeapYears ()" no próprio código (ou algo semelhante). A documentação vem na forma de testes que exercitam a lógica do ano bissexto.
Eric Rei

3
Eu consideraria adicionar uma chamada de método para substituir uma única linha de código por um excesso de comentários, principalmente porque o nome do método é, na verdade, apenas um comentário que rotula um pedaço de código e não garante uma melhor precisão da documentação. (Se essa linha ocorreu em dois ou mais lugares, em seguida, a introdução de uma chamada de método seria, naturalmente, ser exatamente a solução certa.)
Vince O'Sullivan

11
@ Jay O motivo é que tornar suas abstrações explícitas (introduzindo métodos, por exemplo) é a regra. Caso contrário, você pode acabar com um método que tem uma linha. Deixe-me parafrasear a regra arbitrária real : "Use as estruturas da sua linguagem de programação (normalmente métodos e classes) para introduzir abstrações, a menos que a implementação dessa abstração possa ser expressa como uma linha de código; nesse caso, especifique a abstração na linguagem natural adicionando um comentário."
Eric

3

Em alguns idiomas (F # por exemplo), todo esse comentário / documentação pode realmente ser expresso na assinatura do método. Isso ocorre porque, em F #, nulo geralmente não é um valor permitido, a menos que seja especificamente permitido.

O que é comum no F # (e também em várias outras linguagens funcionais) é que, em vez de nulo, você usa um tipo de opção Option<T>que pode ser Noneou Some(T). O idioma entenderia isso e forçaria você a (ou avisará se não o fizer) corresponder nos dois casos ao tentar usá-lo.

Por exemplo, em F #, você poderia ter uma assinatura parecida com esta

val GetProductById: int -> Option<Product>

E isso seria uma função que usa um parâmetro (um int) e, em seguida, retorna um produto ou o valor Nenhum.

E então você poderia usá-lo assim

let product = GetProduct 42
match product with
| None -> printfn "No product found!"
| Some p -> DoThingWithProduct p

E você receberá avisos do compilador se não corresponder aos dois casos possíveis. Portanto, não há como obter exceções de referência nula (a menos que você ignore os avisos do compilador, é claro), e você sabe tudo o que precisa apenas olhando a assinatura da função.

Obviamente, isso requer que sua linguagem seja projetada dessa maneira - o que muitas linguagens comuns como C #, Java, C ++ etc. Portanto, isso pode não ser útil para você na sua situação atual. Mas (espero) é bom saber que existem idiomas por aí que permitem expressar esse tipo de informação de maneira estaticamente tipada, sem recorrer a comentários etc. :)


1

Há algumas excelentes respostas aqui e não quero repetir o que dizem. Mas deixe-me adicionar alguns comentários. (Sem trocadilhos.)

Há muitas declarações que pessoas inteligentes fazem - sobre desenvolvimento de software e muitos outros assuntos, suponho - que são conselhos muito bons quando entendidos em contexto, mas que pessoas tolas que saem de contexto ou se aplicam em situações inapropriadas ou levam a extremos ridículos.

A idéia de que o código deve ser auto-documentado é uma excelente ideia. Mas na vida real, existem limitações na praticidade dessa idéia.

Um problema é que o idioma pode não fornecer recursos para documentar o que precisa ser documentado de forma clara e concisa. À medida que as linguagens de computador melhoram, isso se torna cada vez menos problemático. Mas não acho que tenha desaparecido completamente. Na época em que escrevi na assembler, fazia muito sentido incluir um comentário como "preço total = preço de itens não tributáveis ​​mais preço de itens tributáveis ​​mais preço de itens tributáveis ​​mais preço de itens tributáveis ​​* taxa de imposto". Exatamente o que estava em um registro em um dado momento não era necessariamente óbvio. Foram necessárias várias etapas para executar uma operação simples. Etc. Mas se você estiver escrevendo em uma linguagem moderna, esse comentário seria apenas uma reformulação de uma linha de código.

Sempre fico irritado quando vejo comentários como "x = x + 7; // adicione 7 a x". Como, uau, obrigado, se eu tivesse esquecido o que um sinal de mais significa que poderia ter sido muito útil. Onde eu realmente posso estar confuso é em saber o que é "x" ou por que foi necessário adicionar 7 a ele neste momento específico. Esse código pode ser auto-documentado, dando um nome mais significativo a "x" e usando uma constante simbólica em vez de 7. Como se você tivesse escrito "total_price = total_price + MEMBERSHIP_FEE;", um comentário provavelmente não será necessário. .

Parece ótimo dizer que o nome de uma função deve informar exatamente o que uma função faz, para que quaisquer comentários adicionais sejam redundantes. Tenho boas lembranças da época em que escrevi uma função que verificava se um número de item estava em nossa tabela de itens do banco de dados, retornando verdadeiro ou falso, e que chamei de "ValidateItemNumber". Parecia um nome decente. Então alguém apareceu e modificou essa função para também criar um pedido para o item e atualizar o banco de dados, mas nunca mudou o nome. Agora o nome era muito enganador. Parecia que fazia uma coisa pequena, quando realmente fazia muito mais. Mais tarde, alguém chegou a validar o número do item e fez isso em outro lugar, mas ainda não mudou o nome. Portanto, mesmo que a função agora não tenha nada a ver com a validação de números de itens,

Mas, na prática, muitas vezes é impossível para um nome de função descrever completamente o que a função faz sem que o nome da função seja tão longo quanto o código que a compõe. O nome nos dirá exatamente quais validações são executadas em todos os parâmetros? O que acontece em condições de exceção? Soletrar todas as ambiguidades possíveis? Em algum momento, o nome ficaria tão longo que se tornaria confuso. Eu aceitaria String BuildFullName (String firstname, String lastname) como uma assinatura de função decente. Mesmo que isso não explique se o nome é expresso "primeiro sobrenome" ou "sobrenome, primeiro" ou alguma outra variação, o que faz se uma ou ambas as partes do nome estiverem em branco, se impuser limites ao comprimento combinado e o que faz se for excedido,

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.