Cheira porque provavelmente há muitos casos em que poderia ser editado ou melhorado.
A maioria desses cheiros são apenas indícios de algo que pode estar errado. Eles não são necessariamente consertados per se ... (Você deve investigar isso.)
Vamos continuar...
Ao comparar com booleanos, realizamos conjurações mágicas e obtemos resultados inesperados.
TL;DR: Não compare com o verdadeiro. Ou você é verdadeiro, ou falso ou não deve comparar
Muitos idiomas lançam valores para domínios de cruzamento booleanos.
#!/bin/bash if [ false ]; then echo "True" else echo "False" fi # this evaluates to true since # "false" is a non-empty string if [ false ] = true; then echo "True" else echo "False" fi # this also evaluates to true
#!/bin/bash if false ; then echo "True" else echo "False" fi # this evaluates to false
Linters podem verificar comparações e avisos explícitos.
É uma prática comum da indústria usar muitos não booleanos como booleanos. Devemos ser muito rigorosos ao usar booleanos.
Code Smell 69 - Big Bang (JavaScript Ridiculous Castings)
Foto de Michael Held no Unsplash
Se não funcionar, não importa o quão rápido não funcione.
-Mich Ravera
IFs e Elses aninhados são muito difíceis de ler e testar
TL;DR: Evite IFs aninhados. Melhor ainda: evite TODOS os IFs
No código procedural, é muito comum ver ifs aninhados complexos. Essa solução está mais relacionada a scripts do que a programação orientada a objetos.
if (actualIndex < totalItems) { if (product[actualIndex].Name.Contains("arrow")) { do { if (product[actualIndex].price == null) { // handle no price } else { if (!(product[actualIndex].priceIsCurrent())) { // add price } else { if (!hasDiscount) { // handle discount } else { // etc } } } actualIndex++; } while (actualIndex < totalCounf && totalPrice < wallet.money); } else actualIndex++; } return actualIndex; }
foreach (products as currentProduct) addPriceIfDefined(currentProduct) addPriceIfDefined() { //Several extracts }
Como muitos linters podem analisar árvores, podemos verificar em tempo de compilação os níveis de aninhamento.
Seguindo o conselho do tio bob , devemos deixar o código mais limpo do que encontramos.
Refatorar esse problema é fácil.
Cheiro de código 03 - as funções são muito longas
Cheiro de código 36 - instruções switch/case/elseif/else/if
O propósito da engenharia de software é controlar a complexidade, não criá-la.
- Pâmela Zave See More
Chamar nossos próprios métodos de acesso pode parecer uma boa ideia de encapsulamento. Mas não é.
TL;DR: Não use setters e getters, mesmo para uso privado
O uso de encapsulamento duplo era um procedimento padrão na década de 90.
Queríamos ocultar detalhes de implementação, mesmo para uso privado.
Isso estava escondendo outro cheiro quando muitas funções dependem da estrutura de dados e da implementação acidental.
Por exemplo, podemos alterar a representação interna de um objeto e confiar em seu protocolo externo.
Custo/benefício não vale a pena.
contract MessageContract { string message = "Let's trade"; function getMessage() public constant returns(string) { return message; } function setMessage(string newMessage) public { message = newMessage; } function sendMessage() public constant { this.send(this.getMessage()); // We can access property but make a self call instead } }
contract MessageContract { string message = "Let's trade"; function sendMessage() public constant { this.send(message); } }
Podemos inferir getters e setters e verificar se eles são invocados do mesmo objeto.
O encapsulamento duplo era uma ideia da moda para proteger a implementação acidental, mas expunha mais do que protegia.
Cheiro de Código 37 - Atributos Protegidos
Foto de Ray Hennessy no Unsplash
Encapsule o conceito que varia.
-Erich Gama See More
Afirmar contra booleanos torna o rastreamento de erros mais difícil.
TL;DR: Não declare verdadeiro a menos que esteja verificando um valor booleano
Ao declarar um booleano, nossos mecanismos de teste não podem nos ajudar muito.
Eles apenas nos dizem que algo falhou.
O rastreamento de erros fica mais difícil.
<? final class RangeUnitTest extends TestCase { function testValidOffset() { $range = new Range(1, 1); $offset = $range->offset(); $this->assertTrue(10 == $offset); // No functional essential description :( // Accidental description provided by tests is very bad } } // When failing Unit framework will show us // // 1 Test, 1 failed // Failing asserting true matches expected false :( // () <-- no business description :( // // <Click to see difference> - Two booleans // (and a diff comparator will show us two booleans)
<? final class RangeUnitTest extends TestCase { function testValidOffset() { $range = new Range(1, 1); $offset = $range->offset(); $this->assertEquals(10, $offset, 'All pages must have 10 as offset'); // Expected value should always be first argument // We add a functional essential description // to complement accidental description provided by tests } } // When failing Unit framework will show us // // 1 Test, 1 failed // Failing asserting 0 matches expected 10 // All pages must have 10 as offset <-- business description // // <Click to see difference> // (and a diff comparator will help us and it will be a great help // for complex objects like objects or jsons)
Alguns linters nos avisam se estamos verificando o booleano após definir essa condição.
Precisamos alterá-lo para uma verificação mais específica.
Tente reescrever suas asserções booleanas e você corrigirá as falhas muito mais rapidamente.
Code Smell 101 - Comparação com Booleanos
Code Smell 07 - Variáveis Booleanas
Foto de Joël de Vriend no Unsplash
Finalmente aprendi o que significa 'compatível com versões anteriores'. Isso significa que podemos manter todos os nossos velhos erros.
-Dennie van Tassel
Use nomes profissionais e significativos
TL;DR: Não seja informal ou ofensivo
Nossa profissão tem um lado criativo.
Às vezes ficamos entediados e tentamos ser engraçados.
function erradicateAndMurderAllCustomers(); // unprofessional and offensive
function deleteAllCustomers(); // more declarative and professional
Podemos ter uma lista de palavras proibidas.
Também podemos verificá-los em revisões de código.
Os nomes são contextuais, então seria uma tarefa difícil para um linter automático.
As convenções de nomenclatura devem ser genéricas e não devem incluir jargão cultural.
Seja profissional na maneira como você nomeia as coisas em seu código.
Não tente ser um comediante dando um nome bobo a uma variável.
Você deve escrever o código de produção para que os futuros desenvolvedores de software (até mesmo você) entendam facilmente.
Code Smell 38 - Nomes abstratos
Foto de Stewart Munro no Unsplash
Essa mentalidade de 'usuários são idiotas e estão confusos com a funcionalidade' do Gnome é uma doença. Se você acha que seus usuários são idiotas, apenas idiotas irão usá-lo.
- Linus Torvalds
Grandes Citações de Engenharia de Software
E isso é tudo por agora…
O próximo artigo explicará mais 5 code smells!