DEV Community

Jonilson Sousa
Jonilson Sousa

Posted on • Edited on

Anotações Capítulo 5: Formatting

  • “Você deve tomar conta para que seu código fique bem formatado”;
  • Escolha regras simples e aplique de forma consistente.
  • Em equipe, todos devem concordar com uma única série de regras de formatação.

Objetivo da formatação

  • A formatação de código é importante.
  • Serve como comunicação.
  • Legibilidade do código terá um grande efeito em todas as mudanças futuras.

Formatação vertical

  • Há uma grande diversidade de tamanhos e diferenças de estilo.
  • As linhas verticais mostram os comprimentos mínimo e máximo.
  • Arquivos pequenos costumam ser mais fáceis de se entender do que os grandes.

A metáfora do jornal

  • “No topo você espera ver uma manchete que lhe diz do que se trata a história e lhe permite decidir se deseja ou não ler”.
  • Primeiro parágrafo é a sinopse da história.
  • O demais detalhes vem no decorrer da leitura.
  • Queremos que o código fonte seja como artigo de jornal.

Espaçamento vertical entre conceitos

  • Há linhas em branco que separam a declaração e a importação do pacote e cada uma das funções.
  • “Cada linha em branco indica visualmente a separação entre conceitos”.
  • Retirar as linhas em branco, gera um efeito muito ruim na legibilidade do código.

Continuidade vertical

  • A continuidade vertical indica uma associação íntima.
  • Linhas de código que estão intimamente relacionadas devem aparecer verticalmente unidas.
  • Comentários inúteis quebram essa intimidade de duas variáveis:
public class ReporterConfig { /** * The class name of the reporter listener */ private String m_className; /** * The properties of the reporter listener */ private List<Property> m_properties = new ArrayList<Property>(); public void addProperty(Property property) { m_properties.add(property); } 
Enter fullscreen mode Exit fullscreen mode
  • Removendo os comentários fica mais fácil de ler:
public class ReporterConfig { private String m_className; private List<Property> m_properties = new ArrayList<Property>(); public void addProperty(Property property) { m_properties.add(property); } } 
Enter fullscreen mode Exit fullscreen mode

Esse último exemplo, o código cabe numa única visão, podemos compreender todo o método sem ter que mover a cabeça ou os olhos.

Distância vertical

  • Os conceitos intimamente relacionados para conceitos em arquivos separados.
  • Não devemos separar em arquivos distintos conceitos intimamente relacionados, a menos que tenha uma razão muito boa.
  • A separação vertical deles deve ser uma medida do quão importante eles são para a inteligibilidade um do outro.
  • Devemos declarar variáveis o mais próximo possível de onde serão usadas”.
  • Exemplo: Devemos declarar variáveis de controle para loops dentro da estrutura de iteração:
public int countTestCases() { int count= 0; for (Test each : tests) count += each.countTestCases(); return count; } 
Enter fullscreen mode Exit fullscreen mode
  • Em alguns casos pode-se declarar uma variável no início de um bloco ou logo depois de um loop em uma função longa:
for (XmlTest test : m_suite.getTests()) { TestRunner tr = m_runnerFactory.newTestRunner(this, test); tr.addListener(m_textReporter); m_testRunners.add(tr); invoker = tr.getInvoker(); for (ITestNGMethod m : tr.getBeforeSuiteMethods()) { beforeSuiteMethods.put(m.getMethod(), m); } for (ITestNGMethod m : tr.getAfterSuiteMethods()) { afterSuiteMethods.put(m.getMethod(), m); } } 
Enter fullscreen mode Exit fullscreen mode
  • Variáveis de Instância: Devemos declarar as variáveis de instância no início da classe. Isso não deve aumentar a distância vertical entre tais variáveis, elas serão usadas por muitos, senão todos, os métodos da classe.
  • O importante é que as variáveis de instância sejam declaradas em um local bem conhecido. Todos devem saber onde buscar as declarações.
  • Funções dependentes: Se uma função chama outra, elas devem ficar verticalmente próximas. Assim, a que chama deve ficar acima da que for chamada. Isso dá um fluxo natural ao programa.
  • Assim, os leitores poderão confiar que as declarações daquelas funções virão logo em seguida.
  • Afinidade conceitual: Quanto maior a afinidade, menor deve ser a distância entre eles.
  • A afinidade se baseia numa dependência direta. Uma função chamando outra. Uma função usando uma variável.
  • Um grupo de funções que efetuam uma operação parecida cria uma afinidade. Exemplo:
public class Assert { static public void assertTrue(String message, boolean condition) { if (!condition) fail(message); } static public void assertTrue(boolean condition) { assertTrue(null, condition); } static public void assertFalse(String message, boolean condition) { assertTrue(message, !condition); } static public void assertFalse(boolean condition) { assertFalse(null, condition); } ... 
Enter fullscreen mode Exit fullscreen mode

Essas funções possuem uma afinidade conceitual forte, pois compartilham de uma mesma convenção de nomes e efetuam variações de uma mesma tarefa. Bem como o fato de uma chamar a outra.

Ordenação vertical

  • Desejamos que as chamadas das dependências da função apontem para baixo;
  • No caso, “a função chamada deve ficar embaixo da que a chama”;
  • Cria um fluxo natural para baixo no módulo do código-fonte, de um nível maior para um menor.
  • Assim os detalhes de baixo nível venham por último.

Formatação horizontal

  • “Devemos nos esforçar para manter nossas linhas curtas”;
  • O antigo limite de 80 de Hollerith é arbitrário;
  • Com 100 linhas ou 120 ainda é aceitável, porém ultrapassar 120 caracteres é uma falta de cuidado;

Espaçamento e continuidade horizontal

  • Operadores de atribuição entre espaços em branco:
int lineSize = line.length(); 
Enter fullscreen mode Exit fullscreen mode

Essas instruções tem dois lados distintos, o lado esquerdo e o lado direito. Assim, os espaços tornam essa separação óbvia.

  • Porém não coloque espaços entre os nomes das funções e os parênteses de abertura. Isso porque a função e seus parâmetros estão intimamente relacionados;
  • Bem como separar os parâmetros entre parênteses na chamada da função realçar a vírgula e mostram que estão separados;
  • Espaço em branco entre operadores é para destacar a prioridade dos mesmo;

Alinhamento horizontal

  • Esse tipo de alinhamento não é prático;
  • Parece enfatizar as coisas erradas e afasta o propósito real;
  • As ferramentas de reformatação automática geralmente eliminam esse tipo de alinhamento;
  • É melhor não usar esse tipo de alinhamento;
  • Se tiver listas longas que precisam ser alinhadas, “o problema está no tamanho das listas”e não na falta de alinhamento;

Indentação

  • Um código-fonte é mais como uma hierarquia do que algo esquematizado;
  • Informações pertinentes ao arquivo, classes individuais dentro do arquivo, aos métodos das classes, aos blocos dentro dos métodos.
  • Cada nível dessa hierarquia é um escopo.
  • E para tornar visível essa hierarquia indentamos o código.
  • Os programadores dependem bastante dessa indentação.
  • Elas alinham visualmente na esquerda as linhas para ver em qual escopo eles estão.
  • Assim a navegação e a compreensão do código para o programador é facilitada, ele sempre vai procurar a declaração variáveis mais a esquerda, etc.
  • A mesma versão de um código sem indentação é quase incompreensível.
  • Ignorando a indentação: Podemos querer não fazer a indentação mas no fim voltamos e fazemos, é uma necessidade.

Escopos minúsculos

  • Estruturas while ou for minúsculas, é complicado para uma boa indentação.

Regra de equipes

  • Todo programador tem suas regras de formatação prediletas;
  • Mais em uma equipe, as regras são dela;
  • A equipe deve escolher um único estilo de formatação e todos devem usá-lo;
  • Assim o código tem estilo consistente;
  • O leitor precisa poder confiar que as formatações que ele vir em uma arquivo-fonte terão o mesmo significado nos outros.

Regras de formatação do Uncle Bob

  • Considere este um exemplo de como o código torna o melhor documento padrão de codificação:
public class CodeAnalyzer implements JavaFileAnalysis { private int lineCount; private int maxLineWidth; private int widestLineNumber; private LineWidthHistogram lineWidthHistogram; private int totalChars; public CodeAnalyzer() { lineWidthHistogram = new LineWidthHistogram(); } public static List<File> findJavaFiles(File parentDirectory) { List<File> files = new ArrayList<File>(); findJavaFiles(parentDirectory, files); return files; } private static void findJavaFiles(File parentDirectory, List<File> files) { for (File file : parentDirectory.listFiles()) { if (file.getName().endsWith(".java")) files.add(file); else if (file.isDirectory()) findJavaFiles(file, files); } } public void analyzeFile(File javaFile) throws Exception { BufferedReader br = new BufferedReader(new FileReader(javaFile)); String line; while ((line = br.readLine()) != null) measureLine(line); } private void measureLine(String line) { lineCount++; int lineSize = line.length(); totalChars += lineSize; lineWidthHistogram.addLine(lineSize, lineCount); recordWidestLine(lineSize); } private void recordWidestLine(int lineSize) { if (lineSize > maxLineWidth) { maxLineWidth = lineSize; widestLineNumber = lineCount; } } public int getLineCount() { return lineCount; } public int getMaxLineWidth() { return maxLineWidth; } public int getWidestLineNumber() { return widestLineNumber; } <restante do código> } 
Enter fullscreen mode Exit fullscreen mode

Top comments (0)