Clean Code – FUNÇÕES

Present Day, Present Time HAHAHAHA

Clean Code – FUNÇÕES

Março 21, 2023 dev 0

Funções são a primeira linha de organização em qualquer programa.

  • Pequenas!: A primeira regra para funções é que elas devem ser pequenas. Antigamente se dizia que uma função não deveria ser maior que o tamanho da tela. O problema disso hoje em dia, é que temos muitos tamanhos de tela haha. Funções devem ter NO MÁXIMO 20 linhas.

  • Blocos e indentação: Blocos dentro de instruções if, else, while e outros devem ter apenas uma linha. Possivelmente uma chamada de função. O nível de indentação deve ser de no máximo um ou dois.

  • Faça apenas uma coisa: Se uma função faz apenas aqueles passos em um nível abaixo do nome da função, então ela está fazendo apenas uma coisa. O motivo de termos funções, é para decompor um conceito maior em uma série de passos no próximo nível de abstração.

“As funções devem fazer apenas uma coisa, Devem fazê-la bem. Devem fazer apenas ela.”

Uma forma de saber se uma função faz mais de uma coisa, é se você pode extrair outra função à partir dela, que não seja apenas uma reformulação de sua implementação


  • Ler o código de cima para baixo – Regra decrescente: O código deve ser lido de cima para baixo, como uma narrativa. Cada função deve ser seguida pelas outras no próximo nível de abstração de cada vez, conforme percorremos a lista de funções.
    Cada função deve descrever o nível atual de abstração, fazendo referência aos parágrafos consecutivos no próximo nível.

  • Instruções switch: Apesar de ser difícil criar uma estrutura switch pequena, podemos nos certificar que cada switch está em uma classe de baixo nível e nunca é repetido. Para isso, usamos o polimorfismo. É aceitável que o switch apareça apenas uma vez, escondida atrás de uma relação de herança de forma que o restante do sistema não a enxergue.

  • Use nomes descritivos: Um nome extenso mas explicativo é melhor que um nome pequeno e enigmático, bem como, melhor que um comentário extenso e descritivo.
    Usar nomes descritivos esclarecerá o modelo de módulo na sua mente. Procure utilizar os mesmos nomes e verbos nos nomes de funções no seu código.

  • Parâmetros de funções: O número ideal de parâmetros passados para funções é zero.
    • Funções mônades: Um parâmetro de entrada, é a melhor coisa depois de zero parâmetros. Se uma função for transformar o parâmetro de entrada, então a alteração deve aparecer como o valor retornado. Ex.:
      StringBuilder transform(StringBuffer in) ainda é melhor que void transform(StringBuffer out) mesmo que a implementação do primeiro retorne o parâmetro de entrada.
      • Parâmetros lógicos: É feio passar um parâmetro booleano para uma função, pois nos mostra que a função faz mais de uma coisa. Uma chamada render(true) é muito confusa para um leitor simples. Analisar a chamada render(Boolean isSuite) ajuda um pouco, mas mesmo assim, esta função poderia ser dividida em renderForSuite( ) e renderForSingleTest( ), por exemplo.
    • Funções díades: Estas funções são ainda mais difíceis de entender que as mônades. Quando lemos funções com mais de um parâmetro, tendemos a ignorar o primeiro parâmetro quando fazemos uma pausa para entender o segundo. E é aí que moram os bugs. Há casos é claro, que precisaremos de dois parâmetros, Ex.:
      Point p = new Point(1,2)
      (Claro que, neste caso os dois parâmetros são componentes de um único valor)
      Podemos contornar a situação transformando a função em mônades. Ex.:
      1. Tornar o método writeField um membro de outputStream, de modo que se possa chamar outputStream.writeField(name);
      2. Tornar outputStream membro da classe em uso, a fim de não precisar passar por parâmetro
        OU
        Você poderia ainda extrair uma nova classe, como FieldWriter, que receba o outputStream em seu construtor e possua o método write( ).
    • Funções tríades: Funções que recebem 3 parâmetros são consideravelmente mais difíceis de entender do que as díades. As questões de ordenação, pausa e ignoração apresentam mais do que o dobro de dificuldade.
      • Objetos como parâmetros: Procure reduzir o número de parâmetros através da criação de objetos. Quando grupos de variáveis são passadas juntas, como:
        Circle make(double x, double y, double radius);
        é provável que sejam parte de um conceito que mereça um nome só pra ele. Ex.:
        Circle make(Point center, double radius);

  • Objetos como parâmetros: Reduza a o número de parâmetros através da criação de objetos. Pode ser que um grupo de parâmetros faça parte de um conceito que mereça um nome só pra ele. Ex.:
    Circle make(double x, double y, double radius);
    Circle make(Point center, double radius);

  • Lista como parâmetro: Se os parâmetros variáveis forem todos tratados da mesma forma, serão equivalentes a um único parâmetro do tipo list. Para que as funções não sejam maiores que funções tríades. Ex.:
    void monad(Integer ...args);
    void dyad(String name, Integer ...args);
    void triad(String name, int count, Integer ...args);

  • Parâmetros de saída: A finalidade do this é atuar como uma referência de saída. Em geral, é recomendável evitar o uso de parâmetros de saída. Se uma função precisar modificar o estado de algo, é aconselhável alterar o estado do objeto que ela pertence.

  • Separação comando-consulta: Uma função deve fazer apenas uma coisa. Ou a função altera o estado de um objeto ou retorna informações sobre ele.

  • Prefira exceções a retorno de códigos de erro: Ao retornar um código de erro, criamos um problema para o chamador que deverá lidar imediatamente com o erro.

  • Extraia os blocos try/catch: Utilize das estruturas try/catch sempre que necessário, em suas funções. Try deve ser a primeira instrução e nada deve vir após os blocos catch/finally.

  • Tratamento de erro é uma coisa só: Uma função que trata erros não deve fazer mais nada.

Como escrever boas funções? Organizar, refinar, dividir funções, trocar nomes, eliminar duplicação, reduzir os métodos e reorganizar. Mas não é necessário fazer desde o começo, pois é praticamente impossível.

Tente pensar que sistemas devam ser como histórias a serem contadas ao invés de programas a serem escritos.

 

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *