<?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/de/tags/refactoring/</link><description>Recent content in Refactoring on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>de</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 20:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/de/tags/refactoring/index.xml" rel="self" type="application/rss+xml"/><item><title>Die Kunst des Refactorings: Veralteten C++ Code sicher verbessern</title><link>http://kenji.blog/de/p/refactoring-legacy-cpp-code-safely/</link><pubDate>Sat, 12 Sep 2026 20:00:00 +0900</pubDate><guid>http://kenji.blog/de/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 Die Kunst des Refactorings: Veralteten C++ Code sicher verbessern" />&lt;h1 id="die-kunst-des-refactorings-veralteten-c-code-sicher-verbessern">Die Kunst des Refactorings: Veralteten C++ Code sicher verbessern
&lt;/h1>&lt;p>In der modernen Softwareentwicklung ist der Kampf gegen &amp;ldquo;Legacy-Code&amp;rdquo; (veralteten Code) unvermeidlich. Besonders in der Sprache C++ stellt Legacy-Code eine Bedrohung dar, die mit der in anderen Sprachen unvergleichlich ist. Manuelle Speicherverwaltung (ein Sturm aus rohen Zeigern, &lt;code>new&lt;/code> und &lt;code>delete&lt;/code>), der Missbrauch globaler Variablen, fehlende Ausnahmesicherheit und vor allem die Tatsache, dass es &amp;ldquo;keine Tests&amp;rdquo; gibt. Michael Feathers behauptete in seinem Meisterwerk &amp;ldquo;Working Effectively with Legacy Code&amp;rdquo;: &amp;ldquo;Code ohne Tests ist Legacy-Code.&amp;rdquo;&lt;/p>
&lt;p>Dieser Artikel erläutert umfassend sowohl die Theorie als auch die Praxis, wie man eine über Jahrzehnte angesammelte C++-Legacy-Codebasis sicher und zuverlässig zu Modern C++ (C++11/14/17/20) migriert und refaktoriert. Ausgehend von mathematischen Modellen für technische Schulden, über die sichere Trennung von Abhängigkeiten, bis hin zur Bereinigung des Codes mit modernen Sprachfunktionen, decken wir praktische Ansätze ab.&lt;/p>
&lt;hr>
&lt;h2 id="1-mathematisches-modell-von-komplexität-und-technischen-schulden">1. Mathematisches Modell von Komplexität und technischen Schulden
&lt;/h2>&lt;p>Um Refactoring zu rechtfertigen, ist es notwendig, die Probleme der aktuellen Codebasis zu quantifizieren. Die gängigste Metrik zur Messung der strukturellen Komplexität von Code ist die &amp;ldquo;Zyklomatische Komplexität&amp;rdquo; (Cyclomatic Complexity). Diese Komplexität ist basierend auf der Graphentheorie von Kontrollflussgraphen durch die folgende Formel definiert:&lt;/p>
$$ M = E - N + 2P $$&lt;p>Hierbei ist:&lt;/p>
&lt;ul>
&lt;li>$M$ die zyklomatische Komplexität&lt;/li>
&lt;li>$E$ die Anzahl der Kanten (Verarbeitungsfluss, Übergänge) im Graphen&lt;/li>
&lt;li>$N$ die Anzahl der Knoten (grundlegende Verarbeitungsblöcke) im Graphen&lt;/li>
&lt;li>$P$ die Anzahl der zusammenhängenden Komponenten (normalerweise $P=1$ für eine einzelne Funktion oder Methode)&lt;/li>
&lt;/ul>
&lt;p>Je größer die Komplexität $M$ wird, desto linearer oder – abhängig von den Verzweigungskombinationen – exponentieller steigt die Anzahl der Testfälle, die für einen umfassenden Test der Funktion erforderlich sind. Darüber hinaus gibt es eine Faustregel, dass die Wahrscheinlichkeit des Auftretens eines Bugs $P(bug)$ exponentiell zur Komplexität $M$ steigt. Wenn wir dies ähnlich einer Poisson-Verteilung modellieren, erhalten wir Folgendes:&lt;/p>
$$ P(bug) = 1 - e^{-\lambda \cdot M} $$&lt;p>(Hierbei ist $\lambda$ eine Konstante, die von den Fähigkeiten des Entwicklungsteams und der Schwierigkeit der Domäne abhängt.)&lt;/p>
&lt;p>Außerdem steigen die Kosten für technische Schulden mit Zinseszins. Wenn die anfänglichen technischen Schulden $C_0$ sind und der Zinssatz pro Iteration (Prozentsatz des Produktivitätsverlusts aufgrund von Schwierigkeiten bei Codeänderungen) $r$ ist, können die Überarbeitungskosten $Cost(t)$ nach $t$ Perioden wie folgt ausgedrückt werden:&lt;/p>
$$ Cost(t) = C_0 \times (1 + r)^t $$&lt;p>Diese Formel zeigt deutlich die grausame Tatsache: &amp;ldquo;Das Belassen von Legacy-Code führt im Laufe der Zeit zu einem exponentiellen Kostenanstieg.&amp;rdquo; Daher müssen Schulden frühzeitig zurückgezahlt (refaktoriert) werden.&lt;/p>
&lt;hr>
&lt;h2 id="2-das-absolute-prinzip-des-refactorings-test-first">2. Das absolute Prinzip des Refactorings: &amp;ldquo;Test First&amp;rdquo;
&lt;/h2>&lt;p>Die größte Angst bei der Änderung von Legacy-Code ist, dass man &amp;ldquo;das bestehende, normale Verhalten zerstören könnte (eine Regression verursachen)&amp;rdquo;. Der einzige Weg, diese Angst zu beseitigen, sind &amp;ldquo;automatisierte Tests&amp;rdquo;.&lt;/p>
&lt;p>Legacy-Code hat jedoch von vornherein keine Tests. Hier wird die Einführung von &amp;ldquo;Charakterisierungstests&amp;rdquo; (Characterization Tests) wichtig. Ein Charakterisierungstest ist ein Test, der aufzeichnet, &amp;ldquo;wie sich das System derzeit verhält&amp;rdquo;, und nicht, &amp;ldquo;wie es sich eigentlich verhalten sollte&amp;rdquo;.&lt;/p>
&lt;p>Das folgende Flussdiagramm zeigt den Lebenszyklus eines sicheren Refactorings.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;Den Ziel-Legacy-Code identifizieren&amp;#34;] --&amp;gt; B[&amp;#34;Charakterisierungstests schreiben&amp;#34;]
B --&amp;gt; C[&amp;#34;Sicherstellen, dass alle Tests bestehen&amp;#34;]
C --&amp;gt; D[&amp;#34;Kleine Refactorings durchführen&amp;#34;]
D --&amp;gt; E[&amp;#34;Tests erneut ausführen&amp;#34;]
E -- &amp;#34;Fehlgeschlagen (Red)&amp;#34; --&amp;gt; F[&amp;#34;Änderungen rückgängig machen (Revert)&amp;#34;]
F --&amp;gt; D
E -- &amp;#34;Erfolgreich (Green)&amp;#34; --&amp;gt; G[&amp;#34;Code committen&amp;#34;]
G --&amp;gt; H{&amp;#34;Gibt es nächste Verbesserungsbereiche?&amp;#34;}
H -- &amp;#34;Yes&amp;#34; --&amp;gt; D
H -- &amp;#34;No&amp;#34; --&amp;gt; I[&amp;#34;Refactoring abgeschlossen&amp;#34;]
&lt;/pre>
&lt;p>Durch das Durchlaufen dieses Zyklus können Entwickler den Code immer in einem Sicherheitsnetz ändern. Wenn ein Test fehlschlägt, ist es wichtig, ihn sofort rückgängig zu machen (&lt;code>Revert&lt;/code>), ohne die Ursache zu tief zu untersuchen.&lt;/p>
&lt;hr>
&lt;h2 id="3-das-konzept-der-säume-seams-zur-schaffung-von-testbarkeit">3. Das Konzept der &amp;ldquo;Säume&amp;rdquo; (Seams) zur Schaffung von Testbarkeit
&lt;/h2>&lt;p>Wenn Sie versuchen, Tests zu Legacy-Code hinzuzufügen, ist die erste Hürde, auf die Sie stoßen, &amp;ldquo;Abhängigkeiten&amp;rdquo;. Wenn direkte Datenbankverbindungen, Netzwerkkommunikation und fest codierte Dateisystemzugriffe eng gekoppelt sind, ist es unmöglich, Unit-Tests zu schreiben.&lt;/p>
&lt;p>Hier kommt das Konzept einer &amp;ldquo;Naht&amp;rdquo; oder eines &amp;ldquo;Saums&amp;rdquo; (Seam) ins Spiel. Ein Saum ist &amp;ldquo;ein Ort, an dem Sie das Verhalten des Systems ändern können, ohne den Code selbst zu bearbeiten&amp;rdquo;. In C++ verwenden wir hauptsächlich die folgenden drei Arten von Säumen:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Objektsäume (Object Seams)&lt;/strong>: Polymorphismus unter Verwendung von virtuellen Funktionen (Virtual Functions).&lt;/li>
&lt;li>&lt;strong>Kompilierzeitsäume (Compile-time Seams)&lt;/strong>: Vorlagen (Templates) oder das Umschalten von &lt;code>#include&lt;/code>.&lt;/li>
&lt;li>&lt;strong>Linkzeitsäume (Link-time Seams)&lt;/strong>: Umschalten der zu linkenden Bibliotheken oder Objektdateien während des Builds.&lt;/li>
&lt;/ol>
&lt;p>Indem Sie diese voll ausschöpfen, können Sie Abhängigkeiten isolieren, indem Sie Produktionsumgebungsmodule durch Mock-Objekte für die Testumgebung ersetzen.&lt;/p>
&lt;hr>
&lt;h2 id="4-das-brechen-enger-kopplungen-abhängigkeitsinjektion-dependency-injection">4. Das Brechen enger Kopplungen: Abhängigkeitsinjektion (Dependency Injection)
&lt;/h2>&lt;p>Die Abhängigkeitsinjektion (DI: Dependency Injection) ist ein mächtiges Muster, um die Verantwortung für die Objekterstellung vom Inneren einer Klasse nach außen zu verlagern.&lt;/p>
&lt;p>Schauen wir uns zunächst ein veraltetes und eng gekoppeltes Klassendesign in C++ an.&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;Direkte Erstellung (verwendet new)&amp;#34;
LegacyOrderProcessor --&amp;gt; FileLogger : &amp;#34;Direkte Erstellung (verwendet new)&amp;#34;
&lt;/pre>
&lt;p>Dieser &lt;code>LegacyOrderProcessor&lt;/code> verwendet in seinem Konstruktor direkt &lt;code>new&lt;/code> für &lt;code>DatabaseConnection&lt;/code> und &lt;code>FileLogger&lt;/code>, daher gibt es keine Säume, um sie durch Mocks zu ersetzen. Wir werden dies mit Schnittstellen (rein virtuellen Klassen) refaktorieren, um lose gekoppelt zu sein.&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;Implementierung&amp;#34;
ILogger &amp;lt;|.. FileLogger : &amp;#34;Implementierung&amp;#34;
ModernOrderProcessor --&amp;gt; IDatabase : &amp;#34;DI (Konstruktor-Injektion)&amp;#34;
ModernOrderProcessor --&amp;gt; ILogger : &amp;#34;DI (Konstruktor-Injektion)&amp;#34;
&lt;/pre>
&lt;h3 id="beispiel-für-legacy-code-c03">Beispiel für Legacy-Code (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">// Verarbeitung...
&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="nach-dem-refactoring-modern-c">Nach dem 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">// Definition von Schnittstellen (Objektsäume)
&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">// Design zur Injektion von Abhängigkeiten von außen
&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">// Konstruktor-Injektion (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>Durch diese Überarbeitung des Designs können Mock-Objekte von &lt;code>IDatabase&lt;/code> problemlos mit Frameworks wie Google Mock (gmock) erstellt werden, was testgetriebene Entwicklung (TDD) ermöglicht.&lt;/p>
&lt;hr>
&lt;h2 id="5-der-abbau-der-teuflischen-globalen-variablen-und-singletons">5. Der Abbau der teuflischen globalen Variablen und Singletons
&lt;/h2>&lt;p>Was bei Legacy-C++ die meisten Kopfschmerzen bereitet, ist der Missbrauch von globalen Variablen und dem &amp;ldquo;Singleton-Muster&amp;rdquo;. Das Singleton mag auf den ersten Blick wie ein praktisches Entwurfsmuster erscheinen, aber in Wirklichkeit ist es nichts anderes als eine &amp;ldquo;globale Variable im Gewand der Objektorientierung&amp;rdquo;.&lt;/p>
&lt;p>Ein globaler Zustand teilt den Zustand zwischen Testfällen, was die parallele Ausführung von Tests unmöglich macht und unvorhersehbare unzuverlässige Tests (Flaky Tests) verursacht.&lt;/p>
&lt;p>Die Lösung besteht darin, Abhängigkeiten von impliziten globalen Zuständen zu beseitigen und den erforderlichen Zustand explizit als Funktionsargumente zu übergeben (Parametrisierung). Dies wird als &amp;ldquo;Übergabe des Kontexts&amp;rdquo; bezeichnet.&lt;/p>
&lt;hr>
&lt;h2 id="6-modernisierung-der-speicherverwaltung-und-das-wesen-von-raii">6. Modernisierung der Speicherverwaltung und das Wesen von RAII
&lt;/h2>&lt;p>Im Code der C++98/03-Ära waren &lt;code>new&lt;/code> und &lt;code>delete&lt;/code> im gesamten Code verstreut, was ein Nährboden für Speicherlecks (Memory Leaks) und hängende Zeiger (Dangling Pointers) war. In Modern C++ (ab C++11) wird das Konzept der &lt;strong>Eigentümerschaft (Ownership)&lt;/strong> auf Sprachebene unterstützt, und eine sichere Ressourcenverwaltung mithilfe von Smart Pointern ist zum Standard geworden.&lt;/p>
&lt;h3 id="raii-resource-acquisition-is-initialization">RAII (Resource Acquisition Is Initialization)
&lt;/h3>&lt;p>RAII ist das wichtigste Idiom in C++. Indem die Ressourcenzuweisung an die Objektinitialisierung (Konstruktor) und die Ressourcenfreigabe an die Objektzerstörung (Destruktor) gebunden wird, wird garantiert, dass die Ressource beim Verlassen des Gültigkeitsbereichs sicher freigegeben wird.&lt;/p>
&lt;p>Selbst wenn Ausnahmen (Exceptions) auftreten, wird der Destruktor lokaler Variablen während des Stack-Unwinding-Prozesses automatisch aufgerufen, wodurch Ressourcenlecks verhindert werden.&lt;/p>
&lt;p>&lt;strong>Vorher (Gefährlicher Legacy-Code)&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">// Leicht zu vergessen
&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">// Leicht zu vergessen
&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">// Vermeidung von Speicherlecks im Ausnahmefall
&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>Dieser Code erfordert die manuelle Freigabe von Ressourcen bei jeder Verzweigung im Kontrollfluss, was eine extrem fragile Struktur darstellt.&lt;/p>
&lt;p>&lt;strong>Nachher (Nutzung von RAII und Smart Pointern)&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 verwaltet Datei-Handles mit 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 ist ein exklusiver Besitzer, der Heap-Speicher mit RAII verwaltet
&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">// Wird beim Verlassen des Gültigkeitsbereichs automatisch freigegeben
&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">// Selbst wenn eine Ausnahme auftritt, geben die Destruktoren von unique_ptr und 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">// die Ressourcen sicher frei (Garantie für null Speicherlecks)
&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>Durch dieses Refactoring wird die Code-Menge drastisch reduziert, die Absicht wird klar und vor allem wird die Ausnahmesicherheit (Exception Safety) perfekt garantiert.&lt;/p>
&lt;hr>
&lt;h2 id="7-verbesserte-ausdruckskraft-durch-funktionen-von-modern-c">7. Verbesserte Ausdruckskraft durch Funktionen von Modern C++
&lt;/h2>&lt;p>Beim Refactoring von Legacy-Code sollten Sie die Vorteile von Aktualisierungen der Sprachfunktionen voll ausschöpfen.&lt;/p>
&lt;h3 id="71-typableitung-mit-auto">7.1. Typableitung mit &lt;code>auto&lt;/code>
&lt;/h3>&lt;p>Die Lesbarkeit wird verbessert, indem ausführliche Schreibweisen, wie z. B. lange Iterator-Typnamen, durch &lt;code>auto&lt;/code> ersetzt werden. Best Practice ist jedoch, es nicht überall zu verwenden, sondern nur &amp;ldquo;wenn der Typ durch einen Blick auf die rechte Seite offensichtlich ist&amp;rdquo;.&lt;/p>
&lt;h3 id="72-berechnungen-zur-kompilierzeit-mit-constexpr-und-consteval">7.2. Berechnungen zur Kompilierzeit mit &lt;code>constexpr&lt;/code> und &lt;code>consteval&lt;/code>
&lt;/h3>&lt;p>Nutzen Sie &lt;code>constexpr&lt;/code> aktiv, um den Overhead zur Laufzeit zu reduzieren und Fehler zur Kompilierzeit zu erkennen.&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">// Legacy-Code (Makros und Laufzeitberechnungen)
&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">// Modern C++ (ab C++20) Stil
&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 (C++20) garantiert die Auswertbarkeit zur Kompilierzeit
&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">// Null Laufzeitkosten. Die resultierende Konstante wird zur Kompilierzeit direkt in das Binary eingebettet.
&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>Um Fehler zu vermeiden, bei denen der Rückgabewert einer Funktion (insbesondere Fehlercodes und wichtige Zustände) ignoriert wird, fügen Sie das Attribut &lt;code>[[nodiscard]]&lt;/code> hinzu. Dadurch gibt der Compiler eine Warnung für Aufrufe aus, die den Rückgabewert nicht akzeptieren.&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">// Verbietet das Ignorieren des Rückgabewerts
&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-nutzung-automatisierter-tools-und-kontinuierliche-verbesserung">8. Nutzung automatisierter Tools und kontinuierliche Verbesserung
&lt;/h2>&lt;p>Die manuelle Korrektur einer großen Legacy-Codebasis ist unrealistisch. Die Nutzung der Leistungsfähigkeit einer Toolchain ist der schnellste Weg zum Erfolg.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Clang-Tidy&lt;/strong>: Ein leistungsstarker Linter und statisches Analysetool für C++. Durch Aktivieren der &lt;code>modernize-*&lt;/code>-Prüfungen können Sie automatisch (Fix-it) &lt;code>auto&lt;/code> anwenden, durch &lt;code>nullptr&lt;/code> ersetzen, &lt;code>override&lt;/code> hinzufügen und vieles mehr.&lt;/li>
&lt;li>&lt;strong>AddressSanitizer (ASan)&lt;/strong>: Die Einbindung als Kompilierungsoption (&lt;code>-fsanitize=address&lt;/code>) lokalisiert Speicherlecks und Pufferüberläufe zur Laufzeit genau. Es sollte während der Testausführung immer aktiviert sein.&lt;/li>
&lt;li>&lt;strong>Aufbau einer CI/CD-Pipeline&lt;/strong>: Verwenden Sie GitHub Actions oder GitLab CI, um Builds, automatisierte Tests und statische Analysen für alle Pull Requests auszuführen und so das Einschleichen neuer technischer Schulden zu verhindern.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="9-fazit">9. Fazit
&lt;/h2>&lt;p>Das Refactoring von Legacy-C++-Code ist keine Aufgabe, die über Nacht erledigt werden kann. Es ist eine heikle, aber kühne Aufgabe, vergleichbar mit einer Operation am System.&lt;/p>
&lt;p>Bitte behalten Sie die in diesem Artikel erläuterten folgenden Schritte im Hinterkopf.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>Messen Sie die Komplexität und entwickeln Sie eine Strategie auf der Grundlage von Fakten&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Finden Sie Säume und schützen Sie das System mit Charakterisierungstests&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Brechen Sie enge Kopplungen durch DI auf und beseitigen Sie globale Zustände&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Beseitigen Sie Bedenken hinsichtlich der Speicherverwaltung durch RAII und Smart Pointer&lt;/strong>&lt;/li>
&lt;li>&lt;strong>Nutzen Sie die Funktionen von Modern C++ und lassen Sie den Compiler die Arbeit erledigen&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>Die wahre Kunst des Refactorings besteht darin, den Geist der &amp;ldquo;Pfadfinderregel&amp;rdquo; (Hinterlasse den Campingplatz sauberer, als du ihn vorgefunden hast) beizubehalten und den Code durch tägliche Entwicklungsaufgaben allmählich, aber stetig weiter zu verbessern.&lt;/p></description></item></channel></rss>