Clean Code
-
Upload
renato-chencinski -
Category
Technology
-
view
204 -
download
1
description
Transcript of Clean Code
1) O QUE É CÓDIGO LIMPO
- Michael Feathers - Clean code always looks like it was written by someone who cares.
- Ron Jeffries / Kent Beck
1) Run all tests
2) No duplication
3) Express design ideas
4) Minimizes # of entities (classes, methods, ..)
1) O QUE É CÓDIGO LIMPO
- Ward Cunningham - Each routine you read is pretty much what you expected
1) O QUE É CÓDIGO LIMPO
Paradigma: Razão de tempo lendo código vs escrevendo: > 10:1
- Fazer software fácil de ler é fazer ele fácil de escrever
- Código enxuto, sem textos poluindo que atrasem entendimento
- Poucos comentários
- Classes / funções pequenas
- Níveis de abstração coerentes com contexto
- Código expressivo
COMO MEDIR SE CÓDIGO É LIMPO?
COMENTÁRIOSComentário desatualizado
/**
* Always returns true.
*/
public boolean isAvailable() {
return false;
}
//private instance variable for storing age
public static int age;
http://stackoverflow.com/questions/184618/what-is-the-best-comment-in-source-code-you-have-ever-encountered?page=1&tab=votes#tab-top
COMENTÁRIOSComentário inusitado
// somedev1 - 6/7/02 Adding temporary tracking of Login screen
// somedev2 - 5/22/07 Temporary my ass
COMENTÁRIOSComentários úteis
return 1; # returns 1
i++; // increase i by 1
FÁCIL LEITURA E ENTENDIMENTOGlobalConfiguration.Configuration.Filters.Add(new HandleAndLogErrorAttribute());
ViewEngines.Engines.RemoveAt(1);
Domains = Empresa.SelectAllURLs(new Context()).ToDictionary(e => e.Dominio, e => new ViewTema() { ViewNome = e.ViewNome, Tema = e.Tema });
ViewEngines.Engines.Add(new CustomViewEngine(Domains));
FÁCIL LEITURA E ENTENDIMENTOGlobalConfiguration.Configuration.Filters.Add(new HandleAndLogErrorAttribute());
ViewEngines.Engines.RemoveAt(1);
Domains = ObtemViewsETemasDaEmpresa();
ViewEngines.Engines.Add(new CustomViewEngine(Domains));
FÁCIL LEITURA E ENTENDIMENTO
public static KeyValuePair<string, ViewTema> FindDominio(Dictionary<string, ViewTema> dominios, Uri url) {
return dominios.FirstOrDefault(e => e.Key.Split(';').FirstOrDefault(s => String.Equals(s, url.Authority, StringComparison.CurrentCultureIgnoreCase)) != null);
}
FÁCIL LEITURA E ENTENDIMENTO
[Código de função gigante]
2) NOMES SIGNIFICATIVOS
- Revelam intenção
- int elapsedTimeInDays
- Usar constantes para explicar valores
- cell[0] -> cell[STATUS_VALUE]
- Refactor nos nomes sempre para deixar mais significativo
2) NOMES SIGNIFICATIVOS
public List<int[]> getThem() {
List<int[]> list1 = new ArrayList<int[]>();
for (int[] x : theList)
if (x[0] == 4)
list1.add(x);
return list1;
}
2) NOMES SIGNIFICATIVOS
public List<Cell> getFlaggedCells() {
List<Cell> flaggedCells = new ArrayList<Cell>();
for (Cell cell : gameBoard)
if (cell.isFlagged())
flaggedCells.add(cell);
return flaggedCells;
}
3) FUNÇÕES
PEQUENAS
3) FUNÇÕES
PEQUENAS
3) FUNÇÕES (PEQUENAS!)
3) FUNÇÕES (PEQUENAS!)
3) FUNÇÕES (PEQUENAS!)
3) FUNÇÕES (PEQUENAS!)
3) FUNÇÕES (PEQUENAS!)
- Empírico
- Anos 80 - não maior que altura da tela (24 linhas)
- 20 linhas no máximo do máximo
- Blocos e indentações
- Por ser pequena, if / while / etc terão 1 ou 2 linhas
- Indentação 1 ou 2
3) FUNÇÕES (PEQUENAS!)
Funções devem fazer UMA coisa.
Devem fazer isso bem.
Devem fazer apenas isso.
- O que é 1 coisa?
- Apenas 1 nível de abstração abaixo do nome da função.
- Consegue descrever em uma sentença.
3) FUNÇÕES (PEQUENAS!)
3) FUNÇÕES (PEQUENAS!)
- Níveis de abstração:
- Alto - getHtml
- Médio - String pagePath = PathParser.render(pagePath)
- Baixo - append("\n")
- Misturar níveis confunde, dificulta para o leitor saber se é importante ou se é detalhe
3) FUNÇÕES (PEQUENAS!)
- Usar nomes descritivos
- Difícil superestimar valor de bons nomes
- Quanto menor e mais focada função, mais fácil será dar nome
- Melhor nome longo que comentário
- Não ter medo de usar tempo para escolher nome bom
testableHtml -> includeSetupAndTeardownPages
3) FUNÇÕES (PEQUENAS!)
- Argumentos
- 0 - ideal
- 1-2 - normal
- 3 - evitar ao máximo
- 4+ - não usar
- Dificultam muito entendimento
- Dificulta testes - casos de teste crescem exponencialmente
- Usar variável membro de classe ao invés de passar arg de fç pra outra
3) FUNÇÕES (PEQUENAS!)- Casos principais de acordo com qtde de argumentos
- 1
- Fazer pergunta
- fileExist("myFile")
- Operar sobre argumento e transformar em algo e retornar
- InputStream FileOpen("MyFile")
- Flags
- Muito ruim, indício que função está fazendo mais de uma coisa
- Ex:
- .render(true)
- ininteligível
- mouse over render -> bool isSuite
- menos ruim
- render(isSuite)
- renderForSuite() / renderForSingleTest()
- 2
- Point p(0,0)
- 3
- assertEquals(1.0, ammount, 0.001)
3) FUNÇÕES (PEQUENAS!)
- NÃO GERAR EFEITOS COLATERAIS
- Não faça coisas escondidas
- checkPassword(username, pass)
...
session.Initialize()
checkPasswordAndInitializeSession()
Melhor, mas já fica evidente que viola "faça uma coisa"
3) FUNÇÕES (PEQUENAS!)
Princípio DRY
DON'T REPEAT YOURSELF
Duplicação pode ser a raiz de todo o mal em software
3) FUNÇÕES (PEQUENAS!)
- Como escrever código bom assim?
- É igual escrever livro -> 1o põe idéias no papel, depois refina
- Passos
- Escreve rascunho
- Testes para tudo
- Refatora até ficar bom
NÃO É ESPERADO QUE 1A VEZ SEJA PERFEITO
3) FUNÇÕES (PEQUENAS!)
- Mudança incremental, MANTENDO TESTES PASSANDO, um passo de cada vez (baby steps)
3) FUNÇÕES (PEQUENAS!)
Arte de programar é a arte de design de idioma
Funções são a linguagem para ajudar a contar história do sistema
4) COMENTÁRIOS
- Explique-se por código- Comentários bons
- Informações legais- Explicação de intenção- Aviso de consequências
4) COMENTÁRIOS
4) COMENTÁRIOS
4) COMENTÁRIOS
4) COMENTÁRIOS
- Comentários ruins- Comentar só por achar que precisa comentar- Redundantes- Ruído- Código comentado- Excesso de informação
4) COMENTÁRIOS
- Comentários ruins- Comentar só por achar que precisa comentar- Redundantes- Ruído- Código comentado- Excesso de informaçãoNão use comentário onde você pode usar uma função ou
variável
4) COMENTÁRIOS
4) COMENTÁRIOS
4) COMENTÁRIOS
- Código comentado- Por que essas 2 linhas estão comentadas? São importantes?- Outros não terão coragem de apagar, por achar que pode ser
importante
17) BAD SMELLS
17) BAD SMELLS
- Código comentado- Comentário ao invés de código- Comentário obsoleto- Argumentos demais em função- Código em nível errado de abstração
17) BAD SMELLS
- Usar variáveis explanatórias
Matcher match = headerPattern.matcher(line);
if(match.find())
{
headers.put(match.group(1), match.group(2));
}
17) BAD SMELLS
- Usar variáveis explanatórias
Matcher match = headerPattern.matcher(line);
if(match.find())
{
String key = match.group(1);
String value = match.group(2);
headers.put(key.toLowerCase(), value);
}
17) BAD SMELLS
- Constantes no lugar de números mágicos
O que é mais fácil de entender, e de procurar?
assertEquals(7777, Employee.find(“John Doe”).employeeNumber());
assertEquals(
HOURLY_EMPLOYEE_ID,
Employee.find(HOURLY_EMPLOYEE_NAME).employeeNumber());
17) BAD SMELLS
- Encapsular condições
if (timer.hasExpired() && !timer.isRecurrent())
if (shouldBeDeleted(timer))
17) BAD SMELLS
- Função fazer mais de uma coisa
17) BAD SMELLS
- Testes- Insuficientes- Não ter relatório de cobertura de testes
OBSERVAÇÕES PESSOAIS
- Refactor para deixar sempre código melhor do que pegou- Para permitir Refactor:
- Testes- Testes- Testes
- Code Review – forma excelente de refactor e aprender
OBSERVAÇÕES PESSOAIS
- Testes- F.I.R.S.T. - Fast, Independent, Repeatable, Self-
Validating, Timely
OBSERVAÇÕES PESSOAIS
Funções e classes pequenas
Facilita entendimento, cada bloco só ter 1 nível de abstração
“Fazer uma coisa” é mais fácil de ser seguido
Comentários bem menos necessários
Evita indentação excessiva que complica entendimento
Facilita ver começo e fim de bloco (ex: if-else), sem precisar rolar página pra cima e pra baixo
Bora escrever código limpo?