<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Refactoring on kenji.blog</title><link>http://kenji.blog/fr/tags/refactoring/</link><description>Recent content in Refactoring on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>fr</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 20:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/fr/tags/refactoring/index.xml" rel="self" type="application/rss+xml"/><item><title>Le secret du refactoring : améliorer le code C++ legacy en toute sécurité</title><link>http://kenji.blog/fr/p/refactoring-legacy-cpp-code-safely/</link><pubDate>Sat, 12 Sep 2026 20:00:00 +0900</pubDate><guid>http://kenji.blog/fr/p/refactoring-legacy-cpp-code-safely/</guid><description>&lt;img src="http://kenji.blog/p/refactoring-legacy-cpp-code-safely/img/eyecatch.jpg" alt="Featured image of post Le secret du refactoring : améliorer le code C++ legacy en toute sécurité" />&lt;h1 id="le-secret-du-refactoring--améliorer-le-code-c-legacy-en-toute-sécurité">Le secret du refactoring : améliorer le code C++ legacy en toute sécurité
&lt;/h1>&lt;p>Dans le développement logiciel moderne, la bataille contre le &amp;ldquo;code legacy&amp;rdquo; est inévitable. Surtout dans un langage comme le C++, le code legacy présente une menace bien supérieure à celle des autres langages. La gestion manuelle de la mémoire (une tempête de pointeurs bruts, de &lt;code>new&lt;/code> et de &lt;code>delete&lt;/code>), l&amp;rsquo;abus de variables globales, le manque de sécurité des exceptions et, par-dessus tout, le fait qu&amp;rsquo;il n&amp;rsquo;y ait &amp;ldquo;pas de tests&amp;rdquo;. Michael Feathers a déclaré dans son célèbre ouvrage &lt;em>Working Effectively with Legacy Code&lt;/em> que &amp;ldquo;le code sans tests est du code legacy&amp;rdquo;.&lt;/p>
&lt;p>Cet article expliquera de manière exhaustive, d&amp;rsquo;un point de vue à la fois théorique et pratique, les secrets pour migrer et refactoriser de manière sûre et fiable une base de code C++ legacy accumulée sur plusieurs décennies vers du Modern C++ (C++11/14/17/20). Commençant par un modèle mathématique de la dette technique, nous couvrirons des approches pratiques telles que l&amp;rsquo;isolation sûre des dépendances et le nettoyage du code à l&amp;rsquo;aide de fonctionnalités de langage modernes.&lt;/p>
&lt;hr>
&lt;h2 id="1-modèle-mathématique-de-la-complexité-et-de-la-dette-technique">1. Modèle mathématique de la complexité et de la dette technique
&lt;/h2>&lt;p>Pour justifier le refactoring, il est nécessaire de quantifier les problèmes de la base de code actuelle. La &amp;ldquo;complexité cyclomatique&amp;rdquo; (Cyclomatic Complexity) est la métrique la plus courante pour mesurer la complexité structurelle du code. Cette complexité est définie par la formule suivante, basée sur la théorie des graphes du graphe de flux de contrôle.&lt;/p>
$$ M = E - N + 2P $$&lt;p>Ici,&lt;/p>
&lt;ul>
&lt;li>$M$ est la complexité cyclomatique&lt;/li>
&lt;li>$E$ est le nombre d&amp;rsquo;arêtes (flux de traitement, transitions) du graphe&lt;/li>
&lt;li>$N$ est le nombre de nœuds (blocs de base de traitement) du graphe&lt;/li>
&lt;li>$P$ est le nombre de composantes connexes (généralement, pour une seule fonction ou méthode, $P=1$)&lt;/li>
&lt;/ul>
&lt;p>Plus la complexité $M$ est grande, plus le nombre de cas de test requis pour tester cette fonction de manière exhaustive augmente linéairement, ou exponentiellement selon la combinaison des branchements conditionnels. De plus, il existe une règle empirique selon laquelle la probabilité d&amp;rsquo;apparition de bugs $P(bug)$ augmente de façon exponentielle avec la complexité $M$. Si nous modélisons cela sous une forme similaire à la distribution de Poisson, nous obtenons ce qui suit.&lt;/p>
$$ P(bug) = 1 - e^{-\lambda \cdot M} $$&lt;p>(Où $\lambda$ est une constante dépendant des compétences de l&amp;rsquo;équipe de développement et de la difficulté du domaine.)&lt;/p>
&lt;p>De plus, le coût de la dette technique augmente de manière composée. Si la dette technique initiale est $C_0$ et le taux d&amp;rsquo;intérêt par itération (le taux de baisse de productivité due à la difficulté de modifier le code) est $r$, le coût de modification $Cost(t)$ après $t$ périodes peut être exprimé comme suit :&lt;/p>
$$ Cost(t) = C_0 \times (1 + r)^t $$&lt;p>Ce que cette formule montre clairement est la cruelle réalité selon laquelle &amp;ldquo;laisser le code legacy tel quel entraîne une augmentation exponentielle des coûts au fil du temps&amp;rdquo;. Par conséquent, la dette doit être remboursée (refactorisée) rapidement.&lt;/p>
&lt;hr>
&lt;h2 id="2-le-principe-absolu-du-refactoring--test-first">2. Le principe absolu du refactoring : &amp;ldquo;Test First&amp;rdquo;
&lt;/h2>&lt;p>La plus grande peur lors de la modification de code legacy est la question : &amp;ldquo;Ne vais-je pas casser le comportement normal existant (provoquer une régression) ?&amp;rdquo;. La seule façon de dissiper cette peur est d&amp;rsquo;utiliser des &amp;ldquo;tests automatisés&amp;rdquo;.&lt;/p>
&lt;p>Cependant, le code legacy ne possède pas de tests au départ. C&amp;rsquo;est là qu&amp;rsquo;intervient l&amp;rsquo;introduction de &amp;ldquo;tests de caractérisation&amp;rdquo; (Characterization Test). Un test de caractérisation est un test qui n&amp;rsquo;enregistre pas &amp;ldquo;comment le système devrait se comporter&amp;rdquo;, mais plutôt &amp;ldquo;comment il se comporte actuellement&amp;rdquo;.&lt;/p>
&lt;p>L&amp;rsquo;organigramme suivant illustre le cycle de vie d&amp;rsquo;un refactoring sûr.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Identifier le code legacy cible&amp;#34;] --&amp;gt; B[&amp;#34;Écrire des tests de caractérisation&amp;#34;]
B --&amp;gt; C[&amp;#34;Vérifier que tous les tests passent&amp;#34;]
C --&amp;gt; D[&amp;#34;Effectuer un petit refactoring&amp;#34;]
D --&amp;gt; E[&amp;#34;Réexécuter les tests&amp;#34;]
E -- &amp;#34;Échec (Red)&amp;#34; --&amp;gt; F[&amp;#34;Annuler les modifications (Revert)&amp;#34;]
F --&amp;gt; D
E -- &amp;#34;Succès (Green)&amp;#34; --&amp;gt; G[&amp;#34;Commiter le code&amp;#34;]
G --&amp;gt; H{&amp;#34;Y a-t-il une autre partie à améliorer ?&amp;#34;}
H -- &amp;#34;Oui&amp;#34; --&amp;gt; D
H -- &amp;#34;Non&amp;#34; --&amp;gt; I[&amp;#34;Refactoring terminé&amp;#34;]
&lt;/pre>
&lt;p>En répétant ce cycle, les développeurs peuvent toujours modifier le code sur un filet de sécurité. Si un test échoue, il est important d&amp;rsquo;annuler immédiatement les modifications (&lt;code>Revert&lt;/code>) sans chercher la cause en profondeur.&lt;/p>
&lt;hr>
&lt;h2 id="3-le-concept-de-coutures-seams-créant-la-testabilité">3. Le concept de &amp;ldquo;Coutures&amp;rdquo; (Seams) créant la testabilité
&lt;/h2>&lt;p>Lorsque vous essayez d&amp;rsquo;ajouter des tests à du code legacy, le premier mur auquel vous vous heurtez est celui des &amp;ldquo;dépendances&amp;rdquo;. Si les connexions directes à la base de données, la communication réseau ou l&amp;rsquo;accès codé en dur au système de fichiers sont étroitement couplés, il est impossible d&amp;rsquo;écrire des tests unitaires (Unit Test).&lt;/p>
&lt;p>C&amp;rsquo;est là qu&amp;rsquo;intervient le concept de &amp;ldquo;Couture&amp;rdquo; (Seam). Une couture désigne &amp;ldquo;un endroit où vous pouvez modifier le comportement du système sans éditer le code lui-même&amp;rdquo;. En C++, nous utilisons principalement les trois coutures suivantes.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Coutures d&amp;rsquo;objets (Object Seams)&lt;/strong> : Polymorphisme utilisant des fonctions virtuelles (Virtual Functions).&lt;/li>
&lt;li>&lt;strong>Coutures à la compilation (Compile-time Seams)&lt;/strong> : Basculement de templates (Templates) ou de &lt;code>#include&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Coutures à l&amp;rsquo;édition de liens (Link-time Seams)&lt;/strong> : Basculement des bibliothèques ou fichiers objets liés lors du build.&lt;/li>
&lt;/ol>
&lt;p>En utilisant ces éléments, vous pouvez isoler les dépendances en remplaçant les modules de l&amp;rsquo;environnement de production par des objets factices (Mock) pour l&amp;rsquo;environnement de test.&lt;/p>
&lt;hr>
&lt;h2 id="4-briser-le-couplage-fort--linjection-de-dépendances-dependency-injection">4. Briser le couplage fort : l&amp;rsquo;Injection de Dépendances (Dependency Injection)
&lt;/h2>&lt;p>L&amp;rsquo;Injection de Dépendances (DI : Dependency Injection) est un modèle puissant pour retirer la responsabilité de la création d&amp;rsquo;objets de l&amp;rsquo;intérieur d&amp;rsquo;une classe vers l&amp;rsquo;extérieur.&lt;/p>
&lt;p>Tout d&amp;rsquo;abord, examinons la conception d&amp;rsquo;une classe C++ legacy et étroitement couplée.&lt;/p>
&lt;pre class="mermaid">
classDiagram
class LegacyOrderProcessor {
-DatabaseConnection* db
-FileLogger* logger
+LegacyOrderProcessor()
+processOrder(int orderId) void
}
class DatabaseConnection {
+DatabaseConnection()
+save(int orderId) void
}
class FileLogger {
+FileLogger()
+log(string msg) void
}
LegacyOrderProcessor --&amp;gt; DatabaseConnection : &amp;#34;Création directe (utilise new)&amp;#34;
LegacyOrderProcessor --&amp;gt; FileLogger : &amp;#34;Création directe (utilise new)&amp;#34;
&lt;/pre>
&lt;p>Ce &lt;code>LegacyOrderProcessor&lt;/code> instancie directement &lt;code>DatabaseConnection&lt;/code> et &lt;code>FileLogger&lt;/code> avec &lt;code>new&lt;/code> dans le constructeur, il n&amp;rsquo;y a donc pas de couture pour les remplacer par des mocks. Nous allons refactoriser cela en un couplage faible en utilisant des interfaces (classes virtuelles pures).&lt;/p>
&lt;pre class="mermaid">
classDiagram
class IDatabase {
&amp;lt;&amp;lt;interface&amp;gt;&amp;gt;
+save(int orderId) void
}
class ILogger {
&amp;lt;&amp;lt;interface&amp;gt;&amp;gt;
+log(string msg) void
}
class ModernOrderProcessor {
-std::unique_ptr~IDatabase~ db
-std::shared_ptr~ILogger~ logger
+ModernOrderProcessor(std::unique_ptr~IDatabase~ db, std::shared_ptr~ILogger~ logger)
+processOrder(int orderId) void
}
class DatabaseConnection {
+save(int orderId) void
}
class FileLogger {
+log(string msg) void
}
IDatabase &amp;lt;|.. DatabaseConnection : &amp;#34;Implémentation&amp;#34;
ILogger &amp;lt;|.. FileLogger : &amp;#34;Implémentation&amp;#34;
ModernOrderProcessor --&amp;gt; IDatabase : &amp;#34;DI (Injection par constructeur)&amp;#34;
ModernOrderProcessor --&amp;gt; ILogger : &amp;#34;DI (Injection par constructeur)&amp;#34;
&lt;/pre>
&lt;h3 id="exemple-de-code-legacy-c03">Exemple de code legacy (C++03)
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">LegacyOrderProcessor&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">private&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">DatabaseConnection&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">db_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">FileLogger&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">logger_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">LegacyOrderProcessor&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">db_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">DatabaseConnection&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;localhost&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3306&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logger_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">FileLogger&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;/var/log/app.log&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">~&lt;/span>&lt;span class="n">LegacyOrderProcessor&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">delete&lt;/span> &lt;span class="n">db_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">delete&lt;/span> &lt;span class="n">logger_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">processOrder&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">orderId&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Traitement...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">db_&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">save&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">orderId&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logger_&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Order processed&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="après-refactoring-modern-c">Après refactoring (Modern C++)
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Définition de l&amp;#39;interface (Couture d&amp;#39;objet)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">IDatabase&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="o">~&lt;/span>&lt;span class="n">IDatabase&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">save&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">orderId&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">ILogger&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="o">~&lt;/span>&lt;span class="n">ILogger&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">virtual&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">msg&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Conception qui injecte les dépendances de l&amp;#39;extérieur
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">class&lt;/span> &lt;span class="nc">ModernOrderProcessor&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">private&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">IDatabase&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">db_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">shared_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">ILogger&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">logger_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Injection par constructeur (Constructor Injection)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">ModernOrderProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">IDatabase&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">db&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">shared_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">ILogger&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">logger&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">db_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">db&lt;/span>&lt;span class="p">)),&lt;/span> &lt;span class="n">logger_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">logger&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">processOrder&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">orderId&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">db_&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">save&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">orderId&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">logger_&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">log&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Order processed&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>En modifiant la conception de cette manière, vous pouvez facilement créer des objets mock pour &lt;code>IDatabase&lt;/code> à l&amp;rsquo;aide de frameworks comme Google Mock (gmock), permettant ainsi le développement piloté par les tests (TDD).&lt;/p>
&lt;hr>
&lt;h2 id="5-le-démantèlement-des-redoutables-variables-globales-et-des-singletons">5. Le démantèlement des redoutables variables globales et des singletons
&lt;/h2>&lt;p>Ce qui cause le plus de maux de tête dans le C++ legacy est l&amp;rsquo;abus des variables globales et du &amp;ldquo;modèle Singleton&amp;rdquo;. À première vue, un singleton peut sembler être un modèle de conception pratique, mais en réalité, ce n&amp;rsquo;est qu&amp;rsquo;une &amp;ldquo;variable globale déguisée en orientation objet&amp;rdquo;.&lt;/p>
&lt;p>Les états globaux partagent l&amp;rsquo;état entre les cas de test, ce qui rend l&amp;rsquo;exécution parallèle des tests impossible et provoque des tests instables (Flaky Tests) de cause inconnue.&lt;/p>
&lt;p>La solution consiste à éliminer les dépendances implicites à l&amp;rsquo;état global et à transmettre explicitement l&amp;rsquo;état nécessaire en tant qu&amp;rsquo;arguments de fonction (paramétrage). Cela s&amp;rsquo;appelle la &amp;ldquo;transmission de contexte&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="6-modernisation-de-la-gestion-de-la-mémoire-et-lessence-du-raii">6. Modernisation de la gestion de la mémoire et l&amp;rsquo;essence du RAII
&lt;/h2>&lt;p>Le code de l&amp;rsquo;époque du C++98/03 a des &lt;code>new&lt;/code> et &lt;code>delete&lt;/code> éparpillés partout, ce qui en fait un vivier de fuites de mémoire et de pointeurs fantômes. Dans le Modern C++ (C++11 et ultérieur), le concept de &lt;strong>propriété (Ownership)&lt;/strong> est supporté au niveau du langage, et la gestion sûre des ressources à l&amp;rsquo;aide de pointeurs intelligents est devenue la norme.&lt;/p>
&lt;h3 id="raii-resource-acquisition-is-initialization">RAII (Resource Acquisition Is Initialization)
&lt;/h3>&lt;p>Le RAII est l&amp;rsquo;idiome le plus important en C++. En liant l&amp;rsquo;acquisition des ressources à l&amp;rsquo;initialisation de l&amp;rsquo;objet (constructeur) et la libération des ressources à la destruction de l&amp;rsquo;objet (destructeur), il garantit que les ressources sont libérées de manière fiable lors de la sortie de la portée.&lt;/p>
&lt;p>Même si une exception (Exceptions) se produit, le destructeur des variables locales est appelé automatiquement lors du processus de déroulement de la pile (Stack Unwinding), ce qui empêche les fuites de ressources.&lt;/p>
&lt;p>&lt;strong>Avant (Code legacy dangereux)&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">processFile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="kt">char&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">filename&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">FILE&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">file&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">fopen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">filename&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;r&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">return&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Data&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">Data&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">readData&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">delete&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Souvent oublié
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">fclose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// Souvent oublié
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">process&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">(...)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">delete&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Évitement de la fuite de mémoire lors d&amp;#39;une exception
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">fclose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">throw&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">delete&lt;/span> &lt;span class="n">data&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">fclose&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Ce code nécessite la libération manuelle des ressources dans chaque branche du flux de contrôle, ce qui est une structure extrêmement fragile.&lt;/p>
&lt;p>&lt;strong>Après (Utilisation du RAII et des pointeurs intelligents)&lt;/strong>&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">processFile&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">filename&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// std::ifstream gère le descripteur de fichier avec le RAII
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">ifstream&lt;/span> &lt;span class="n">file&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">filename&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">is_open&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="k">return&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// std::unique_ptr est le propriétaire exclusif gérant la mémoire tas avec le RAII
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">auto&lt;/span> &lt;span class="n">data&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">make_unique&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">Data&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">readData&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// Libéré automatiquement lors de la sortie de la portée
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// Même si une exception se produit, les destructeurs de unique_ptr et ifstream
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// libéreront de manière fiable les ressources de manière sûre (garantie de zéro fuite de mémoire)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">process&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>Grâce à ce refactoring, la quantité de code est considérablement réduite, l&amp;rsquo;intention devient claire et, par-dessus tout, la sécurité des exceptions (Exception Safety) est parfaitement garantie.&lt;/p>
&lt;hr>
&lt;h2 id="7-amélioration-de-lexpressivité-grâce-aux-fonctionnalités-du-modern-c">7. Amélioration de l&amp;rsquo;expressivité grâce aux fonctionnalités du Modern C++
&lt;/h2>&lt;p>Lors du refactoring du code legacy, vous devez tirer pleinement parti des avantages apportés par les mises à jour des fonctionnalités du langage.&lt;/p>
&lt;h3 id="71-auto-pour-linférence-de-type">7.1. &lt;code>auto&lt;/code> pour l&amp;rsquo;inférence de type
&lt;/h3>&lt;p>En remplaçant les descriptions verbeuses, telles que les noms de types d&amp;rsquo;itérateurs longs, par &lt;code>auto&lt;/code>, la lisibilité est améliorée. Cependant, la meilleure pratique n&amp;rsquo;est pas de tout changer en &lt;code>auto&lt;/code>, mais de le limiter aux &amp;ldquo;cas où le type est évident en regardant le côté droit&amp;rdquo;.&lt;/p>
&lt;h3 id="72-calcul-à-la-compilation-avec-constexpr-et-consteval">7.2. Calcul à la compilation avec &lt;code>constexpr&lt;/code> et &lt;code>consteval&lt;/code>
&lt;/h3>&lt;p>Afin de réduire la surcharge d&amp;rsquo;exécution et de détecter les erreurs à la compilation, &lt;code>constexpr&lt;/code> est activement utilisé.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Code legacy (macros et calculs à l&amp;#39;exécution)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#define MAX_BUFFER_SIZE 1024
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="kt">double&lt;/span> &lt;span class="n">PI&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">3.1415926535&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">double&lt;/span> &lt;span class="nf">calculateCircleArea&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">double&lt;/span> &lt;span class="n">radius&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">PI&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">radius&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">radius&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Style Modern C++ (C++20 et ultérieur)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">constexpr&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">MaxBufferSize&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1024&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">constexpr&lt;/span> &lt;span class="kt">double&lt;/span> &lt;span class="n">Pi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">3.14159265358979323846&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// consteval garantissant que cela peut être évalué à la compilation (C++20)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">consteval&lt;/span> &lt;span class="kt">double&lt;/span> &lt;span class="nf">calculateCircleArea&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">double&lt;/span> &lt;span class="n">radius&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">Pi&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">radius&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">radius&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Coût d&amp;#39;exécution nul. La constante du résultat est directement intégrée au binaire à la compilation.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">constexpr&lt;/span> &lt;span class="kt">double&lt;/span> &lt;span class="n">area&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">calculateCircleArea&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">10.0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="73-attribut-nodiscard">7.3. Attribut &lt;code>[[nodiscard]]&lt;/code>
&lt;/h3>&lt;p>Pour éviter les bugs où les valeurs de retour des fonctions (en particulier les codes d&amp;rsquo;erreur et les états importants) sont ignorées, l&amp;rsquo;attribut &lt;code>[[nodiscard]]&lt;/code> est ajouté. Ainsi, le compilateur émettra un avertissement pour les appels qui ne reçoivent pas la valeur de retour.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="na">[[nodiscard]]&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="n">initializeSystem&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="c1">// Interdit d&amp;#39;ignorer la valeur de retour
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;hr>
&lt;h2 id="8-utilisation-doutils-dautomatisation-et-amélioration-continue">8. Utilisation d&amp;rsquo;outils d&amp;rsquo;automatisation et amélioration continue
&lt;/h2>&lt;p>Il est irréaliste de corriger manuellement une base de code legacy à grande échelle. L&amp;rsquo;aide d&amp;rsquo;une chaîne d&amp;rsquo;outils est le chemin le plus court vers le succès.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Clang-Tidy&lt;/strong> : Un linter et un outil d&amp;rsquo;analyse statique puissant pour C++. En activant les vérifications de la famille &lt;code>modernize-*&lt;/code>, il appliquera automatiquement (Fix-it) des choses comme l&amp;rsquo;application d&amp;rsquo;&lt;code>auto&lt;/code>, le remplacement par &lt;code>nullptr&lt;/code>, et l&amp;rsquo;ajout d&amp;rsquo;&lt;code>override&lt;/code>.&lt;/li>
&lt;li>&lt;strong>AddressSanitizer (ASan)&lt;/strong> : En l&amp;rsquo;intégrant comme option de compilation (&lt;code>-fsanitize=address&lt;/code>), il identifiera avec précision les fuites de mémoire et les débordements de tampon (buffer overruns) à l&amp;rsquo;exécution. Il doit absolument être activé lors de l&amp;rsquo;exécution des tests.&lt;/li>
&lt;li>&lt;strong>Construction de pipelines CI/CD&lt;/strong> : Utilisez GitHub Actions ou GitLab CI pour exécuter des builds, des tests automatisés et une analyse statique sur toutes les pull requests, empêchant ainsi l&amp;rsquo;introduction d&amp;rsquo;une nouvelle dette technique.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="9-conclusion">9. Conclusion
&lt;/h2>&lt;p>Le refactoring du code C++ legacy n&amp;rsquo;est jamais terminé du jour au lendemain. C&amp;rsquo;est un travail à la fois délicat et audacieux, semblable à la réalisation d&amp;rsquo;une intervention chirurgicale sur un système.&lt;/p>
&lt;p>Veuillez garder à l&amp;rsquo;esprit les étapes suivantes expliquées dans cet article.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Mesurez la complexité et établissez une stratégie basée sur des faits&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Trouvez les coutures et protégez le système avec des tests de caractérisation&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Brisez le couplage fort par la DI et éradiquez l&amp;rsquo;état global&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Dissipez les inquiétudes liées à la gestion de la mémoire grâce au RAII et aux pointeurs intelligents&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Utilisez les fonctionnalités du Modern C++ et laissez le compilateur faire le travail&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>Avoir l&amp;rsquo;esprit de la &amp;ldquo;règle du Boy Scout (quittez le terrain de camping plus propre que vous ne l&amp;rsquo;avez trouvé)&amp;rdquo; et continuer à améliorer le code petit à petit, mais sûrement, au sein de vos tâches de développement quotidiennes est le véritable secret du refactoring.&lt;/p></description></item></channel></rss>