Executando verificação de segurança...
5

Emergência: Como um bom design surge naturalmente

Introdução

Imagine que você está construindo um LEGO gigante. Se você apenas sair encaixando peças sem critério, logo vai acabar com algo frágil e confuso. Mas se seguir algumas regras básicas, sem perceber, você criará uma estrutura bem planejada e funcional. Isso é a "Emergência" no código: um bom design que surge naturalmente a partir de boas práticas.

Robert C. Martin (Uncle Bob) fala disso no capítulo 12 do Clean Code, destacando quatro princípios que levam a um código simples e bem estruturado.

Os 4 pilares de um design emergente

1. Passe em todos os testes ✅

Código bom é código confiável. Se você escreve testes automatizados e garante que tudo está funcionando, já está no caminho certo. Como o Filipe Deschamps disse nesse video onde utilizar testes, faz com que você programe mais rapido.

Exemplo: Se você altera uma função e ela quebra outra parte do sistema, sem testes você nem percebe. Com testes, o erro é detectado na hora. Além de conseguir testar tudo que você esta fazendo sem depender de uma interface.

Código sem testes:

public int somar(int a, int b) {
    return a + b;
}

Código com testes:

@Test
public void testSomar() {
    assertEquals(5, somar(2, 3));
}

2. Elimine duplicidades 🚀

A repetição é o maior inimigo do código limpo. Sempre que vê algo duplicado, é um sinal de que pode haver uma abstração melhor.

Código com duplicação:

public double calcularDescontoClienteOuro(double valor) {
    return valor * 0.9;
}

public double calcularDescontoClientePrata(double valor) {
    return valor * 0.95;
}

Código refatorado:

public double calcularDesconto(double valor, double taxa) {
    return valor * taxa;
}

3. Expresse claramente sua intenção 💡

Seu código deve ser legível como um livro. Nomes significativos, estrutura clara e pouca necessidade de comentários excessivos.

Exemplo ruim:

int c = 10; // Quantidade de clientes ativos

Exemplo bom:

int clientesAtivos = 10;

Outro exemplo ruim:

public void p() {
    for (int i = 0; i < lista.size(); i++) {
        System.out.println(lista.get(i));
    }
}

Refatorado para melhor clareza:

public void imprimirListaClientes(List<String> clientes) {
    for (String cliente : clientes) {
        System.out.println(cliente);
    }
}

4. Mantenha o código pequeno e simples 📦

Classes e métodos devem ser curtos. Menos é mais. Se seu método precisa de um manual para ser entendido, ele está grande demais.

Código grande e confuso:

public void processarPedido(Pedido pedido) {
    if (pedido.isPago()) {
        if (pedido.getCliente().isVip()) {
            aplicarDescontoVip(pedido);
        }
        gerarNotaFiscal(pedido);
        enviarEmailConfirmacao(pedido);
    }
}

Código refatorado:

public void processarPedido(Pedido pedido) {
    if (!pedido.isPago()) return;
    
    aplicarDescontosSeNecessario(pedido);
    gerarNotaFiscal(pedido);
    enviarEmailConfirmacao(pedido);
}

private void aplicarDescontosSeNecessario(Pedido pedido) {
    if (pedido.getCliente().isVip()) {
        aplicarDescontoVip(pedido);
    }
}

Por que "Emergência"?

O nome do capítulo não é à toa. Assim como um jardim bem cuidado floresce sem precisar ser desenhado folha por folha, um design bem feito emerge naturalmente quando aplicamos essas boas práticas.

Conclusão

Seguir esses princípios não garante que seu software será perfeito, mas evita que ele vire um Frankenstein de código. Quanto mais você pratica, mais intuitivo fica escrever código limpo.

Se quiser um resumo visual com exemplos e boa explicação, confere esse vídeo do Felipe Gavilan Programa: LINK

Carregando publicação patrocinada...
3

O 1 me lembra de criar uma palestra/vídeo/artigo chamado "Não faça testes!". Eu percebo que muitas pessoas (eu sou uma pessoa) não sabem fazer testes adequados, testando o que não precisa e deixando de testar o que é necessário, então a pessoas está só se inserindo na moda, não ajudando seu software ser melhor. POde ser que tenha algum ganho, mas não tão grande e muito mais trabalhos do que deveria. Testar é fazer código muito simples, mas exige entender muito bem o problema, a matemática e a computação. Isso falta para m uita gente. E precisa de experiência, eu não tenho ela tão boa mesmo depois de 40 anos fazendo isso, por uma razão básica, eu treinei o erro no passado, ficou difícil para mim.

O 2 muda a semântica do código e pode introduzir erros mais facilmente. Pode ser que o segundo exemplo seja realmente melhor, mas depende dos requisitos, mas aí o primeiro exemplo sequer caberia porque não atenderia os requisitos, a mudança da entrada de dados da função já indica a mudança. As pessoas confudem o que é DRY. Só com o contexto exato e concreto é que eu poderia escolher qual é o melhor.

Achar que existe uma regra de ouro é algo que iniciantes e experientes que aprenderam erraram e treinaram a vida toda assim, tornado-se teimoso, cometem muito. Eu vejo muito dessas regras nas redes sociais por aí e boa parte está pelo menos parcialmente erradas, ou seja, tem muita gente espalhando fake news apesar da boa intenção, muitas vezes ela está só reproduzindo o que ela aprendeu errado. Não é por acaso que o primeiro vídeo do meu canal se chamará "A péssima prática de seguir boas práticas".

O 3 indiretamente contém um mito muito comum no caso do laço. O exemplo mostrado é bom sim, se você puder varrer uma coleção em vez de ir lendo passo a passo, você deve fazer isso mesmo. Mas há casos que isso não é possível ou pode ser sensível na performance e precisa o método mais rápido , então o primeiro é melhor. O mito é que algumas pessoas não usaria a variável i, já vi muito falarem para usar contador ou algo do tipo. Isso não deixa mais legível, pelo contrário. Se ser verboso em vez e ser simbólico quando é universal, então COBOL seria a linguagem preferida das pessoas.Você tem que ser sompreendido, e todo mundo sabe o que é esse i , confunde até menos.

No 4 em geral as pessoas usam exemplo para evitar o if (anda bem popular fazer isso) que são simples, fáceis e realmente pode dar uma vantagem, mas ninguém mostra os casos que tentar fazer isso seria ruim. E a questão de separar em um método separado uma das ações que se faz depende de contexto para decidir se é o melhor a fazer, não é uma verdade absoluta. Não é tão comum, mas esse tipo de código pode dificultar a manutenção , quebrando em parte a coesão. Novamente, depende. Poderia ser que o if ali teria que estar dentro do aplicarDescontoVip(), masis uma vez, só dá para decidir sabwendo dos requisitos reais.

A lição é: não siga receitas de bolo, entenda o que está fazendo. Inclusive porque tem contextos que pode fazer de qualquer jeito que está bom.

Quanto mais pratica o erro, menos aceita o certo.

S2


Farei algo que muitos pedem para aprender a programar corretamente, gratuitamente (não vendo nada, é retribuição na minha aposentadoria) (links aqui no perfil também).