web-dev-qa-db-fra.com

Code révisant les nitpicks pour la lisibilité [en fait pour DRY]

Je faisais une revue de code aujourd'hui et j'ai remarqué que le code fonctionnerait mais aurait facilement pu être rendu plus lisible.

L'exemple en particulier était approximativement le suivant:

def group(x):
    GROUP_ALPHA = ('a', 'b', 'e', 'f', 'i', 'j', 'k', 'l')
    GROUP_BETA = ('m', 'n', 'o', 'p', 'q')
    GROUP_CHARLIE = ('x', 'y', 'z', 'aa', 'ab', 'ae', 'af')
    GROUP_DELTA = ('ag', 'ah', 'ai', 'aj')
    GROUP_ECHO = ('ak', 'al', 'am', 'an', 'ao', 'ar', 'as')

    if x in GROUP_ALPHA:
        return 'ALPHA'
    Elif x in GROUP_BETA:
        return 'BETA'
    Elif x in GROUP_CHARLIE:
        return 'CHARLIE'
    Elif x in GROUP_DELTA:
        return 'DELTA'
    Elif x in GROUP_ECHO:
        return 'ECHO'

Notez que chaque groupe est disjoint.

Pour moi, ce serait plus lisible avec:

def group(x):
    GROUPS = {
        'ALPHA': ('a', 'b', 'e', 'f', 'i', 'j', 'k', 'l'),
        'BETA': ('m', 'n', 'o', 'p', 'q'),
        'CHARLIE': ('x', 'y', 'z', 'aa', 'ab', 'ae', 'af'),
        'DELTA': ('ag', 'ah', 'ai', 'aj'),
        'ECHO': ('ak', 'al', 'am', 'an', 'ao', 'ar', 'as')
    }
    for group_name, group_elements in GROUPS:
        if x in group_elements:
            return group_name

Dois-je le mentionner? Le code d'origine fonctionne et est utilisé dans une capacité non critique. Quand je faisais des recherches, j'ai remarqué cette réponse , qui remarque:

Chaque changement coûte de l'argent. Réécrire du code qui fonctionne et qui n'a probablement pas besoin d'être modifié pourrait être un effort inutile. Concentrez votre attention sur les sections les plus susceptibles d'être modifiées ou les plus importantes pour le projet.

Cela donnerait à penser que la réponse est non, mais il semble inutile de revoir le code et de ne pas suggérer une meilleure façon de faire les choses, même si la méthode originale "fonctionne". Personnellement, je voudrais que quelqu'un me fasse une telle suggestion.

Remarque: les exemples ci-dessus ont été modifiés depuis la première rédaction de la question. De plus, chaque entrée ('a', 'b', etc.) est en fait un str lisible par l'homme lié à la logique métier.

6
Shayaan

L'exemple donné ne fait pas à mon humble avis une grande différence de lisibilité - en fait, il est assez discutable si la deuxième variante est vraiment plus lisible que la première. Cependant, il s'agit clairement d'une amélioration du respect du principe SEC , et c'est une raison très valable pour changer le code.

Supposons que l'intention est de traiter tous ces groupes toujours de la même manière, ce qui, je suppose, est fort probable. Supposons également qu'il existe au moins cinq de ces groupes. Maintenant, vous obtenez la nouvelle exigence de changer la logique en quelque chose comme

if lower(x) in GROUP_ALPHA:

puis dans le premier exemple, vous devrez changer 5 emplacements, assurez-vous de les changer à l'identique et n'oubliez aucun endroit. Dans le deuxième exemple, il n'y aura qu'un seul endroit où changer, ce qui est certainement une amélioration. De plus, si vous allez écrire un test unitaire pour cette fonction, ou spécifiquement pour la modification de cette fonction, la première variante nécessitera 5 cas de test différents pour obtenir une couverture complète, et la seconde une seule.

Encore plus simple - supposons que vous vouliez simplement ajouter un autre groupe - dans le premier exemple, vous devrez changer deux endroits dans le code (ce qui inclut la copie de la section "recherche"), dans le deuxième exemple, vous n'aurez qu'à étendre la dictionnaire.

Garder le code DRY n'est pas seulement une question de "goût" - il s'agit de mettre le code dans un état où il est moins susceptible de causer de futurs maux de tête. Et les révisions de code sont une bonne occasion pour cette.

14
Doc Brown

L'un des avantages des revues de code est en effet de suggérer de meilleures façons de faire les choses. Mieux, bien sûr, signifie différentes choses dans différents contextes, mais peut inclure du code qui est plus lisible, plus rapide, consomme moins de mémoire, suit de bons principes de conception, est moins complexe, etc. Suggérer un changement plus lisible est un exemple parfait de quelque chose à noter lors d'une revue de code.

Chaque changement coûte de l'argent, mais il en va de même pour essayer de déchiffrer un code mal écrit dans 6 mois.

Gardez à l'esprit votre public cible, cependant, et réalisez qu'il peut être plus lisible pour vous mais moins lisible pour les autres (surtout si vous travaillez avec beaucoup d'ingénieurs débutants). Gardez également votre environnement/besoins d'application à l'esprit lorsque vous proposez ces modifications. Bien que votre solution soit plus rapide, un code plus rapide peut ne pas être nécessaire. Si le dictionnaire ne contient que 2 clés qui correspondent à une liste de 3 éléments, les performances ne seront jamais un problème, quelle que soit la façon dont vous l'avez configuré. Cela vaut probablement la peine d'être évoqué, car le reste de votre équipe peut l'utiliser la prochaine fois, mais réalisez que ce n'est pas quelque chose à creuser dans vos talons.

9
mmathis

Le changement proposé introduit un bug subtil, donc je suppose que c'est un bon exemple de la raison pour laquelle les suggestions doivent être examinées attentivement.

Si x est membre de plusieurs groupes, le premier exemple renverra le groupe first trouvé dans l'ordre explicite des if. Dans le deuxième exemple, les groupes seront vérifiés dans un ordre non spécifié (car les dictionnaires ne sont pas ordonnés), de sorte que celui des groupes qu'il renvoie n'est pas défini. Ceci est particulièrement insidieux car il pourrait être la sortie attendue dans les tests unitaires, mais cela pourrait changer sur une plate-forme différente ou avec une mise à jour de version.

Le problème sous-jacent est que le nouveau code ne communique pas clairement l'intention. Si le résultat escompté est en effet non déterministe, je pense qu'il devrait être clairement communiqué dans la documentation, car cela rompt définitivement avec le "principe de la moindre surprise".

Si d'un autre côté vous vous attendez à ce qu'un x apparaisse dans exactement un groupe, alors je pense que la structure des données devrait être modifiée pour communiquer clairement, par ex.

def group(x):
    GROUPS = {
      'a': 'ALPHA', 
      'c': 'ALPHA',
      'd': 'ALPHA',
      'h': 'BETA', 
      'k': 'BETA', 
      'l': 'BETA'
    }
    return GROUPS[x]

Il s'agit également d'un code beaucoup plus simple, car les hypothèses sont codées dans la structure de données plutôt que dans les boucles d'itération.

Cela dit, je conviens que c'est une bonne idée de suggérer des améliorations de lisibilité dans les revues de code. Mais c'est vraiment quelque chose dont vous devriez discuter dans votre équipe.

6
JacquesB