window.pipedriveLeadboosterConfig = { base : 'leadbooster-chat.pipedrive.com', companyId : 11580370, playbookUuid: '22236db1-6d50-40c4-b48f-8b11262155be', version : 2, } ;(function () { var w = window if (w.LeadBooster) { console.warn('LeadBooster existe déjà') } else { w.LeadBooster = { q : [], on : function (n, h) { this.q.push({ t : 'o', n : n, h : h }) }, trigger : function (n) { this.q.push({ t : 't', n : n }) }, } } })() thecodest, Author at The Codest - Page 8 of 18

Il est donc incompréhensible pour certains que remaniement est en fait un domaine de la programmation, et c'est aussi une partie très importante du travail du programmeur. Le code est en constante évolution, il sera modifié tant qu'il sera possible d'ajouter de nouvelles fonctionnalités. Cependant, il peut prendre une forme qui ne permet plus d'ajouter efficacement de nouvelles fonctionnalités et il serait alors plus facile de réécrire l'ensemble du programme.

Qu'est-ce que le refactoring ?

Habituellement, la réponse que vous entendez est qu'il s'agit de changer la structure du code en appliquant une série de transformations de refactoring sans affecter le comportement observable du code. Cela est vrai. Récemment, je suis également tombé sur une définition de Martin Fowler dans son livre "Améliorer la conception des codes existants". où il décrit remaniement comme "faire de grands changements à petits pas". Il décrit remaniement comme une modification du code n'affectant pas son fonctionnement, mais il insiste sur le fait que cela doit se faire par petites étapes.

Le livre préconise également que remaniement n'affecte pas le fonctionnement du code et souligne qu'elle n'a aucun effet sur la réussite des tests à tout moment. Il décrit étape par étape comment effectuer en toute sécurité remaniement. J'ai aimé son livre parce qu'il décrit des astuces simples qui peuvent être utilisées dans le travail de tous les jours.

Pourquoi avons-nous besoin d'un remaniement ?

 Le plus souvent, vous pouvez en avoir besoin lorsque vous souhaitez introduire une nouvelle fonctionnalité et que le code dans sa version actuelle ne le permet pas ou qu'il serait plus difficile de le faire sans modifier le code. Elle est également utile lorsque l'ajout de nouvelles fonctionnalités n'est pas rentable en termes de temps, c'est-à-dire qu'il serait plus rapide de réécrire le code à partir de zéro. Je pense que l'on oublie parfois que remaniement peut rendre le code plus propre et plus lisible. Martin écrit dans son livre qu'il effectue des remaniements lorsqu'il sent des odeurs désagréables dans le code et, comme il le dit lui-même, qu'il n'y a pas d'autres solutions que de remanier le code, "Il laisse toujours de la place pour le meilleur. Et il m'a surpris ici en considérant le refactoring comme un élément du travail quotidien du code. Pour moi, les codes sont souvent incompréhensibles, les lire est un peu une expérience car le code est souvent peu intuitif.

La caractéristique d'un programme bien conçu est sa modularitéGrâce à la modularité, il suffit de ne connaître qu'une petite partie du code pour introduire la plupart des modifications. La modularité facilite également l'intégration de nouvelles personnes et leur permet de travailler plus efficacement. Pour parvenir à cette modularité, les éléments de programme apparentés doivent être regroupés, les connexions étant compréhensibles et faciles à trouver. Il n'existe pas de règle empirique unique sur la manière d'y parvenir. Au fur et à mesure que l'on comprend mieux comment le code est censé fonctionner, on peut regrouper les éléments, mais il faut aussi parfois tester et vérifier.

L'une des règles du refactoring en YAGNIIl s'agit d'un acronyme pour "You Aren't Gonna Need It" (vous n'en aurez pas besoin), qui provient de l'anglais "You Aren't Gonna Need It". Programmation eXtreme (XP) utilisé principalement dans Agile développement de logiciels équipes. Pour faire court, YAGNI dit qu'il ne faut faire que les choses les plus récentes. Cela signifie essentiellement que même si quelque chose peut être nécessaire à l'avenir, il ne faut pas le faire tout de suite. Mais nous ne pouvons pas non plus bloquer les extensions futures et c'est là que la modularité devient importante.

Lorsque l'on parle de remaniementil convient de mentionner l'un des éléments les plus essentiels, à savoir les tests. En effet, en remaniementNous avons besoin de savoir que le code fonctionne toujours, parce que remaniement ne modifie pas son fonctionnement, mais sa structure, de sorte que tous les tests doivent être réussis. Il est préférable d'exécuter des tests pour la partie du code sur laquelle nous travaillons après chaque petite transformation. Cela nous permet de confirmer que tout fonctionne comme il se doit et de réduire la durée de l'ensemble de l'opération. C'est ce dont Martin parle dans son livre : exécuter des tests aussi souvent que possible afin de ne pas prendre du recul et perdre du temps à chercher une transformation qui a cassé quelque chose.

Refonte du code Sans test, c'est un vrai calvaire et il y a de grandes chances que quelque chose ne fonctionne pas. Si c'est possible, il serait préférable d'ajouter au moins quelques tests de base qui nous donneront un peu d'assurance que le code fonctionne.

Les transformations énumérées ci-dessous ne sont que des exemples, mais elles sont très utiles dans la programmation quotidienne :

Exemple

Il s'agit d'un article sur remaniement et un exemple est nécessaire. Je veux montrer un exemple simple de refactorisation ci-dessous avec l'utilisation de Remplacer la déclaration imbriquée et Remplacement du polymorphisme d'instruction conditionnelle. Supposons que nous ayons une fonction de programme qui renvoie un hachage contenant des informations sur la manière d'arroser les plantes dans la vie réelle. Ces informations se trouveraient probablement dans le modèle, mais pour cet exemple, elles se trouvent dans la fonction.

def watering_info(plant)
     result = {}
     if plant.is_a ? Suculent || plant.is_a ? Cactus
         result = { water_amount : "Un petit peu" , how_to : "Par le bas", durée de l'arrosage : "2 semaines" }
     elsif plant.is_a ? Alocasia || plant.is_a ? Maranta
         result = { water_amount : "Grande quantité", how_to : "Comme vous préférez", watering_duration : "5 jours" }
     elsif plant.is_a ? Peperomia
         result = { water_amount : "Quantité d'eau",
             how_to : "Par le bas ! ils n'aiment pas l'eau sur les feuilles",
             watering_duration : "1 semaine" }
     else
         result = { water_amount : "Quantité d'eau",
             how_to : "Comme vous le souhaitez",
             watering_duration : "1 semaine"
             }
     fin
     retourner le résultat
 fin

L'idée est de changer pour revenir :

if plant.isa ? Suculent || plant.isa ? Cactus

     result = { wateramount : "Un peu" , howto : "Depuis le bas",

Pour

return { water_amount : "Un petit peu" , how_to : "Depuis le bas",watering_duration : "2 semaines" } if plant.is_a ? Suculent || plant.is_a ? Cactus

return { eaumontant : "Un peu", commentà : "De bas en haut", arrosagedurée : "2 semaines" } if plant.isa ? Suculent || plant.is_a ? Cactus

Et ainsi de suite, jusqu'à ce que nous arrivions à une fonction qui ressemble à ceci :

def watering_info(plant)

return result = { wateramount : "Un petit peu" , howto : "Depuis le bas", durée de l'arrosage : "2 semaines" } if plant.isa ? Suculent || plant.is_a ? Cactus

return result = { wateramount : "Grande quantité", howto : "Comme vous le souhaitez", wateringduration : "5 jours" } if plant.isa ? Alocasia || plant.is_a ? Maranta

return result = { water_amount : "Quantité d'eau",

          howto : "Par le bas ! ils n'aiment pas l'eau sur les feuilles",
          wateringduration : "1 semaine" } if plant.is_a ? Peperomia

return result = { water_amount : "Quantité d'eau",

          how_to : "Comme vous le souhaitez",

          watering_duration : "1 semaine"

          }

fin

 À la toute fin, nous avions déjà un résultat de retour. Une bonne habitude consiste à procéder étape par étape et à tester chaque changement. Vous pourriez remplacer ce bloc if par un switch case et cela aurait immédiatement l'air mieux, et vous n'auriez pas à vérifier tous les ifs à chaque fois. Cela ressemblerait à ceci :

def watering_info(plant)

swich plant.class.to_string

case Suculente, Cactus

     { wateramount : "Un peu" , howto : "Par le bas", watering_duration : "2 semaines" }

cas Alocasia, Maranta

     { wateramount : "Grande quantité", howto : "Comme vous le souhaitez", watering_duration : "5 jours" }

cas Peperomia

     { water_amount : "Quantité d'eau",

          how_to : "Par le bas ! ils n'aiment pas l'eau sur les feuilles",

          watering_duration : "1 semaine" }

else

     { water_amount : "Dicent amount",

            how_to : "Comme vous préférez",

       watering_duration : "1 semaine" }

fin

fin

Vous pouvez ensuite appliquer le Remplacement du polymorphisme d'instruction conditionnelle. Il s'agit de créer une classe avec une fonction qui renvoie la bonne valeur et qui les place à l'endroit approprié.

classe Suculente

...

def watering_info()

     return { quantité d'eau : "Un petit peu" , howto : "Depuis le bas", watering_duration : "2 semaines" }

fin

fin

classe Cactus

...

def watering_info()

     return { quantité d'eau : "Un petit peu" , howto : "Depuis le bas", watering_duration : "2 semaines" }

fin

fin

classe Alocasia

...

def watering_info

     return { wateramount : "Grande quantité", howto : "Comme vous le souhaitez", watering_duration : "5 jours" }

fin

fin

classe Maranta

...

def watering_info

     return { wateramount : "Grande quantité", howto : "Comme vous le souhaitez", watering_duration : "5 jours" }

fin

fin

classe Peperomia

...

def watering_info

     return {montant_d'eau : "Montant de l'arrosage",

      how_to : "Par le bas ! ils n'aiment pas l'eau sur les feuilles",

      watering_duration : "1 semaine" }

fin

fin

classe Plant

...

def watering_info

     return {montant_d'eau : "Montant de l'arrosage",

              how_to : "Comme vous préférez",

              watering_duration : "1 semaine" }

fin

fin

Et dans la fonction principale watering_infofunction, le code ressemblera à ceci :

def watering_info(plant)

    plant.map(&:watering_info)

end

Bien entendu, cette fonction peut être supprimée et remplacée par son contenu. Avec cet exemple, j'ai voulu présenter le fonctionnement général de la fonction modèle de remaniement.

Résumé

Refonte est un vaste sujet. J'espère que cet article vous a donné envie d'en savoir plus. Ces articles compétences en matière de refonte vous aider à attraper vos bogues et à améliorer votre atelier de code propre. Je recommande la lecture du livre de Martin (Improving the Design of Existing Code), qui est un ensemble de règles assez basiques et utiles de remaniement. L'auteur montre différentes transformations étape par étape avec une explication complète et une motivation, ainsi que des conseils pour éviter les erreurs. remaniement. Grâce à sa polyvalence, c'est un livre idéal pour les frontend et les . développeurs backend.

Devenir développeur Ruby junior

Lire la suite

GraphQL Ruby. Qu'en est-il des performances ?

Rails et autres moyens de transport

Développement Rails avec TMUX, Vim, Fzf + Ripgrep

fr_FRFrench