web-dev-qa-db-fra.com

Est-il jamais logique pour un refactoriste de se retrouver avec un LOC plus élevé?

Y a-t-il des cas où un code plus verbeux (comme dans des déclarations plus logiques) est plus propre qu'un code plus concis?

25
wrongusername

Pour répondre à cela, prenons un exemple du monde réel qui m'est arrivé. En C # une bibliothèque que je maintiens, j'avais le code suivant:

TResult IConsFuncMatcher<T, TResult>.Result() =>
    TryCons(_enumerator) is var simpleMatchData && !simpleMatchData.head.HasValue
        ? _emptyValue.supplied
            ? _emptyValue.value
            : throw new NoMatchException("No empty clause supplied");
        : _recursiveConsTests.Any() 
            ? CalculateRecursiveResult() 
            : CalculateSimpleResult(simpleMatchData);

En discutant avec des pairs, le verdict unanime était que les expressions ternaires imbriquées, couplées à l'utilisation "intelligente" de is var a donné un code concis mais difficile à lire.

Je l'ai donc refactorisé pour:

TResult IConsFuncMatcher<T, TResult>.Result()
{
    var simpleMatchData = TryCons(_enumerator);

    if (!simpleMatchData.head.HasValue)
    {
        return _emptyValue.supplied
            ? _emptyValue.value
            : throw new NoMatchException("No empty clause supplied");
    }

    return _recursiveConsTests.Any() 
        ? CalculateRecursiveResult() 
        : CalculateSimpleResult(simpleMatchData);
}

La version d'origine ne contenait qu'une seule expression composée avec un return implicite. La nouvelle version contient désormais une déclaration de variable explicite, une instruction if et deux returns explicites. Il contient plus d'instructions et plus de lignes de code. Pourtant, tous ceux que j'ai consultés ont jugé plus facile à lire et à raisonner, qui sont des aspects clés du "code propre".

La réponse à votre question est donc un "oui" catégorique, plus verbeux peut être plus propre qu'un code concis et constitue donc une refactorisation valide.

70
David Arno

1. Manque de corrélation entre LOC et la qualité du code.

Le refactoring a pour objectif d'améliorer la qualité d'un morceau de code.

LOC est une métrique très basique qui, parfois, est en corrélation avec la qualité d'un morceau de code: par exemple, une méthode avec quelques milliers de LOC est susceptible d'avoir des problèmes de qualité. Il convient de noter, cependant, que LOC n'est pas la métrique seulement et, dans de nombreux cas, manque de corrélation avec la qualité. Par exemple, une méthode 4 LOC n'est pas nécessairement plus lisible ou plus maintenable qu'une méthode 6 LOC.

2. Certaines techniques de refactoring consistent à ajouter des LOC.

Si vous prenez ne liste de techniques de refactoring , vous pouvez facilement repérer celles qui consistent à intentionnellement ajouter LOCs. Exemples:

Les deux sont des techniques de refactorisation très utiles, et leur effet sur le LOC est complètement hors de propos lorsque vous envisagez de les utiliser ou non.

Évitez d'utiliser LOC.

LOC est une métrique dangereuse. Il est très facile à mesurer et très difficile à interpréter correctement.

Jusqu'à ce que vous vous familiarisiez avec les techniques de mesure de la qualité du code, pensez à éviter de mesurer LOC en premier lieu. La plupart du temps, vous n'obtiendrez rien de pertinent, et il y aura des cas où cela vous induira en erreur en diminuant la qualité de votre code.

30
Arseni Mourzenko

Si vous voulez voir le résultat final de simplement minimiser le nombre d'octets ou le nombre de LoC de votre code source, allez jeter un œil aux soumissions au site Golf Stack Exchange Code Golf .

Si votre code source est réduit de cette façon, vous aurez bientôt un gâchis impossible à maintenir. Même si vous êtes la personne qui a écrit un tel code et que vous le comprenez parfaitement à l'époque, quelle sera votre efficacité lorsque vous y reviendrez dans six mois? Il n'y a aucune preuve qu'un tel code minimal s'exécute réellement plus rapidement.

Le code doit être rédigé de manière à ce que tout membre de votre équipe puisse le consulter et comprendre immédiatement ce qu'il fait.

12
Peregrine

Oui, le refactoring peut définitivement générer plus de lignes de code.

Le cas le plus courant IMO est lorsque vous prenez du code qui n'est pas générique et que vous le rendez plus générique/flexible. La génération de code fait facilement augmenter considérablement les lignes de code (parfois d'un facteur deux ou plus).

Si vous vous attendez à ce que le nouveau code générique soit utilisé par d'autres (au lieu d'être simplement un composant logiciel interne) en tant que bibliothèque, vous finissez généralement par ajouter du code le plus unitaire et un balisage de documentation dans le code, ce qui augmentera à nouveau les lignes de code.

Par exemple, voici un scénario très courant qui se produit pour tous les développeurs de logiciels:

  • votre produit a besoin d'une nouvelle fonctionnalité urgente hautement prioritaire ou d'un correctif ou d'une amélioration de bogue dans deux semaines (ou quel que soit le délai considéré comme urgent pour la taille de votre projet/la taille de l'entreprise/etc.)
  • vous travaillez dur et livrez XYZ à temps et cela fonctionne. Toutes nos félicitations! Bon travail!
  • Pendant que vous développiez XYZ, votre conception/implémentation de code existante ne supportait pas vraiment XYZ mais vous pouviez shim XYZ dans la base de code
  • le problème est que la cale est moche et a une odeur de code terrible parce que vous avez fait des choses délicates/intelligentes/laides/mauvaises pratiques mais qui fonctionnent un peu
  • lorsque vous trouvez du temps plus tard, vous refactorisez le code qui peut changer de nombreuses classes ou ajouter une nouvelle couche de classes et votre nouvelle solution est "bien faite" et n'a plus la mauvaise odeur de code ... cependant, le faire de la "bonne façon" prend désormais beaucoup plus de lignes de code.

Quelques exemples concrets qui me viennent du haut de ma tête:

  • pour une interface de ligne de commande vous pourriez avoir 5000 lignes de code if/else-if ou vous pourriez utiliser des rappels ... chaque rappel serait beaucoup plus petit et plus facile à lire/tester/vérifier/déboguer/etc, mais si vous comptez les lignes de code, les 5 000 lignes de code if/else-if seraient probablement plus petites
  • pour un morceau de code de traitement qui prend en charge N méthodes de traitement, vous pouvez à nouveau utiliser les instructions if/else qui auraient l'air les plus laides ...
    • ou vous pouvez passer aux rappels, ce qui serait mieux/mieux, mais les rappels prennent plus de lignes de code (compilez quand même le temps)
    • ou vous pouvez extraire davantage et faire des plugins qui peuvent être modifiés au moment de l'exécution. les plugins sont agréables car vous n'avez pas à recompiler le produit principal pour chaque nouveau plugin ou modification d'un plugin existant. et vous pouvez publier l'API pour que d'autres puissent étendre le produit. MAIS encore une approche plugin utilise plus de lignes de code.
  • pour une interface graphique, vous créez un excellent nouveau widget
    • vous ou un collègue remarque que le nouveau widget serait idéal pour XYZ et ABC, mais pour l'instant le widget n'est étroitement intégré que pour fonctionner pour XYZ
    • vous refactorisez le widget pour qu'il fonctionne pour les deux mais maintenant le nombre total de lignes de code augmente
1
Trevor Boyd Smith