Fermer

août 2, 2021

Stratégie, tests de régression et maintenance (partie 2) —


Résumé rapide ↬

Après avoir analysé la base de code CSS et ses faiblesses, et la direction ayant donné son feu vert au projet de refactoring, il est temps de commencer à refactoriser la base de code. Une équipe doit se mettre d'accord sur les normes de code interne et les meilleures pratiques, planifier la stratégie de refactorisation et définir les tâches individuelles. Pour rendre l'ensemble du processus fluide et encore plus efficace, il est recommandé de mettre en place une suite de tests de régression visuels et un plan de maintenance pour appliquer les nouvelles normes et meilleures pratiques à l'avenir.

Dans la Partie 1nous avons couvert les effets secondaires d'une base de code CSS de mauvaise qualité sur les utilisateurs finaux, les équipes de développement et la direction. La maintenance, l'extension et l'utilisation d'une base de code de faible qualité sont difficiles et nécessitent souvent du temps et des ressources supplémentaires. Avant de présenter la proposition de refactorisation à la direction et aux parties prenantes, il peut être utile de soutenir la suggestion avec des données concrètes sur la santé de la base de code – non seulement pour convaincre le service de gestion, mais aussi pour avoir un objectif mesurable pour le processus de refactoring.

Supposons que la direction ait approuvé le projet de refactoring CSS. L'équipe de développement a analysé et identifié les faiblesses de la base de code CSS et a défini des objectifs cibles pour le refactor (taille de fichier, spécificité, définitions de couleurs, etc.). Dans cet article, nous approfondirons le processus de refactorisation lui-même et couvrirons la stratégie de refactorisation incrémentielle, les tests de régression visuelle et la maintenance de la base de code refactorisée.

Préparation et planification

Avant de commencer le processus de refactorisation, l'équipe doit passer en revue les problèmes de base de code et  données d'audit de santé CSS (taille du fichier CSS, complexité du sélecteur, propriétés dupliquées et déclarations, etc.) et discuter des problèmes individuels sur la façon de les aborder et les défis s'attendre à. Ces problèmes et défis sont spécifiques à la base de code et peuvent rendre le processus de refactorisation ou les tests difficiles. Comme conclu dans l'article précédentil est important d'établir des règles internes et des normes de base de code et de les conserver documentés pour s'assurer que l'équipe est sur la même longueur d'onde et a une approche plus unifiée et standardisée du refactoring. .

L'équipe doit également décrire les tâches de refactorisation individuelles et fixer les délais pour terminer le projet de refactorisation, en tenant compte des tâches en cours et en s'assurant que le projet de refactorisation n'empêche pas l'équipe de traiter des tâches urgentes ou de travailler sur les fonctionnalités prévues. Avant d'estimer la durée et la charge de travail du projet de refactorisation, l'équipe doit consulter la direction sur les plans à court terme et ajuster ses estimations et sa charge de travail en fonction des fonctionnalités planifiées et des procédures de maintenance régulières.

Contrairement aux fonctionnalités régulières et aux bogues. correctifs, le processus de refactorisation donne peu ou pas de changements visibles et mesurables sur le front-end, et la direction ne peut pas suivre les progrès par elle-même. Il est important d'établir une communication transparente pour tenir la direction et les autres parties prenantes du projet informées de l'avancement et des résultats de la refactorisation. Des outils d'espace de travail collaboratif en ligne tels que Miro ou MURAL peuvent également être utilisés pour une communication et une collaboration efficaces entre les membres de l'équipe et la direction, ainsi qu'un outil de gestion des tâches simple et rapide.

Christoph Reinartz a souligné l'importance de la transparence et d'une communication claire pendant que l'équipe de trivago travaillait sur le projet de refactoring CSS. notre seule arme. Nous avons décidé de créer un tableau Kanban très simple, d'établir un stand-up de projet et un canal de projet Slack, et de tenir la direction et l'entreprise à jour via notre réseau interne de distribution sociale. "

 Simple, clair et efficace Tableau Kanban utilisé pour la refactorisation CSS à grande échelle chez trivago. (Image de trivago)

Tableau Kanban simple, clair et efficace utilisé pour la refactorisation CSS à grande échelle chez trivago. (Image de trivago) ( Grand aperçu)

L'élément le plus crucial de la planification du processus de refactorisation est de maintenir la portée de la tâche de refactorisation CSS aussi petite que possible. Cela rend les tâches plus gérables et plus faciles à tester et à intégrer.

Harry Roberts appelle ces tâches des "tunnels de refactoring". Par exemple, la refactorisation de l'ensemble de la base de code pour suivre la méthodologie BEM en une seule fois peut entraîner une amélioration considérable de la base de code et du processus de développement. Cela peut sembler être une simple tâche de recherche et de remplacement au début. Cependant, cette tâche affecte tous les éléments de chaque page (portée élevée) et l'équipe ne peut pas « voir la lumière au bout du tunnel » tout de suite ; beaucoup de choses peuvent se briser dans le processus et des problèmes inattendus peuvent ralentir la progression et personne ne peut dire quand la tâche va être terminée. L'équipe peut passer des jours ou des semaines à travailler dessus et risquer de se heurter à un mur, d'accumuler des dettes techniques supplémentaires ou de rendre la base de code encore moins saine. L'équipe finit par abandonner la tâche de recommencer, perdant du temps et des ressources dans le processus.

En revanche, améliorer uniquement le composant de navigation CSS est une tâche de plus petite envergure et est beaucoup plus gérable et faisable. Il est également plus facile à tester et à vérifier. Cette tâche peut être accomplie en quelques jours. Même avec des problèmes et des défis potentiels qui ralentissent la tâche, les chances de réussite sont élevées. L'équipe peut toujours « voir le bout du tunnel » pendant qu'elle travaille sur la tâche, car elle sait que la tâche sera terminée une fois que le composant aura été remanié et que tous les problèmes liés au composant auront été résolus.

Enfin, l'équipe doit se mettre d'accord sur la stratégie de refactorisation et la méthode de test de régression. C'est là que le processus de refactorisation devient difficile — la refactorisation doit être aussi rationalisée que possible et ne doit pas introduire de régressions ou de bogues.

Plongeons-nous dans l'une des stratégies de refactorisation CSS les plus efficaces et voyons comment peut l'utiliser pour améliorer la base de code rapidement et efficacement.

Plus après le saut ! Continuez à lire ci-dessous ↓

Incremental Refactoring Strategy

Le refactoring est un processus difficile qui est beaucoup plus complexe que la simple suppression du code hérité et son remplacement par le refactorisé code. Il s'agit également d'intégrer la base de code refactorisée à la base de code héritée et d'éviter les régressions, les suppressions accidentelles de code, les conflits de feuilles de style, etc. Pour éviter ces problèmes, je recommanderais d'utiliser une stratégie de refactorisation incrémentielle (ou granulaire).

Dans à mon avis, c'est l'une des stratégies de refactoring CSS les plus sûres, les plus logiques et les plus recommandées que j'ai rencontrées jusqu'à présent. Harry Roberts a décrit cette stratégie en 2017. et c'est ma stratégie personnelle de refactoring CSS depuis que j'en ai entendu parler pour la première fois.

Examinons cette stratégie étape par étape.

Étape 1 : Choisissez un composant et développez-le de manière isolée

Cette stratégie repose sur des tâches individuelles de faible portée, ce qui signifie que nous devons refactoriser le projet composant par composant. Il est recommandé de commencer par des tâches de faible portée (composants individuels), puis de passer à des tâches de plus grande portée (styles globaux).

En fonction de la structure du projet et des sélecteurs CSS, les styles de composants individuels consistent en une combinaison de composants (classe) styles et styles globaux (élément étendu). Les styles de composants et les styles globaux peuvent être à l'origine des problèmes de base de code et peuvent nécessiter une refactorisation.

Jetons un coup d'œil aux problèmes de base de code CSS plus courants qui peuvent affecter un seul composant. Les sélecteurs de composants (classes) peuvent être trop complexes, difficiles à réutiliser ou peuvent avoir une spécificité élevée et appliquer le balisage ou la structure spécifique. Les sélecteurs globaux (d'élément) peuvent être gourmands et laisser échapper des styles indésirables dans plusieurs composants qui doivent être annulés avec des sélecteurs de composants à haute spécificité.

 État de départ de la base de code CSS et HTML que nous voulons refactoriser. Le balisage des composants de la carte se compose de plusieurs éléments HTML. Les styles de composants de carte consistent en une combinaison de styles de sélecteur de classe et de styles de sélecteur d'élément global.

État de départ de la base de code CSS et HTML que nous voulons refactoriser. Le balisage des composants de la carte se compose de plusieurs éléments HTML. Les styles de composants de carte consistent en une combinaison de styles de sélecteur de classe et de styles de sélecteur d'élément global. ( Grand aperçu)

Après avoir choisi un composant à refactoriser (une tâche de portée inférieure), nous devons le développer dans un environnement isolé, loin du code hérité, de ses faiblesses et des sélecteurs conflictuels. C'est également une bonne occasion d'améliorer le balisage HTML, de supprimer les imbrications inutiles, d'utiliser de meilleurs noms de classe CSS, d'utiliser des attributs ARIA, etc. cela, vous pouvez même utiliser CodePen pour reconstruire les composants individuels. Pour éviter les conflits avec les noms de classe hérités et pour séparer plus clairement le code refactorisé du code hérité, nous utiliserons un préfixe rf- sur les sélecteurs de nom de classe CSS.

Création du composant de carte refactorisé CSS et Balisage isolé.

Création du composant de carte refactorisé CSS et balisage isolément. ( Grand aperçu)

Étape 2 : Fusionner avec la base de code héritée et corriger les bogues

Une fois que nous avons fini de reconstruire le composant dans un environnement isolé, nous devons remplacer le balisage HTML hérité par un balisage refactorisé (nouvelle structure HTML, noms de classe, attributs , etc.) et ajoutez le composant CSS refactorisé aux côtés du CSS hérité.

Nous ne voulons pas agir trop hâtivement et supprimer les styles hérités tout de suite. En effectuant trop de modifications simultanément, nous perdrons la trace des problèmes qui pourraient survenir en raison des bases de code conflictuelles et des modifications multiples. Pour l'instant, remplaçons le balisage et ajoutons du CSS refactorisé à la base de code existante et voyons ce qui se passe. Gardez à l'esprit que le CSS refactorisé doit avoir le préfixe .rf- dans leurs noms de classe pour éviter les conflits avec la base de code héritée. . Les composants hérités et les styles globaux appliquent des effets secondaires indésirables en raison des sélecteurs globaux ou d'éléments à grande portée. Les composants hérités et les styles globaux appliquent des effets secondaires indésirables en raison des sélecteurs globaux ou d'éléments de grande portée. ( Grand aperçu)

Le CSS et les styles globaux des composants hérités peuvent provoquer des effets secondaires inattendus et laisser échapper des styles indésirables dans le composant refactorisé. La base de code refactorisée pourrait manquer le CSS défectueux qui était nécessaire pour annuler ces effets secondaires. En raison de ces styles ayant une portée plus large et affectant éventuellement d'autres composants, nous ne pouvons pas simplement modifier directement le code problématique. Nous devons utiliser une approche différente pour résoudre ces conflits.

Nous devons créer un fichier CSS séparé, que nous pouvons nommer overrides.css ou defend.css qui contiendra code hacky à haute spécificité qui combat les styles indésirables de la base de code héritée.

overrides.css qui contiendra des sélecteurs à haute spécificité qui garantissent que la base de code refactorisée fonctionne avec la base de code héritée. Il ne s'agit que d'un fichier temporaire et il sera supprimé une fois le code hérité supprimé. Pour l'instant, ajoutez les remplacements de style hautement spécifiques pour désactiver les styles appliqués par les styles hérités et tester si tout fonctionne comme prévu.

Nous ajoutons overrides.css pour lutter contre les effets secondaires indésirables. Ce fichier contient un code hautement spécifique qui remplace les styles hérités.

Nous ajoutons overrides.css pour lutter contre les effets secondaires indésirables. Ce fichier contient un code hautement spécifique qui remplace les styles hérités. ( Grand aperçu)

Si vous remarquez des problèmes, vérifiez s'il manque des styles au composant refactorisé en revenant à l'environnement isolé ou si d'autres styles fuient dans le composant et doivent être remplacés. Si le composant a l'air et fonctionne comme prévu après l'ajout de ces remplacements, supprimez le code hérité du composant refactorisé et vérifiez si des problèmes surviennent. Supprimez le code hacky associé de overrides.css et testez à nouveau.

Les styles des composants de la carte héritée peuvent désormais être supprimés en toute sécurité, ainsi que (certains) styles de overrrides.css qui ont aidé à lutter contre les effets secondaires de ceux-ci. sélecteurs. Cependant, les sélecteurs CSS globaux peuvent toujours appliquer des effets secondaires indésirables, nous ne pouvons donc pas supprimer complètement ce fichier tant que nous n'avons pas également remanié les styles globaux. ]overrrides.css</code> qui a aidé à combattre les effets secondaires de ces sélecteurs. Cependant, les sélecteurs CSS globaux peuvent toujours appliquer des effets secondaires indésirables, nous ne pouvons donc pas supprimer complètement ce fichier tant que nous n'avons pas remanié les styles globaux également. (<a href= Grand aperçu

)

Selon le cas, vous ne pourrez probablement pas supprimer tous les remplacements immédiatement. Par exemple, si le problème réside dans un sélecteur d'élément global qui diffuse des styles dans d'autres composants qui doivent également être refactorisés. Pour ces cas, nous ne prendrons pas le risque d'étendre la portée de la tâche et de la demande d'extraction, mais plutôt attendre que tous les composants aient été refactorisés et aborder les tâches à grande portée après avoir supprimé la même dépendance de style à partir de tous les autres composants.

D'une certaine manière, vous pouvez traiter le fichier overrides.css comme votre liste TODO de fortune pour refactoriser des sélecteurs d'éléments gourmands et à grande portée. Vous devriez également envisager de mettre à jour le tableau des tâches pour inclure les problèmes nouvellement découverts. Assurez-vous d'ajouter des commentaires utiles dans le fichier overrides.css afin que les autres membres de l'équipe soient sur la même longueur d'onde et sachent instantanément pourquoi le remplacement a été appliqué et en réponse à quel sélecteur.

/* remplacements. css */
/* Réinitialise les dimensions imposées par ".sidebar > div" dans "sidebar.css" */
.sidebar > .card {
  min-largeur : 0 ;
}

/* Réinitialise la taille de la police imposée par ".hero-container" dans "hero.css"*/
.carte {
  taille de la police : 18px ;
}

Étape 3 : Tester, fusionner et répéter

Une fois que le composant refactorisé a été intégré avec succès à la base de code héritée, créez une demande d'extraction et exécutez un test de régression visuel automatisé pour détecter les problèmes qui auraient pu passer inaperçus et les corriger avant de les fusionner dans l'une des branches principales de git. Les tests de régression visuelle peuvent être considérés comme la dernière ligne de défense avant de fusionner les demandes d'extraction individuelles. Nous aborderons les tests de régression visuelle plus en détail dans l'une des prochaines sections de cet article.

Maintenant, rincez et répétez ces trois étapes jusqu'à ce que la base de code ait été refactorisée et que overrides.css soit vide et puisse être supprimé en toute sécurité.

Étape 4 : Passer des composants aux styles globaux

Supposons que nous ayons refactorisé tous les composants individuels à faible portée et que tout ce qui reste dans le fichier overrides.css est lié aux sélecteurs d'éléments globaux à grande portée. Il s'agit d'un cas très réaliste, d'après l'expérience, car de nombreux problèmes CSS sont causés par des sélecteurs d'éléments à grande portée qui diffusent des styles dans plusieurs composants.

En s'attaquant d'abord aux composants individuels et en les protégeant des effets secondaires CSS globaux à l'aide overrides.cssnous avons rendu ces tâches de portée plus élevée beaucoup plus gérables et moins risquées. Nous pouvons passer à la refactorisation des styles CSS globaux de manière plus sûre qu'auparavant et supprimer les styles dupliqués des composants individuels et les remplacer par des styles d'éléments et des utilitaires généraux – boutons, liens, images, conteneurs, entrées, grilles, etc. Ce faisant, nous allons supprimer progressivement le code de notre fichier TODO improvisé overrides.css et le code dupliqué répété dans plusieurs composants.

Appliquons les trois mêmes étapes de la stratégie de refactorisation incrémentielle, en commençant par développer et tester les styles de manière isolée.

Refactoriser les styles globaux de manière isolée. Si ces styles globaux utilisent des sélecteurs d'éléments sans balisage spécial ou nom de classe appliqué, le balisage ne changera pas et seul le CSS refactorisé doit être déplacé vers la base de code.

Refactoring des styles globaux de manière isolée. Si ces styles globaux utilisent des sélecteurs d'éléments sans aucun balisage spécial ou nom de classe appliqué, le balisage ne changera pas et seul le CSS refactorisé doit être déplacé vers la base de code. ( Grand aperçu)

Ensuite, nous devons ajouter les styles globaux refactorisés à la base de code. Nous pouvons rencontrer les mêmes problèmes lors de la fusion des deux bases de code et nous pouvons ajouter les remplacements nécessaires dans overrides.css. Cependant, cette fois, nous pouvons nous attendre à ce que, à mesure que nous supprimons progressivement les styles hérités, nous puissions également supprimer progressivement les remplacements que nous avons introduits pour lutter contre ces effets secondaires indésirables.

L'inconvénient du développement de composants dans l'isolement peuvent être trouvés dans des styles d'éléments partagés entre plusieurs composants – éléments de guide de style tels que boutons, entrées, en-têtes, etc. Lorsque nous les développons indépendamment de la base de code héritée, nous n'avons pas accès au guide de style hérité. De plus, nous ne voulons pas créer ces dépendances entre la base de code héritée et la base de code refactorisée.

C'est pourquoi il est plus facile de supprimer les blocs de code dupliqués et de déplacer ces styles dans des composants et des sélecteurs de guide de style distincts et plus généraux ultérieurement. Cela nous permet d'aborder ces changements à la fin et avec le moindre risque car nous travaillons avec une base de code beaucoup plus saine et cohérente, au lieu de la base de code héritée désordonnée, incohérente et boguée. Bien sûr, des effets secondaires et des bogues involontaires peuvent toujours se produire et ceux-ci doivent être détectés avec les outils de test de régression visuel que nous couvrirons dans l'une des sections suivantes de l'article.

Fusionner le CSS global refactorisé avec la base de code. et mettre à jour overrides.css pour supprimer les effets secondaires indésirables de la base de code héritée.

Fusionner le CSS global remanié avec la base de code et mettre à jour overrides.css pour supprimer les effets secondaires indésirables de la base de code héritée. ( Grand aperçu)

Lorsque la base de code a été complètement remaniée et que nous avons supprimé tous les éléments TODO de fortune du fichier overrides.cssnous pouvons la supprimer en toute sécurité et nous nous retrouvons avec la base de code CSS refactorisée et améliorée.[19659065]Suppression des styles globaux hérités et overrides.css une fois la base de code complètement refactorisée. »/>

Suppression des styles globaux hérités et overrides.css une fois la base de code complètement refactorisée. ( Grand aperçu)

Exemple de refactorisation CSS incrémentielle

Utilisons la stratégie de refactorisation incrémentielle pour refactoriser une page simple composée d'un élément de titre et de deux composants de carte dans un composant de grille. Chaque élément de carte se compose d'une image, d'un titre, d'un sous-titre, d'une description et d'un bouton et est placé dans une grille à 2 colonnes avec un espacement horizontal et vertical.

Voir le stylo [Refactoring CSS — example 1](https://codepen.io/ smashingmag/pen/KKmRaQJ) par Adrian Bece.

Voir le Pen Refactoring CSS — exemple 1 par Adrian Bece.

Comme vous pouvez le voir , nous avons une base de code CSS sous-optimale avec divers problèmes de spécificité, des remplacements, du code dupliqué et certains cas de styles d'annulation.

h1, h2 {
    marge supérieure : 0 ;
    marge inférieure : 0,75 em ;
    hauteur de ligne : 1.3 ;
    taille de la police : 2,5 em ;
    famille de polices : serif ;
}

/* ... */

.carte h2 {
  famille de polices : Helvetica, Arial, sans-serif ;
  marge inférieure : 0,5 em ;
  hauteur de ligne : initiale ;
  taille de la police : 1,5 em ;
}

Le composant .card utilise également des sélecteurs à haute spécificité qui appliquent une structure HTML spécifique et permettent aux styles de s'infiltrer dans d'autres éléments à l'intérieur des composants de la carte.

/* L'élément doit suivre ce code HTML spécifique. structure pour appliquer ces styles */
.card h2 > petit {
 /* ... */
}

/* Ces styles s'infiltreront dans tous les éléments div d'un composant de carte */
.card div {
  rembourrage: 2em 1.5em 1em;
}

/* Ces styles vont s'infiltrer dans tous les éléments p d'un composant de carte */
.carte p {
  taille de la police : 0.9em ;
  marge supérieure : 0 ;
}

Nous allons commencer par les composants enfants les plus bas et les plus hauts, refactorisons donc le composant card qui est l'enfant le plus haut de la page, c'est-à-dire que le composant card est un enfant du composant grid. Nous développerons le composant de carte de manière isolée et utiliserons les normes et les meilleures pratiques convenues. valeurs de couleur codées en ligne. Nous ajouterons également du CSS pour nous aider à développer le composant, que nous ne copierons pas dans la base de code existante.

Voir le Pen [Refactoring CSS — example 2 (isolated card component)](https://codepen.io/smashingmag/pen/JjNvELK) par Adrian Bece.

Voir le Pen Refactoring CSS — exemple 2 (composant de carte isolée) par Adrian Bece.

Nous utilisons le rf- pour les nouvelles classes CSS afin que nous puissions éviter les conflits de noms de classe et différencier les styles refactorisés des styles hérités pour une meilleure organisation du code et un débogage plus simple. Cela nous permettra également de suivre la progression du refactoring.

.rf-card {
  couleur : var(--color-text);
  arrière-plan : var(--couleur-arrière-plan);
}

.rf-card__figure {
  marge : 0 ;
}

.rf-card__title {
  hauteur de ligne : 1.3 ;
  marge supérieure : 0 ;
  marge inférieure : 0,5 em ;
}

Nous allons remplacer le balisage hérité par le balisage refactorisé et ajouter les styles refactorisés à la base de code CSS. Nous n'allons pas encore supprimer les styles hérités. Nous devons vérifier si des styles d'autres sélecteurs hérités ont fui dans le composant refactorisé.

En raison des problèmes avec les sélecteurs de grande envergure mondiaux, nous avons des remplacements de style indésirables qui fuient dans le composant refactorisé – les propriétés de la police de titre ont été réinitialisées et la taille de la police à l'intérieur du composant de carte a changé.

.grid {
  /* ... */
  taille de la police : 24 px ;
}

h1, h2 {
    /* ... */
    taille de la police : 2,5 em ;
    famille de polices : Géorgie, « Times New Roman », Times, serif ;
}

Voir le stylet [Refactoring CSS — example 3 (merge legacy and refactor)](https://codepen.io/smashingmag/pen/NWjMdYO) de Adrian Bece.

Voir le stylet Refactoring CSS — exemple 3 ( fusionner l'héritage et refactoriser) par Adrian Bece.

Nous devons ajouter des remplacements de style à overrides.css pour supprimer les effets secondaires indésirables des autres sélecteurs. Nous allons également commenter chaque remplacement afin de savoir quel sélecteur a causé le problème.

/* Empêche le remplacement de .grid font-size */
.rf-card {
  taille de la police : 16px ;
}

/* Empêche le remplacement des polices h1, h2 */
.rf-card__title {
  famille de polices : Helvetica, Arial, sans-serif ;
  taille de la police : 1,5 em ;
}

Nous savons maintenant que nous allons devoir refactoriser le composant .grid et le sélecteur global h1, h2 à un moment donné. C'est pourquoi nous pouvons le traiter comme une liste TODO – ces styles divulgués peuvent causer des problèmes dans d'autres composants, ils sont objectivement défectueux et appliquent des styles qui sont réinitialisés dans la majorité des cas d'utilisation.

Voir le Pen [Refactoring CSS — example 4 (adding overrides.css)](https://codepen.io/smashingmag/pen/zYwjNjG) par Adrian Bece.

Voir le Pen Refactoring CSS — exemple 4 (ajout de overrides.css) par Adrian Bece.

Supprimons les styles hérités .card du projet et voyons si tout va bien. Nous pouvons vérifier si nous pouvons supprimer des styles de overrides.csscependant, nous savons tout de suite qu'aucun des remplacements n'est lié aux styles de composants de carte hérités, mais à d'autres composants et sélecteurs d'éléments.

Voir le Pen [Refactoring CSS — example 5 (Removing legacy component styles)](https://codepen.io/smashingmag/pen/yLbjgjW) par Adrian Bece.

Voir le Pen Refactoring CSS — exemple 5 (Suppression des styles de composants hérités) par Adrian Bece.

Maintenant que le composant de la carte a été remanié, vérifions notre liste de TODO de fortune et voyons ce qu'il faut faire ensuite. Nous avons le choix entre :

  • Refactoriser le composant de grille — portée inférieure (tunnel court),
  • Refactoriser les styles globaux — portée supérieure (tunnel plus long).

Nous allons utiliser le composant de portée la plus faible, la grille dans ce cas, et appliquer la même approche. Nous allons commencer par développer le composant de grille de manière isolée. Nous pouvons utiliser le balisage du composant de carte pour les tests, les styles de composant de carte n'affecteront pas la grille et ne nous aideront pas à développer le composant, nous pouvons donc les laisser en dehors du composant isolé pour un balisage CSS plus simple.

Voir le Pen [Refactoring CSS — example 6 (refactoring grid component)](https://codepen.io/smashingmag/pen/JjNvEZK) par Adrian Bece.

Voir le Pen Refactoring CSS — exemple 6 (composant de grille de refactoring) par Adrian Bece.

Remplaçons le balisage HTML de la grille par le balisage refactorisé et ajoutons les styles refactorisés à la base de code CSS et vérifions si nous devons ajouter des styles à overrides.css pour atténuer tout conflit de feuille de style ou fuite de styles.

Voir le Pen [Refactoring CSS — example 7 (merged grid component, updated overrides.css, removed styles)](https://codepen.io/smashingmag/pen/KKmRaeE) par Adrian Bece.

Voir le Stylo Refactoring CSS — exemple 7 (composant de grille fusionné, overrides.css mis à jour, styles supprimés) par Adrian Bece.

W ous pouvons voir qu'aucun nouveau problème n'est apparu, nous pouvons donc procéder à la suppression des styles hérités .grid. Vérifions également si overrides.css contient des styles appliqués pour l'ancien sélecteur .grid.

/* Réinitialiser .grid font-size override */
.rf-card {
  taille de la police : 16px ;
}

C'est pourquoi il est utile de documenter les règles de dérogation. Nous pouvons supprimer ce sélecteur en toute sécurité et le déplacer sur le dernier élément de notre liste TODO de fortune – les sélecteurs d'éléments de titre. Nous allons répéter les mêmes étapes : nous allons créer un balisage refactorisé de manière isolée, remplacer le balisage HTML et ajouter les styles refactorisés à la feuille de style.

Galeries en vedette

.rf-title {
   famille de polices : Géorgie, « Times New Roman », Times, serif ;
}

.rf-title--size-regular {
    hauteur de ligne : 1.3 ;
    taille de la police : 2,5 em ;
}

.rf-title--spacing-regular {
    marge supérieure : 0 ;
    marge inférieure : 0,75 em ;
}

Nous vérifierons s'il y a des problèmes et confirmerons qu'aucun nouveau problème n'a été introduit par le balisage et la feuille de style mis à jour et nous supprimerons l'ancien sélecteur h1, h2 de la feuille de style. Enfin, nous allons vérifier overrides.css et supprimer les styles liés au sélecteur d'élément hérité.

Voir le Pen [Refactoring CSS — example 8 (element selectors)](https://codepen.io/smashingmag/pen/ VwbxPBW) par Adrian Bece.

Voir le Pen Refactoring CSS — exemple 8 (sélecteurs d'éléments) par Adrian Bece.

Le overrides.css est maintenant vide et nous avons remanié les composants card, grid et title dans notre projet. Notre base de code est beaucoup plus saine et cohérente par rapport au point de départ – nous pouvons ajouter des éléments au composant de grille et de nouvelles variations de titre sans avoir à annuler les styles divulgués.

Cependant, nous pouvons apporter quelques modifications. pour améliorer notre base de code. Comme nous avons développé les composants de manière isolée, nous avons probablement reconstruit plusieurs fois les mêmes composants du guide de style et créé du code dupliqué. Par exemple, un bouton est un composant de guide de style et nous avons étendu ces styles à un composant de carte.

/* Styles de bouton refactorisés étendus à un composant */
.rf-card__link {
  couleur : var(--color-text-negative);
  couleur d'arrière-plan : var(--color-cta);
  rembourrage : 1em ;
  affichage : flexible ;
  justifier-contenu : centre ;
  texte-décoration : aucun ;
  transformation de texte : majuscule ;
  interlettrage : 0,05 em ;
  font-weight : 600 ;
}

Si un autre composant utilise les mêmes styles de boutons, cela signifie que nous allons écrire les mêmes styles à chaque fois que nous les développerons de manière isolée. Nous pouvons refactoriser ces doublons dans un composant distinct .button et remplacer les styles de portée dupliqués par des styles de guide de style général. Cependant, nous avons déjà un sélecteur de bouton hérité .button qui doit être refactorisé, nous sommes donc également en mesure de supprimer le sélecteur de bouton hérité.

Même si nous passons à la refactorisation d'éléments de portée plus élevée, la base de code est beaucoup plus saine et cohérente par rapport au point de départ, donc le risque est plus faible et la tâche est beaucoup plus faisable. Nous n'avons pas non plus à craindre que les modifications apportées aux composants enfants les plus élevés remplacent toutes les modifications apportées au sélecteur général.

/* Styles de boutons hérités défectueux */
.bouton {
  bordure : 0 ;
  bloc de visualisation;
  largeur max : 200px !important;
  text-align : centre ;
  marge : 1em automatique ;
  rembourrage : 1em ;
  transformation de texte : majuscule ;
  interlettrage : 0,05 em ;
  curseur : pointeur ;
  font-weight : gras ;
  texte-décoration : aucun ;
}

.cta {
  max-width : aucun !important;
  marge inférieure : 0 ;
  couleur : #fff ;
  couleur de fond : rouge foncé ;
  marge supérieure : 1em ;
}

Nous pouvons utiliser la même approche incrémentielle pour le Nous allons reconstruire le composant bouton isolément, mettre à jour le balisage et ajouter les styles refactorisés à la feuille de style. Nous allons faire une vérification rapide des conflits et des bogues de feuille de style, remarquer que rien n'a changé et supprimer le balisage de bouton hérité et les styles de bouton de portée de composant.

.rf-button {
  affichage : flexible ;
  justifier-contenu : centre ;
  texte-décoration : aucun ;
  transformation de texte : majuscule ;
  interlettrage : 0,05 em ;
  font-weight : 600 ;
}

.rf-bouton--régulier {
   rembourrage : 1em ;
}

.rf-bouton--cta {
  couleur : var(--color-text-negative);
  couleur d'arrière-plan : var(--color-cta);
}
/* Avant - styles de boutons limités à un composant de carte */
View gallery

/* After - General styles from a button component */
View gallery

See the Pen [Refactoring CSS — example 9 (final result)](https://codepen.io/smashingmag/pen/yLbjgqd) by Adrian Bece.

See the Pen Refactoring CSS — example 9 (final result) by Adrian Bece.

Once the refactoring project has been completed, we can use search-and-replace to clean up the rf- prefixes in the codebase and treat the existing codebase as the new standard. That way, extending the codebase won’t introduce naming inconsistencies or force the rf- prefix naming that could cause issues for any future refactors.

Testing And Avoiding Regressions

Regardless of the refactor tasks’ scope size and how well the team follows the incremental refactoring strategy steps, bugs and regressions can happen. Ideally, We want to avoid introducing issues and regressions in the codebase — conflicting styles, missing styles, incorrect markup, leaked styles from other elements, etc.

Using automated visual regression testing tools like Percy or Chromatic on a Pull Request level can speed up testing, allow developers to address regressions quickly and early, and make sure that the bugs don’t end up on the live site. These tools can take screenshots of individual pages and components and compare changes in style and layout and notify developers of any visual changes that can happen due to changes in the markup or CSS.

Since the CSS refactor process shouldn’t result in any visual changes in usual cases and depending on the task and issues in the legacy codebase, the visual regression testing process can potentially be simple as checking if any visual changes happened at all and checking if these changes were intentional or unintentional.

Visual regression test example in Chromatic. Dimensions for this specific button variation have been unintentionally changed when the button component has been refactored. This issue has been caught when Pull Request has been created, so developers were able to address this issue early.

Visual regression test example in Chromatic. Dimensions for this specific button variation have been unintentionally changed when the button component has been refactored. This issue has been caught when Pull Request has been created, so developers were able to address this issue early. (Large preview)

Depending on the project, testing tools don’t need to be complex or sophisticated to be effective. While working on refactoring the Sundance Institute’s CSS codebase, the development team used a simple static style guide page generated by Jekyll to test the refactored components.

“One unintended consequence of executing the refactor in abstraction on a Jekyll instance was that we could now publish it to Github pages as a living style guide. This has become an invaluable resource for our dev team and for external vendors to reference.”

Once the CSS refactor tasks have been completed and the refactored code is ready for production, the team can also consider doing an A/B test to check the effect of the refactored codebase on users. For example, if the goal of the refactoring process was to reduce the overall CSS file size, the A/B test can potentially yield significant improvements for mobile users, and these results can also be beneficial to project stakeholders and management. That’s exactly how the team at Trivago approached the deployment of their large-scale refactoring project.

“(…) we were able to release the technical migration as an A/B Test. We tested the migration for one week, with positive results on mobile devices where mobile-first paid out and accepted the migration after only four weeks.”

Keeping Track Of Refactoring Progress

Kanban board, GitHub issues, GitHub project board, and standard project management tools can do a great job of keeping track of the refactoring progress. However, depending on the tools and how the project is organized, it may be difficult to estimate the progress on a per-page basis or do a quick check on which components need to be refactored.

This is where our .rf-prefixed CSS classes come in. Harry Roberts has talked about the benefits of using the prefix in detail. The bottom line is — not only do these classes allow developers to clearly separate the refactored CSS codebase from the legacy codebasebut also to quickly show the progress to the project managers and other project stakeholders on a per-page basis.

For example, management may decide to test the effects of the refactored codebase early by deploying only the refactored homepage code and they would want to know when the homepage components will be refactored and ready for A/B testing.

Instead of wasting some time comparing the homepage components with the available tasks on the Kanban board, developers can just temporarily add the following styles to highlight the refactored components which have the rf- prefix in their class names, and the components that need to be refactored. That way, they can reorganize the tasks and prioritize refactoring homepage components.

/* Highlights all refactored components */
[class*="rf-"] {
  outline: 5px solid green;
}

/* Highlights all components that havent been refactored */

body *:not([class]) {
  outline: 5px solid red;
}

Previous example of refactored card component with temporary highlight code added. Components that have been refactored are highlighted with the green outline, while components that may need to be refactored are highlighted with the red outline.

Previous example of refactored card component with temporary highlight code added. Components that have been refactored are highlighted with the green outline, while components that may need to be refactored are highlighted with the red outline. (Large preview)

Maintaining The Refactored Codebase

After the refactoring project has been completed, the team needs to make sure to maintain the codebase health for the foreseeable future — new features will be developed, some new features might even be rushed and produce technical debt, various bugfixes will also be developed, etc. All in all, the development team needs to make sure that the codebase health remains stable as long as they’re in charge of the codebase.

Technical debt which can result in potentially faulty CSS code should be isolated, documented, and implemented in a separate CSS file which is often named as shame.css.

It’s important to document the rules and best practices that were established and applied during the refactoring projects. Having those rules in writing allows for standardized code reviews, faster project onboarding for new team members, easier project handoff, etc.

Some of the rules and best practices can also be enforced and documented with automated code-checking tools like stylelint. Andrey Sitnik, the author of widely-used CSS development tools like PostCSS and Autoprefixer, has noted how automatic linting tools can make code reviews and onboarding easier and less stressful.

“However, automatic linting is not the only reason to adopt Stylelint in your project. It can be extremely helpful for onboarding new developers on the team: a lot of time (and nerves!) are wasted on code reviews until junior developers are fully aware of accepted code standards and best practices. Stylelint can make this process much less stressful for everyone.”

Additionally, the team can create a Pull Request template and include the checklist of standards and best practices and a link to the project code rules document so that the developers making the Pull Request can check the code themselves and make sure that it follows the agreed standards and best practices.

Conclusion

Incremental refactoring strategy is one of the safest and most recommended approaches when it comes to refactoring CSS. The development team needs to refactor the codebase component by component to ensure that the tasks have a low scope and are manageable. Individual components need to be then developed in isolation — away from the faulty code — and then merged with the existing codebase. The issues that may come up from the conflicting codebases can be solved by adding a temporary CSS file that contains all the necessary overrides to remove the conflicts in CSS styles. After that, legacy code for the target component can be removed and the process continues until all components have been refactored and until the temporary CSS file which contains the overrides is empty.

Visual regression testing tools like Percy and Chromatic can be used for testing and to detect any regressions and unwanted changes on the Pull Request level, so developers can fix these issues before the refactored code is deployed to the live site.

Developers can use A/B testing and use monitoring tools to make sure that the refactoring doesn’t negatively affect performance and user experience before finally launching the refactored project on a live site. Developers will also need to ensure that the agreed standards and best practices are used on the project continues to maintain the codebase health and quality in the future.

References

Smashing Editorial" width="35" height="46" loading="lazy" decoding="async(vf, yk, il)




Source link