1. Programação limpa em Java
Módulo 01 - Nomenclatura, Funções e Comentários
Data: 17/07/2012
Formador: Marcio Romualdo da Silva
Email: marcioromualdo@yahoo.com.br
1
2. Objetivos
Geral:
No final da sessão o formando será capaz de escrever código Java de forma
limpa, clara e de fácil manutenção.
Específicos:
No final da sessão o formando será capaz de, na linguagem Java:
Criar variáveis com nomes significativos, sem precisar de comentários.
Criar funções com nomes significativos, sem precisar de comentários.
Escrever funcões pequenas com apenas uma única intenção.
Escrever comentários que ajudam na leitura clara do código.
Identificar os comentários que atrapalham a leitura clara do código.
2
4. O que é um código limpo?
Simples e direto
Legível (readable)
Elegante e eficiênte
Com mínimas dependências para fácil manutenção
Com nomes significativos
Sem duplicação
4
5. Por quê você escreveu código sujo?
Estava tentando ir mais rápido? Estava com pressa?
Seu chefe poderia ficar zangado se você tomasse tempo para limpar o código?
Estava cansado de trabalhar no projeto e queria acabar logo?
Havia outras coisas havia prometido terminar e o tempo era curto?
5
6. O custo total da sujeira
Assim que a sujeira aumenta, a produtividade da equipa diminui, aproximando do
zero.
6
7. Nomes Significativos
Use nomes que revelem a sua intenção!
Compare:
int d; // elapsed time in days
Com:
int elapsedTimeInDays;
7
8. Nomes Significativos
Use nomes que revelem a sua intenção!
Qual o propósito deste código?
public List getThem() {
List list1 = new ArrayList();
for (int[] x : theList) {
if (x[0] == 4) {
list1.add(x);
}
}
return list1;
}
8
9. Nomes Significativos
Nós podems melhorar o código consideravelmente:
public List getFlaggedCells() {
List flaggedCells = new ArrayList();
for (int[] cell : gameBoard) {
if (cell[STATUS_VALUE] == FLAGGED) {
flaggedCells.add(cell);
}
}
return flaggedCells;
}
9
10. Nomes Significativos
Faça distinções significativas entre as variáveis!
Nomeação usando números em série (a1, a2, .. aN) é o oposto de nomeação intencional.
public static void copyChars(char a1[], char a2[]) {
for (int i = 0; i < a1.length; i++) {
a2[i] = a1[i];
}
}
10
11. Nomes Significativos
A função se lê muito melhor quando “source” e “destination” são usados como
argumentos.
public static void copyChars(char source[], char destination[]) {
for (int i = 0; i < source.length; i++) {
destination[i] = source[i];
}
}
11
12. Nomes Significativos
Use nomes pronunciáveis!
Compare:
class DtaRcrd102 {
private Date genymdhms;
private Date modymdhms;
private final String pszqint = "102";
/* ... */
}
Com: Conversa inteligente: “Olá, João,
class Customer { dê uma olhada nos dados deste
private Date generationDate; cliente! A data de geração do
private Date modificationDate; está carregada com a data de
private final String recordId = "102"; amanhã! Como isto é possível?”
/* ... */
}
12
13. Nomes Significativos
Use nomes fáceis de encontrar (Searchable Names)!
Se uma variável deve ser usada em vários lugares no código, dê um nome de fácil procura.
Compare:
int s = 0;
for (int j=0; j<10; j++) {
s += (t[j])/5;
}
Com:
int NUMBER_TASKS = 10;
int sum = 0;
for (int j=0; j < NUMBER_TASKS; j++) {
sum += (taskEstimate[j]) / WORK_DAYS_PER_WEEK;
}
13
14. Nomes Significativos
Programadores Java não necessitam de notações hungaras (sName, iAge,
etc) nem de colocarem qualquer prefixo nas variáveis.
Compare:
public class Part {
private String description;
void setDescription(String str_description) {
description = str_description;
}
}
Com:
public class Part {
String description;
void setDescription(String description) {
this.description = description;
}
}
14
15. Funções
As funções devem ser pequenas!
Transparente óbvias!
Sem duplicação!
Fazem apenas uma coisa!
Têm nomes descritivos e significativos!
Não tenha medo de escolher um nome longo!
Um nome longo e descritivo é melhor que um nome curto e enigmático.
15
16. Funções – Número ideial de argumentos
O número ideial de argumentos em uma função é zero.
Depois vem um, seguido por dois.
Três argumentos deverão ser evitados quando possível.
Mais de quatro argumentos requerem uma justificação especial.
Por quê?
Argumentos são difíceis de ponto de vista dos testes. Imaginem a dificuldade em escrever
todos os casos de testes para assegurar que as várias combinações dos argumentos trabalham
corretamente.
16
17. Funções - Argumentos booleanos (true / false)
Argumentos booleanos são feios. Passando um booelan em uma função é uma
prática terrível.
Ele imediatamente complica a assinatura do método, proclamando em voz alta
que a função faz mais de uma coisa:
Faz um coisa se o argumento for true e outra coisa se o argumento false!
Neste caso, nós devemos dividir a função em duas!
17
18. Funções - Como escrever funções
Quando eu escrevo funções, elas saem longas e complicadas.
Elas têm um monte de “Ifs“ e “loops”.
Os nomes são arbitrários, e existe duplicação de código.
Então eu refino o código,
dividindo em mais funções (que só fazem uma coisa),
trocando os nomes,
eliminando a duplicação.
18
19. Comentários
Comentários mentem. Nem sempre, e não intencionalmente, mas com muita
frequência.
A razão é simples. Programadores não podem realisticamente mantê-los!
Uma das razões para escrever comentários é ver um código
confuso e
desorganizado . Então pensamos: vamos escrever um comentário!
Antes de gastar tempo com comentários no código, é melhor limpá-lo, reescrevendo-o!
19
20. Comentários - Explique-se no código
Compare:
// Check to see if the employee is eligible for full benefits
if ((employee.flags & HOURLY_FLAG) && (employee.age > 65)) {
…
}
Com:
if (employee.isEligibleForFullBenefits()) {
…
}
Leva poucos segundos de pensamento para sabermos a intenção do código.
20
21. Comentários - Bons comentários
Alguns comentários são necessários ou benéficos.
-- Comentários Legais (Legal Comments)
Algumas vezes a nossa empresa nos força a escrever certos comentários por razões legais.
// Copyright (C) 2003,2004,2005 by Infosistema, Inc. All rights reserved.
// Released under the terms of the GNU General Public License version 2 or later.
21
22. Comentários - Bons comentários
-- Comentários de explicação da intenção
// This is our best attempt to get a race condition
// by creating large number of threads.
for (int i = 0; i < 25000; i++) {
WidgetBuilderThread widgetBuilderThread =
new WidgetBuilderThread(widgetBuilder, text, parent, failFlag);
Thread thread = new Thread(widgetBuilderThread);
thread.start();
}
Podem não concordar com a solução do programador, mas ao menos sabem o que
ele estava tentando fazer.
22
23. Comentários - Bons comentários
-- Comentários de Clarificação
Algumas vezes ajudam a traduzir o significado de códigos obscuros.
assertTrue(a.compareTo(b) == 0); // a == b
assertTrue(a.compareTo(b) != 0); // a != b
É um risco substancial, é claro, que os comentários de clarificação estejam
incorretos. Então tomem cuidado para que sejam precisos!
23
24. Comentários - Bons comentários
-- Comentários TODO (para fazer)
Algumas vezes é razoável deixar notas em forma de comentários //TODO
São tarefas deviam ter sido feitas, mas por algum motivo não pode ser feita no momento.
Pode ser um lembrete para apagar um recurso substituído (deprecated)
Pode ser um lembrete para alguém olhar para o problema
(Neste caso, pode-se também usar //FIXME)
Pode ser um lembrete para fazer um mudança que está pendente de um evento planeado.
-- Comentários Javadocs em bibliotecas públicas (Public APIs)
Não existe nada mais útil e satisfatório que um bons comentários javadocs em bibliotecas
públicas!
24
25. Comentários - Maus comentários
-- Comentários de ruído (Noise Comments)
Apenas reafirmam o óbvio e não fornecem novas informações.
/** The day of the month. */
private int dayOfMonth;
/**
* Returns the day of the month.
*
* @return the day of the month.
*/
public int getDayOfMonth() {
return dayOfMonth;
}
25
26. Comentários - Maus comentários
-- Comentários com atribuições Bylines
/* Created by Marcio Silva */
String name = “test“;
/* Added by Marcio Silva */
If (!customer.equals(“”)) {
Hoje em dia, temos ótimos controladores de versões (CVS, SVN, GIT, etc)
que irão nos lembrar quem alterou o código!
26
27. Comentários - Maus comentários
-- Códigos antigos comentados (Commented-Out Code)
InputStreamResponse response = new InputStreamResponse();
response.setBody(formatter.getResultStream(), formatter.getByteCount());
// InputStream resultsStream = formatter.getResultStream();
// StreamReader reader = new StreamReader(resultsStream);
Outras pessoas que vêm o código comentário não têm coragem de apagá-lo.
Elas pensam que eles estão lá por algum motivo.
São importantes?
Deixaram paralembrar uma mudança iminente ?
Ou alguém comentou anos atrás e simplesmente não limpou ?
Hoje em dia, temos ótimos controladores de versões (CVS, SVN, GIT, etc) que irão nos
lembrar as alterações no código!
27
28. Comentários - Maus comentários
-- Comentários com muita informação (Too Much Information)
Não coloquem discussões históricas ou irrelevante s em seus comentários.
Alguém lendo o código não tem necessidade ler toda esta informação.
/*
RFC 2045 - Multipurpose Internet Mail Extensions (MIME)
Part One: Format of Internet Message Bodies
section 6.8. Base64 Content-Transfer-Encoding
The encoding process represents 24-bit groups of input bits as output
strings of 4 encoded characters. Proceeding from left to right, a
24-bit input group is formed by concatenating 3 8-bit input groups.
These 24 bits are then treated as 4 concatenated 6-bit groups, each
of which is translated into a single digit in the base64 alphabet.
When encoding a bit stream via the base64 encoding, the bit stream
must be presumed to be ordered with the most-significant-bit first.
That is, the first bit in the stream will be the high-order bit in
the first 8-bit byte, and the eighth bit will be the low-order bit in
the first 8-bit byte, and so on.
28
*/
29. Síntese
Para termos um código limpo em Java, devemos:
Criar variáveis com nomes significativos
Criar funções com nomes significativos
Escrever funções pequenas com apenas uma intenção
Escrever apenas bons comentários que ajudam na leitura clara do código
29
30. Próxima Sessão?
Módulo 02
Formatar o código fonte de maneira organizada e estruturada
Identificar as diferenças entre objetos e estrutura de dados
Criar classes limpas e de fácil leitura
30
32. Muito Obrigado!
Formador: Marcio Romualdo da Silva
Email: marcioromualdo@yahoo.com.br
32
Notes de l'éditeur
Assim que a produtividade diminui, a gestão faz somente um coisa que eles podem: Adicionam mais pessoas no projeto na esperança de aumentar a produtividade. Mas as novas pessoas não conhecem o design do sistema. Toda a gente fica debaixo de uma enorme pressão para aumentar a produtividade.
One way to know that a function is doing more than “one thing” is if you can extract another function from it with a name that is not merely a restatement of its implementation.
Quando uma função parece precisar de mais do que dois ou três argumentos, é provável que alguns desses argumentos deve ser envolvido em uma classe própria. Compare: Circle makeCircle(double x, double y, double radius); Com: Circle makeCircle(Point center, double radius);
The method call render(true) is just plain confusing to a poor reader. Mousing over the call and seeing render(boolean isSuite) helps a little, but not that much. We should have split the function into two: renderForSuite() and renderForSingleTest().
We know it’s a mess. So we say to ourselves, “Ooh, I’d better comment that!” No! You’d better clean it! Rather than spend your time writing the comments that explain the mess you’ve made, spend it cleaning that mess.
In many cases it’s simply a matter of creating a function that says the same thing as the comment you want to write.
Seja o que for um TODO, não é desculpa para deixar um mau código no sistema.
Sometimes we see comments that are nothing but noise. They restate the obvious and provide no new information.
Those systems will remember the code for us. We don’t have to comment it out any more. Just delete the code. We won’t lose it. Promise.
Alguém lendo o seu código não tem necessidade ler toda esta informação.