Sem Comentários. E agora?

Tradicionalmente, considera-se uma boa prática comentar o código. Há algum tempo, tem-se revisto este conceito. Na Liferay, por exemplo, seguimos uma política de não comentar código. Pessoalmente, sou um entusiasta desta filosofia. Mas não quero apresentar ou defender esta estratégia: há muito material bom sobre isto. Quero discutir uma questão em aberto.

Quem comenta quer transmitir alguma informação importante. Que informação é essa? E, mais importante ainda, onde podemos registrá-la? Vejamos algumas alternativas.

O que essas linhas fazem?

Os nomes de funções são excelentes para explicar o que o código faz. Se um bloco de código precisa de um comentário, considere extraí-lo para uma função ou classe. O nome da entidade já esclarecerá seu propósito.

Observe, por exemplo, as linhas abaixo, retiradas desta classe de testes:

Assert.assertNotNull(recurrence);
Assert.assertNull(recurrence.getUntilJCalendar());
Assert.assertEquals(0, recurrence.getCount());Code language: CSS (css)

Essas linhas verificam se a RRule de um evento tem certas propriedades: ela deve existir, ter um “untilCalendar nulo e uma contagem de zero.

Os conceitos são complexos; eu mesmo me confundiria ao reler estes asserts. Um comentário poderia explicá-los. Mas este commit já esclareceu tudo ao mover essas linhas para um método e invocá-lo:

assertRepeatsForever(recurrence);

Aquelas asserções verificavam se o evento se repete eternamente! Nenhum comentário foi necessário — felizmente, pois estes asserts estavam em vários testes.

O que está acontecendo?

Se o comentário iria explicar algo relevante em tempo de execução, considere transformá-lo em uma mensagem de log! Note o exempo abaixo.

if (Validator.isBlank(serviceAccountKey)) {
	// If no credentials are set for GCS Store, the library will
	// use Application Default Credentials.
	_googleCredentials =
		ServiceAccountCredentials.getApplicationDefault();
}
else {
	_googleCredentials = ServiceAccountCredentials.fromStream(
		new ByteArrayInputStream(serviceAccountKey.getBytes()));
}Code language: JavaScript (javascript)

Este comentário pode ser relevante para quem lê o código. Contudo, seria crucial para alguém investigando um problema de autenticação. Por isso, na prática, escolhi logar uma mensagem:

if (Validator.isBlank(serviceAccountKey)) {
	if (_log.isInfoEnabled()) {
		_log.info(
			"No credentials set for GCS Store. Library will use " +
				"Application Default Credentials.");
	}

	_googleCredentials =
		ServiceAccountCredentials.getApplicationDefault();
}
else {
	_googleCredentials = ServiceAccountCredentials.fromStream(
		new ByteArrayInputStream(serviceAccountKey.getBytes()));
}Code language: JavaScript (javascript)

Por que este código está aqui?

Comentários para explicar por que algumas linhas estão ali também são comuns. Um local melhor para compartilhar essas informações são as mensagens de commits.

Estes dias, por exemplo, me pediram para ajudar com um código em que trabalhei anos atrás. Lendo uma JSP — lembre-se, anos atrás — eu encontrei essas linhas:

<liferay-portlet:renderURL portletName="<%= KaleoDesignerPortletKeys.KALEO_DESIGNER %>" var="viewURL">
	<portlet:param name="mvcPath" value="/designer/view_kaleo_definition_version.jsp" />
	<portlet:param name="redirect" value="<%= currentURL %>" />
	<portlet:param name="name" value="<%= kaleoDefinitionVersion.getName() %>" />
	<portlet:param name="draftVersion" value="<%= kaleoDefinitionVersion.getVersion() %>" />
</liferay-portlet:renderURL>Code language: HTML, XML (xml)

Esta tag está gerando uma URL para ser utilizada em outro lugar. Mas meus olhos treinados acharam estranho aquele parâmetro portletName. Este valor costumar ser definido automaticamente.

Um git blame esclareceu tudo, quando encontrei este commit. A mensagem é clara:

LPS-74977 / LPS-73731 By making the render URL explicitly use the Kaleo Designer name, it will be valid when rendered in another portlet.

Entendi! Este código provavelmente vai ser invocado por algum outro portlet. Neste caso, o valor seria automaticamente setado pela outra aplicação, e por alguma razão queremos evitar isso.

(Por esta razão, aliás, prefiro commits pequenos: eles facilitam descobrir a razão de trechos de código bem específicos. É como se todas as linhas de código tivessem um comentário! Não é uma posição unânime, porém: há quem prefira commits maiores.)

A razão da linha foi esclarecida. Mas por que ela pode ser invocada de outra aplicação? Isto não é usual…

Por que esta mudança foi feita?

Um código bem escrito explica como algo foi implementado. A mensagem de commit esclarece o porquê, mas em um contexto local. Como explicar a motivação mais ampla por trás de um código sem recorrer a comentários?

Os tíquetes do issue tracker são excelentes para isto. Normalmente escritos para guiar o desenvolvimento, esses documentos ajudam demais na interpretação do código. Se adicionarmos a chave do tíquete à mensagem de commit, podemos rastrear as razões.

Voltando ao exemplo acima. Descobrimos que uma linha permite usar o mesmo código em vários portlets. Mas isso raramente é necessário. Por que precisamos reutilizar o código neste caso? Por sorte, a mensagem menciona dois tíquetes. Fui verificar o mais antigo; cheguei a LPSA-64324:

[Information Architecture] EE – As a portal admin, I would like to access all workflow portlets from the control panel section under the same tab.

O título já ajuda, e o texto esclarece de vez. Por razões de usabilidade, três aplicações diferentes passaram a aparecer em abas de um mesmo portlet. Faz todo sentido!

Os comentários que a gente gosta

É importante destacar que tentamos evitar comentários desorganizados, que se entrelaçam no código e tentam explicar trechos difíceis de entender. Há vários comentários, frequentemente com formatos padronizados, que não atrapalham a leitura. Um exemplo óbvio são os cabeçalhos de copyright.

Outra maneira de usar comentários efetivamente é a programação letrada. Neste estilo de programação, os comentários são a estrela do show: o código-fonte contem mais prosa do que código executável. Isto é útil quando explicar o algoritmo é mais importante do que lê-lo, como em pesquisas acadêmicas e análise de dados. Não por acaso, é o paradigma de ferramentas populares como Jupyter Notebook e Quarto.

Mais relevante ainda, ferramentas como Javadoc, JSDoc, Doxygen etc. leem comentários em um formato específico para gerar documentação. Estes comentários não afetam a legibilidade. Pelo contrário: javadocs são ótimos para explicar como usar estas entidades. Combinados com ferramentas como meu querido Doctest, temos até garantias de acurácia e atualidade!

Um mundo de possibilidades

Esses são apenas alguns exemplos de alternativas aos comentários. Há muitas outras opções, como wikis, blogs. Já encontrei a explicação para um código que escrevi no Stack Overflow! Podemos pensar em ainda mais soluções para atender a diferentes necessidades. O ponto principal é que, tendo estas ferramentas à nossa disposição, adicionar comentários diretamente ao código torna-se desnecessário.

Naturalmente, evitar comentários é apenas uma das formas para se escrever código legível. Comentários não são proibidos; de fato, há estratégias que podem torná-los eficazes. No entanto, na minha experiência, comentar indisciplinadamente leva a piores resultados, e essas técnicas ajudam a documentar informações importantes que não cabem diretamente no código.

Você é um adepto da estratégia “sem comentários”? Se sim, que outros meios você usa para transmitir infirmações? Se não, como você faz para ter comentários efetivos? Que tipo de comentário você não vê sendo substituído por essas abordagens? Adoraria escutar suas opiniões.

Post Revisions:

Post a Comment

Your email is never shared. Required fields are marked *

*
*

%d bloggers like this: