<?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/ar/tags/refactoring/</link><description>Recent content in Refactoring on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ar</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 20:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ar/tags/refactoring/index.xml" rel="self" type="application/rss+xml"/><item><title>أسرار إعادة الهيكلة: تحسين شيفرات C++ القديمة بأمان</title><link>http://kenji.blog/ar/p/refactoring-legacy-cpp-code-safely/</link><pubDate>Sat, 12 Sep 2026 20:00:00 +0900</pubDate><guid>http://kenji.blog/ar/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 أسرار إعادة الهيكلة: تحسين شيفرات C++ القديمة بأمان" />&lt;h1 id="أسرار-إعادة-الهيكلة-تحسين-شيفرات-c-القديمة-بأمان">أسرار إعادة الهيكلة: تحسين شيفرات C++ القديمة بأمان
&lt;/h1>&lt;p>في تطوير البرمجيات الحديثة، المعركة ضد &amp;ldquo;الشيفرات القديمة (Legacy Code)&amp;rdquo; هي طريق لا مفر منه. خاصة في لغة C++، تشكل الشيفرات القديمة تهديدًا لا يقارن بتلك الموجودة في اللغات الأخرى. إدارة الذاكرة يدويًا (عاصفة من المؤشرات الخام و &lt;code>new&lt;/code> / &lt;code>delete&lt;/code>)، الإساءة في استخدام المتغيرات العامة، الافتقار إلى أمان الاستثناءات، والأهم من ذلك حقيقة &amp;ldquo;عدم وجود اختبارات&amp;rdquo;. صرح مايكل فيذرز بشكل قاطع في كتابه الشهير &amp;ldquo;العمل بفعالية مع الشيفرات القديمة&amp;rdquo; أن &amp;ldquo;الشيفرات التي لا تحتوي على اختبارات هي شيفرات قديمة&amp;rdquo;.&lt;/p>
&lt;p>في هذا المقال، سنشرح بالتفصيل أسرار إعادة الهيكلة والانتقال الآمن والموثوق لقاعدة شيفرات C++ القديمة المتراكمة على مدى عقود إلى Modern C++ (C++11/14/17/20)، من الناحيتين النظرية والعملية. سنغطي النهج العملي الشامل، بدءًا من النماذج الرياضية للدين التقني، الفصل الآمن للتبعيات، وحتى تنظيف الشيفرة باستخدام ميزات اللغة الحديثة.&lt;/p>
&lt;hr>
&lt;h2 id="1-النماذج-الرياضية-للتعقيد-والدين-التقني">1. النماذج الرياضية للتعقيد والدين التقني
&lt;/h2>&lt;p>لتبرير عملية إعادة الهيكلة، من الضروري تحديد المشكلات التي تواجهها قاعدة الشيفرة الحالية بشكل كمي. المقياس الأكثر شيوعًا لقياس التعقيد الهيكلي للشيفرة هو &amp;ldquo;التعقيد السيكلوماتي (Cyclomatic Complexity)&amp;rdquo;. يُعرّف هذا التعقيد بالمعادلة التالية استنادًا إلى نظرية الرسوم البيانية للرسم البياني لتدفق التحكم:&lt;/p>
$$ M = E - N + 2P $$&lt;p>حيث،&lt;/p>
&lt;ul>
&lt;li>$M$ هو التعقيد السيكلوماتي&lt;/li>
&lt;li>$E$ هو عدد الحواف في الرسم البياني (تدفقات العمليات، الانتقالات)&lt;/li>
&lt;li>$N$ هو عدد العقد في الرسم البياني (الكتل الأساسية للعمليات)&lt;/li>
&lt;li>$P$ هو عدد المكونات المتصلة (عادةً، في دالة أو طريقة واحدة، يكون $P=1$)&lt;/li>
&lt;/ul>
&lt;p>كلما زاد التعقيد $M$، زاد عدد حالات الاختبار اللازمة لاختبار تلك الدالة بشكل شامل، إما بشكل خطي، أو في بعض حالات مجموعات التفريغ الشرطي بشكل أُسي. علاوة على ذلك، هناك قاعدة تجريبية تفيد بأن احتمالية حدوث خطأ $P(bug)$ تزداد أُسيًا مع التعقيد $M$. إذا قمنا بصياغة هذا في شكل يشبه توزيع بواسون، فإنه يصبح كالتالي:&lt;/p>
$$ P(bug) = 1 - e^{-\lambda \cdot M} $$&lt;p>(حيث $\lambda$ هو ثابت يعتمد على مهارات فريق التطوير وصعوبة المجال.)&lt;/p>
&lt;p>كما أن تكلفة الدين التقني تزداد بشكل مركب. إذا اعتبرنا أن الدين التقني الأولي هو $C_0$، ومعدل الفائدة لكل تكرار (نسبة انخفاض الإنتاجية بسبب صعوبة تغيير الشيفرة) هو $r$، فإن تكلفة الإصلاح $Cost(t)$ بعد فترة $t$ يمكن التعبير عنها كما يلي:&lt;/p>
$$ Cost(t) = C_0 \times (1 + r)^t $$&lt;p>ما توضحه هذه المعادلة بوضوح هو الحقيقة القاسية المتمثلة في أن &amp;ldquo;إهمال الشيفرات القديمة يؤدي إلى زيادة التكاليف بشكل أُسي مع مرور الوقت&amp;rdquo;. لذلك، من الضروري سداد الديون (إعادة الهيكلة) في مرحلة مبكرة.&lt;/p>
&lt;hr>
&lt;h2 id="2-المبدأ-المطلق-لإعادة-الهيكلة-الاختبار-أولا">2. المبدأ المطلق لإعادة الهيكلة: &amp;ldquo;الاختبار أولاً&amp;rdquo;
&lt;/h2>&lt;p>الخوف الأكبر عند تغيير الشيفرات القديمة هو &amp;ldquo;ألا يؤدي ذلك إلى كسر السلوكيات الصحيحة الحالية (حدوث تراجع أو انحدار في الأداء)&amp;rdquo;. الطريقة الوحيدة لتبديد هذا الخوف هي &amp;ldquo;الاختبارات الآلية&amp;rdquo;.&lt;/p>
&lt;p>ومع ذلك، فإن الشيفرات القديمة لا تحتوي على اختبارات في المقام الأول. وهنا تبرز أهمية إدخال &amp;ldquo;اختبارات التوصيف (Characterization Test)&amp;rdquo;. اختبار التوصيف هو اختبار لا يسجل &amp;ldquo;كيف يجب أن يتصرف النظام في الأصل&amp;rdquo;، بل يسجل &amp;ldquo;كيف يتصرف حاليًا&amp;rdquo; كما هو.&lt;/p>
&lt;p>المخطط الانسيابي أدناه يوضح دورة الحياة الآمنة لإعادة الهيكلة.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
A[&amp;#34;تحديد الشيفرة القديمة المستهدفة&amp;#34;] --&amp;gt; B[&amp;#34;كتابة اختبارات التوصيف&amp;#34;]
B --&amp;gt; C[&amp;#34;التأكد من اجتياز جميع الاختبارات&amp;#34;]
C --&amp;gt; D[&amp;#34;إجراء إعادة هيكلة صغيرة&amp;#34;]
D --&amp;gt; E[&amp;#34;إعادة تشغيل الاختبارات&amp;#34;]
E -- &amp;#34;فشل (Red)&amp;#34; --&amp;gt; F[&amp;#34;إلغاء التغييرات (Revert)&amp;#34;]
F --&amp;gt; D
E -- &amp;#34;نجاح (Green)&amp;#34; --&amp;gt; G[&amp;#34;إيداع (Commit) الشيفرة&amp;#34;]
G --&amp;gt; H{&amp;#34;هل هناك مناطق أخرى للتحسين؟&amp;#34;}
H -- &amp;#34;نعم&amp;#34; --&amp;gt; D
H -- &amp;#34;لا&amp;#34; --&amp;gt; I[&amp;#34;اكتملت إعادة الهيكلة&amp;#34;]
&lt;/pre>
&lt;p>من خلال تدوير هذه الدورة، يمكن للمطورين دائمًا تعديل الشيفرة على شبكة أمان. إذا فشل الاختبار، فمن المهم للغاية إجراء &lt;code>Revert&lt;/code> (إلغاء التغييرات) فورًا دون التعمق في ملاحقة الأسباب.&lt;/p>
&lt;hr>
&lt;h2 id="3-مفهوم-الدرز-seams-الذي-يخلق-القابلية-للاختبار">3. مفهوم &amp;ldquo;الدرز (Seams)&amp;rdquo; الذي يخلق القابلية للاختبار
&lt;/h2>&lt;p>عند محاولة إضافة اختبارات إلى شيفرات قديمة، فإن العقبة الأولى التي ستواجهها هي &amp;ldquo;التبعيات (Dependencies)&amp;rdquo;. عندما يكون الاتصال المباشر بقاعدة البيانات، والاتصالات الشبكية، والوصول إلى نظام الملفات المبرمج بشكل ثابت مقترنة بشكل وثيق، يصبح من المستحيل كتابة اختبارات الوحدة (Unit Test).&lt;/p>
&lt;p>هنا يظهر مفهوم &amp;ldquo;الدرز (Seam)&amp;rdquo;. الدرز يشير إلى &amp;ldquo;المكان الذي يمكنك فيه تغيير سلوك النظام دون تعديل الشيفرة نفسها&amp;rdquo;. في C++، يتم استخدام الدروز الثلاثة الرئيسية التالية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>دروز الكائنات (Object Seams)&lt;/strong>: تعدد الأشكال (Polymorphism) باستخدام الدوال الافتراضية (Virtual Functions).&lt;/li>
&lt;li>&lt;strong>دروز وقت الترجمة (Compile-time Seams)&lt;/strong>: التبديل عبر القوالب (Templates) أو &lt;code>#include&lt;/code>.&lt;/li>
&lt;li>&lt;strong>دروز وقت الربط (Link-time Seams)&lt;/strong>: التبديل بين المكتبات أو ملفات الكائنات المرتبطة أثناء البناء.&lt;/li>
&lt;/ol>
&lt;p>من خلال استغلال هذه الدروز، يمكنك عزل التبعيات عن طريق استبدال وحدات بيئة الإنتاج بكائنات وهمية (Mock) مخصصة لبيئة الاختبار.&lt;/p>
&lt;hr>
&lt;h2 id="4-كسر-الاقتران-الوثيق-حقن-التبعية-dependency-injection">4. كسر الاقتران الوثيق: حقن التبعية (Dependency Injection)
&lt;/h2>&lt;p>حقن التبعية (DI: Dependency Injection) هو نمط قوي لنزع مسؤولية إنشاء الكائنات من داخل الفئة إلى الخارج.&lt;/p>
&lt;p>أولاً، دعنا نلقي نظرة على تصميم فئة C++ قديم ومقترن بشكل وثيق.&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;إنشاء مباشر (باستخدام new)&amp;#34;
LegacyOrderProcessor --&amp;gt; FileLogger : &amp;#34;إنشاء مباشر (باستخدام new)&amp;#34;
&lt;/pre>
&lt;p>لا يحتوي هذا &lt;code>LegacyOrderProcessor&lt;/code> على درز يمكن استبداله بكائن وهمي نظرًا لأنه يقوم بإنشاء &lt;code>DatabaseConnection&lt;/code> و &lt;code>FileLogger&lt;/code> مباشرة باستخدام &lt;code>new&lt;/code> داخل المنشئ (Constructor). سنقوم بإعادة هيكلته إلى اقتران فضفاض باستخدام الواجهات (الفئات الافتراضية النقية).&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;تنفيذ&amp;#34;
ILogger &amp;lt;|.. FileLogger : &amp;#34;تنفيذ&amp;#34;
ModernOrderProcessor --&amp;gt; IDatabase : &amp;#34;حقن التبعية (حقن المنشئ)&amp;#34;
ModernOrderProcessor --&amp;gt; ILogger : &amp;#34;حقن التبعية (حقن المنشئ)&amp;#34;
&lt;/pre>
&lt;h3 id="مثال-على-الشيفرة-القديمة-c03">مثال على الشيفرة القديمة (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">// معالجة...
&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="بعد-إعادة-الهيكلة-modern-c">بعد إعادة الهيكلة (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">// تعريف الواجهة (درز الكائنات)
&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">// تصميم لحقن التبعيات من الخارج
&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">// حقن المنشئ (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>من خلال تعديل التصميم بهذه الطريقة، يمكنك بسهولة إنشاء كائنات وهمية لـ &lt;code>IDatabase&lt;/code> باستخدام أطر عمل مثل Google Mock (gmock)، مما يتيح التطوير الموجه بالاختبار (TDD).&lt;/p>
&lt;hr>
&lt;h2 id="5-تفكيك-المتغيرات-العامة-الشيطانية-ونمط-المتفرد-singleton">5. تفكيك المتغيرات العامة الشيطانية ونمط المتفرد (Singleton)
&lt;/h2>&lt;p>ما يسبب أكبر قدر من الصداع في C++ القديمة هو المتغيرات العامة والإساءة في استخدام &amp;ldquo;نمط المتفرد (Singleton)&amp;rdquo;. قد يبدو المتفرد للوهلة الأولى كنمط تصميم مفيد، لكنه في الواقع مجرد &amp;ldquo;متغير عام متخفٍ في ثوب موجه للكائنات&amp;rdquo;.&lt;/p>
&lt;p>الوضع العام (Global State) يشارك الحالة بين حالات الاختبار، مما يجعل التنفيذ المتوازي للاختبارات مستحيلاً ويتسبب في اختبارات متقلبة (Flaky Tests) غير معروفة السبب.&lt;/p>
&lt;p>الحل هو القضاء على الاعتماد الضمني على الوضع العام وتمرير الحالات الضرورية بشكل صريح كمعلمات للدوال (البارامترات). وهذا ما يسمى بـ &amp;ldquo;تمرير السياق&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;h2 id="6-تحديث-إدارة-الذاكرة-وجوهر-raii">6. تحديث إدارة الذاكرة وجوهر RAII
&lt;/h2>&lt;p>تنتشر عمليات &lt;code>new&lt;/code> و &lt;code>delete&lt;/code> في كل مكان في شيفرات عصر C++98/03، وهي تشكل بؤرة لتسرب الذاكرة والمؤشرات المتدلية (Dangling Pointers). في Modern C++ (C++11 وما بعده)، يتم دعم مفهوم &lt;strong>الملكية (Ownership)&lt;/strong> على مستوى اللغة، وأصبحت الإدارة الآمنة للموارد باستخدام المؤشرات الذكية هي المعيار.&lt;/p>
&lt;h3 id="raii-تخصيص-الموارد-هو-التهيئة">RAII (تخصيص الموارد هو التهيئة)
&lt;/h3>&lt;p>RAII هو أهم اصطلاح (Idiom) في لغة C++. من خلال ربط تأمين المورد بتهيئة الكائن (المنشئ) وربط تحرير المورد بتدمير الكائن (المهدم)، يضمن تحرير المورد بشكل مؤكد عند الخروج من النطاق.&lt;/p>
&lt;p>حتى في حالة حدوث استثناءات (Exceptions)، يتم استدعاء المهدمات للمتغيرات المحلية تلقائيًا خلال عملية فك المكدس (Stack Unwinding)، مما يمنع تسرب الموارد.&lt;/p>
&lt;p>&lt;strong>قبل (شيفرة قديمة خطيرة)&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">// سهل النسيان
&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">// سهل النسيان
&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">// تجنب تسرب الذاكرة عند حدوث استثناء
&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>هذه الشيفرة تتطلب تحرير الموارد يدويًا في كل تفرع من تدفق التحكم، وهي بنية هشة للغاية.&lt;/p>
&lt;p>&lt;strong>بعد (استخدام RAII والمؤشرات الذكية)&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 تدير مقبض الملف باستخدام 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 هو مالك حصري يدير ذاكرة الكومة (heap) باستخدام 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">// يتم التحرير تلقائيًا عند الخروج من النطاق
&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">// حتى في حالة حدوث استثناء، تضمن مهدمات unique_ptr و 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">// تحرير الموارد بشكل آمن (ضمان عدم وجود تسرب للذاكرة)
&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>بفضل إعادة الهيكلة هذه، انخفض حجم الشيفرة بشكل كبير، وأصبحت النوايا واضحة، والأهم من ذلك، تم ضمان أمان الاستثناءات (Exception Safety) بشكل كامل.&lt;/p>
&lt;hr>
&lt;h2 id="7-تحسين-القوة-التعبيرية-بواسطة-ميزات-modern-c">7. تحسين القوة التعبيرية بواسطة ميزات Modern C++
&lt;/h2>&lt;p>في عملية إعادة هيكلة الشيفرات القديمة، ينبغي الاستفادة القصوى من الفوائد المصاحبة لتحديثات ميزات اللغة.&lt;/p>
&lt;h3 id="71-استنتاج-النوع-بواسطة-auto">7.1. استنتاج النوع بواسطة &lt;code>auto&lt;/code>
&lt;/h3>&lt;p>استبدال الكتابات المطولة، مثل أسماء أنواع المكررات (iterators) الطويلة، بـ &lt;code>auto&lt;/code> يؤدي إلى تحسين المقروئية. ومع ذلك، فإن أفضل ممارسة ليست تحويل كل شيء إلى &lt;code>auto&lt;/code>، بل قصرها على الحالات التي يكون فيها &amp;ldquo;النوع واضحًا بمجرد النظر إلى الجانب الأيمن&amp;rdquo;.&lt;/p>
&lt;h3 id="72-حسابات-وقت-الترجمة-باستخدام-constexpr-و-consteval">7.2. حسابات وقت الترجمة باستخدام &lt;code>constexpr&lt;/code> و &lt;code>consteval&lt;/code>
&lt;/h3>&lt;p>من أجل تقليل النفقات العامة (overhead) في وقت التشغيل واكتشاف الأخطاء في وقت الترجمة، يتم استخدام &lt;code>constexpr&lt;/code> بشكل نشط.&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">// شيفرة قديمة (وحدات الماكرو وحسابات وقت التشغيل)
&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++ (منذ 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">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)
&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">// تكلفة وقت التشغيل هي صفر. يتم دمج ثابت النتيجة مباشرة في الثنائيات (binary) في وقت الترجمة.
&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-سمة-nodiscard">7.3. سمة &lt;code>[[nodiscard]]&lt;/code>
&lt;/h3>&lt;p>لمنع الأخطاء الناتجة عن تجاهل القيمة المرجعة للدالة (خاصة أكواد الأخطاء أو الحالات المهمة)، يتم إضافة سمة &lt;code>[[nodiscard]]&lt;/code>. هذا يجعل المترجم (compiler) يصدر تحذيرًا بشأن الاستدعاءات التي لا تستقبل القيمة المرجعة.&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">// منع تجاهل القيمة المرجعة
&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-استخدام-أدوات-الأتمتة-والتحسين-المستمر">8. استخدام أدوات الأتمتة والتحسين المستمر
&lt;/h2>&lt;p>إن محاولة تعديل قاعدة شيفرات قديمة واسعة النطاق يدويًا أمر غير واقعي. الاستعانة بسلسلة الأدوات (toolchain) هو أقصر طريق للنجاح.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>Clang-Tidy&lt;/strong>: أداة فحص شيفرة (Linter) وتحليل ثابت قوية لـ C++. من خلال تفعيل فحوصات عائلة &lt;code>modernize-*&lt;/code>، ستقوم الأداة بتطبيق الإصلاحات تلقائيًا (Fix-it) مثل تطبيق &lt;code>auto&lt;/code>، الاستبدال بـ &lt;code>nullptr&lt;/code>، وإضافة &lt;code>override&lt;/code>.&lt;/li>
&lt;li>&lt;strong>AddressSanitizer (ASan)&lt;/strong>: من خلال دمجها كخيار تجميع (&lt;code>-fsanitize=address&lt;/code>)، يمكنها تحديد تسرب الذاكرة وتجاوزات المخزن المؤقت (buffer overruns) بدقة في وقت التشغيل. يجب تفعيلها دائمًا أثناء تنفيذ الاختبارات.&lt;/li>
&lt;li>&lt;strong>بناء مسار CI/CD&lt;/strong>: استخدام GitHub Actions أو GitLab CI لتنفيذ البناء، الاختبارات الآلية، والتحليل الثابت لجميع طلبات السحب (Pull Requests)، مما يمنع دخول أي دين تقني جديد.&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="9-الخاتمة">9. الخاتمة
&lt;/h2>&lt;p>إعادة هيكلة شيفرات C++ القديمة ليست مهمة تكتمل بين عشية وضحاها بأي حال من الأحوال. إنها عملية دقيقة وجريئة تشبه إجراء عملية جراحية للنظام.&lt;/p>
&lt;p>يرجى وضع الخطوات التالية المشروحة في هذا المقال في الاعتبار:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>قياس التعقيد ووضع استراتيجية بناءً على الحقائق&lt;/strong>&lt;/li>
&lt;li>&lt;strong>اكتشاف الدروز وحماية النظام باختبارات التوصيف&lt;/strong>&lt;/li>
&lt;li>&lt;strong>كسر الاقتران الوثيق بواسطة حقن التبعيات (DI) والقضاء على الوضع العام&lt;/strong>&lt;/li>
&lt;li>&lt;strong>تبديد القلق بشأن إدارة الذاكرة بواسطة RAII والمؤشرات الذكية&lt;/strong>&lt;/li>
&lt;li>&lt;strong>الاستفادة من ميزات Modern C++ وترك العمل للمترجم (compiler)&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>إن التحلي بروح &amp;ldquo;قاعدة الكشافة (اترك موقع التخييم أنظف مما وجدته)&amp;rdquo; ومواصلة تحسين الشيفرة شيئًا فشيئًا، ولكن بثبات من خلال مهام التطوير اليومية، هو الجوهر الحقيقي لإعادة الهيكلة.&lt;/p></description></item></channel></rss>