DEV Community

Jonilson Sousa
Jonilson Sousa

Posted on • Updated 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)