Ça sent mauvais parce qu'il y a probablement de nombreux cas où il pourrait être modifié ou amélioré.
La plupart de ces odeurs ne sont que des indices de quelque chose qui pourrait ne pas fonctionner. Ils ne sont pas obligatoirement corrigés en soi… (Vous devriez cependant y jeter un coup d'œil.)
Nous allons continuer...
Lorsque nous comparons aux booléens, nous effectuons des moulages magiques et obtenons des résultats inattendus.
TL; DR : Ne comparez pas avec la vérité. Soit vous êtes vrai, soit faux ou vous ne devriez pas comparer
De nombreux langages convertissent les valeurs en domaines booléens croisés.
#!/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
Les linters peuvent rechercher des comparaisons et des avertissements explicites.
C'est une pratique courante dans l'industrie d'utiliser de nombreux non-booléens comme booléens. Nous devrions être très stricts lorsque nous utilisons des booléens.
Code Smell 69 - Big Bang (JavaScript Ridicule Castings)
Photo de Michael Held sur Unsplash
Si cela ne fonctionne pas, peu importe à quelle vitesse cela ne fonctionne pas.
- Mich Ravéra
Les IF et Elses imbriqués sont très difficiles à lire et à tester
TL; DR : évitez les IF imbriqués. Encore mieux : évitez TOUS les IF
Dans le code procédural, il est très courant de voir des ifs imbriqués complexes. Cette solution est plus liée aux scripts qu'à la programmation orientée objet.
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 }
Étant donné que de nombreux linters peuvent analyser les arbres, nous pouvons vérifier au moment de la compilation les niveaux d'imbrication.
Suivant les conseils de l'oncle bob , nous devrions laisser le code plus propre que nous ne l'avons trouvé.
Refactoriser ce problème est facile.
Code Smell 78 - L'enfer des rappels
Code Smell 03 - Les fonctions sont trop longues
Code Smell 36 - Déclarations Switch/case/elseif/else/if
Le but du génie logiciel est de contrôler la complexité, pas de la créer.
-Pamela Zave
Appeler nos propres méthodes d'accès peut sembler une bonne idée d'encapsulation. Mais ce n'est pas.
TL;DR : N'utilisez pas de setters et de getters, même pour un usage privé
L'utilisation de la double encapsulation était une procédure standard dans les années 90.
Nous voulions cacher les détails d'implémentation même pour un usage privé.
Cela cachait une autre odeur lorsque trop de fonctions reposent sur la structure des données et une implémentation accidentelle.
Par exemple, on peut changer la représentation interne d'un objet et s'appuyer sur son protocole externe.
Le rapport coût/bénéfice n'en vaut pas la peine.
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); } }
Nous pouvons déduire les getters et les setters et vérifier s'ils sont invoqués à partir du même objet.
La double encapsulation était une idée à la mode pour protéger une mise en œuvre accidentelle, mais elle exposait plus que protégeait.
Code Smell 37 - Attributs protégés
Photo de Ray Hennessy sur Unsplash
Encapsuler le concept qui varie.
-Erich Gamma
L'assertion contre les booléens rend le suivi des erreurs plus difficile.
TL; DR : N'affirmez pas vrai à moins que vous ne vérifiiez un booléen
Lors de l'affirmation d'un booléen, nos moteurs de test ne peuvent pas beaucoup nous aider.
Ils nous disent juste que quelque chose a échoué.
Le suivi des erreurs devient plus difficile.
<? 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)
Certains linters nous avertissent si nous vérifions par rapport à booléen après avoir défini cette condition.
Nous devons le changer pour un contrôle plus spécifique.
Essayez de réécrire vos assertions booléennes et vous corrigerez les échecs beaucoup plus rapidement.
Code Smell 101 - Comparaison avec les booléens
Code Odeur 07 - Variables booléennes
Photo de Joël de Vriend sur Unsplash
J'ai enfin appris ce que signifie "compatibilité ascendante". Cela signifie que nous arrivons à garder toutes nos vieilles erreurs.
-Dennie van Tassel
Utilisez des noms professionnels et significatifs
TL; DR : Ne soyez pas informel ou offensant
Notre métier a un côté créatif.
Parfois, nous nous ennuyons et essayons d'être drôles.
function erradicateAndMurderAllCustomers(); // unprofessional and offensive
function deleteAllCustomers(); // more declarative and professional
Nous pouvons avoir une liste de mots interdits.
Nous pouvons également les vérifier dans les revues de code.
Les noms sont contextuels, ce serait donc une tâche difficile pour un linter automatique.
Les conventions de dénomination doivent être génériques et ne doivent pas inclure de jargon culturel.
Soyez professionnel dans la façon dont vous nommez les choses dans votre code.
N'essayez pas d'être un comédien en donnant à une variable un nom idiot.
Vous devez écrire du code de production afin que les futurs développeurs de logiciels (même vous) puissent facilement comprendre.
Code Smell 38 - Noms abstraits
Photo de Stewart Munro sur Unsplash
Cette mentalité « les utilisateurs sont des idiots et sont confus par la fonctionnalité » de Gnome est une maladie. Si vous pensez que vos utilisateurs sont des idiots, seuls les idiots l'utiliseront.
-Linus Torvalds
Excellentes citations de génie logiciel
Et c'est tout pour le moment...
Le prochain article expliquera 5 odeurs de code supplémentaires !