Réusinage de code Go : quand et comment ne pas casser le projet
\nAvez-vous déjà ouvert votre ancien code Go et ressenti une légère nostalgie ? Des variables nommées a et b, des fonctions longues comme un écran, et la boucle principale de traitement des requêtes qui ressemble au labyrinthe du Minotaure. Cela vous parle ? Bienvenue dans le monde où le réusinage n'est pas un luxe, mais une nécessité.
Go est réputé pour sa simplicité et sa vitesse de compilation, mais cela ne signifie pas que le code s'écrit tout seul de manière parfaite. Tôt ou tard, chaque développeur se pose la question : « Quand est-il temps de mettre de l'ordre ? ». Dans cet article, nous allons voir comment faire du réusinage de code Go sans peur et sans reproche, avec des exemples concrets et des conseils de praticiens.
\n\nQuand le réusinage de code Go est nécessaire : les signaux d'alarme
\nLe réusinage ne consiste pas à « tout réécrire de zéro ». Il s'agit d'améliorer la structure interne sans modifier le comportement externe. Voici des signaux clairs qu'il est temps de sortir les outils :
\n- \n
- Le code sent mauvais (code smell) : duplication, fonctions longues, nombres magiques. \n
- Difficulté à ajouter de nouvelles fonctionnalités : chaque correctif casse les anciens tests. \n
- Tests lents : si les tests unitaires prennent plus de 10 secondes, la structure cloche. \n
- Beaucoup de if/else ou switch : surtout lorsque de nouveaux types apparaissent. \n
- Emboîtement sauvage :
if err != nil { if ... }— un enfer pour le débogage. \n
En Go, il est particulièrement important de surveiller la gestion des erreurs et les interfaces. Si vous vous surprenez à écrire interface{} là où un type concret est nécessaire, c'est un signal d'alarme.
Étapes du réusinage : du plan au commit
\nUn réusinage sans stratégie mène au chaos. Suivez un algorithme simple :
\n- \n
- Comprenez ce qui ne va pas. Écrivez une liste des problèmes : duplication, complexité, zones lentes. \n
- Écrivez des tests. Sans tests, le réusinage est une roulette russe. Utilisez
go testet couvrez les chemins critiques. \n - Faites de petits pas. Un bloc logique à la fois. Commitez après chaque modification réussie. \n
- Lancez les tests et les benchmarks. Assurez-vous que les performances n'ont pas chuté. \n
- Faites une revue de code. Un regard neuf d'un collègue trouvera ce que vous avez manqué. \n
Exemples pratiques de réusinage de code Go
\nLa théorie c'est bien, mais regardons du code concret. Ci-dessous, trois situations typiques et leurs solutions.
\n\n1. Éliminer la duplication à l'aide de fonctions
\nSupposons que vous ayez du code qui analyse une configuration et vérifie les erreurs de la même manière :
\n// Mauvais : duplication de la logique de vérification\nfunc loadConfig(path string) (*Config, error) {\n data, err := os.ReadFile(path)\n if err != nil {\n return nil, fmt.Errorf("read config: %w", err)\n }\n var cfg Config\n err = json.Unmarshal(data, &cfg)\n if err != nil {\n return nil, fmt.Errorf("parse config: %w", err)\n }\n return &cfg, nil\n}\n\nfunc loadSecrets(path string) (*Secrets, error) {\n data, err := os.ReadFile(path)\n if err != nil {\n return nil, fmt.Errorf("read secrets: %w", err)\n }\n var sec Secrets\n err = json.Unmarshal(data, &sec)\n if err != nil {\n return nil, fmt.Errorf("parse secrets: %w", err)\n }\n return &sec, nil\n}\nSolution : extraire la logique commune dans une fonction utilitaire.
\n// Bien : méthode unique pour lire et analyser du JSON\nfunc readJSON[T any](path string) (*T, error) {\n data, err := os.ReadFile(path)\n if err != nil {\n return nil, fmt.Errorf("read file %s: %w", path, err)\n }\n var result T\n err = json.Unmarshal(data, &result)\n if err != nil {\n return nil, fmt.Errorf("unmarshal %s: %w", path, err)\n }\n return &result, nil\n}\n\n// Maintenant