مقدمة: ما هو الكود القديم (legacy code) ولماذا يجب إعادة هيكلته
\n\nكل مطور Java يواجه عاجلاً أم آجلاً الكود القديم (legacy code) — وهو برنامج قديم، ضعيف التنظيم، وقليل التوثيق. غالبًا ما يُكتب هذا الكود بدون اختبارات وحدة (unit-tests)، وبانتهاك مبادئ SOLID، وتصبح صيانته كابوسًا. إعادة هيكلة الكود القديم بلغة Java ليست مجرد نزوة، بل ضرورة لتقليل الديون التقنية وتسريع تطوير الميزات الجديدة.
\n\nفي هذه المقالة، سنشرح إعادة هيكلة الكود القديم بلغة Java من الألف إلى الياء: من تحديد الأجزاء الإشكالية إلى تطبيق التغييرات بأمان باستخدام الأدوات الحديثة.
\n\nالمرحلة 1: تحليل وتقييم الكود القديم
\n\nقبل تغيير الكود، يجب فهمه. إليك الخطوات الرئيسية للتحليل:
\n\n1.1. جمع المقاييس والبحث عن "روائح" الكود
\n\nاستخدم أدوات التحليل الثابت:
\n- \n
- SonarQube — يكشف عن التكرار، والطرق المعقدة، وانتهاكات أسلوب الكود \n
- PMD — يجد الأخطاء المحتملة والكود الميت (dead code) \n
- Checkstyle — يتحقق من الامتثال لمعايير التنسيق \n
مثال على "رائحة" نموذجية — طريقة ضخمة:
\n\npublic class OrderProcessor {\n public void process(Order order) {\n // 200 سطر من الكود: التحقق، حساب الخصومات، إرسال البريد الإلكتروني، تسجيل...\n // قسّم هذا إلى طرق صغيرة!\n }\n}\n\n1.2. بناء خريطة التبعيات
\n\nغالبًا ما يحتوي الكود القديم على تبعيات دائرية وفئات God-classes. استخدم أدوات التصور:
\n- \n
- IntelliJ IDEA Dependency Viewer — أداة مدمجة \n
- Structure101 — حل احترافي لتحليل البنية \n
المرحلة 2: إنشاء شبكة حماية من الاختبارات
\n\nبدون اختبارات، إعادة الهيكلة هي لعبة الروليت الروسية. هدفك هو تغطية السيناريوهات الرئيسية بـ اختبارات التوصيف (Characterization Tests) (اختبارات تثبت السلوك الحالي).
\n\n2.1. تقنية "التسجيل الذهبي" (Golden Master)
\n\nللكتل الكبيرة من الكود بدون اختبارات:
\n- \n
- شغّل النظام ببيانات حقيقية \n
- احفظ المخرجات (السجلات، استجابات API) كمرجع \n
- بعد إعادة الهيكلة، قارن النتيجة بالمرجع \n
2.2. مثال اختبار لفئة قديمة
\n\nimport org.junit.jupiter.api.Test;\nimport static org.junit.jupiter.api.Assertions.*;\n\npublic class LegacyCalculatorTest {\n \n @Test\n public void testLegacyCalculation() {\n LegacyCalculator calc = new LegacyCalculator();\n // تثبيت السلوك الحالي\n int result = calc.calculate(10, 5);\n assertEquals(15, result); // إذا كان هناك خطأ، فالاختبار يحتفظ به!\n }\n}\n\nهام: قم أولاً بحفظ (commit) الاختبارات، ثم أعد الهيكلة. اختبار ناجح (أخضر) هو تأمينك.
\n\nالمرحلة 3: إعادة الهيكلة خطوة بخطوة باستخدام الأنماط
\n\nإعادة هيكلة الكود القديم بلغة Java ليست "إعادة كتابة كل شيء"، بل سلسلة من التحولات الصغيرة الآمنة.
\n\n3.1. استخراج الطريقة (Extract Method)
\n\nأكثر إعادة هيكلة أمانًا. تقوم IDE بذلك تلقائيًا.
\n\nقبل:
\npublic void printInvoice(Invoice invoice) {\n double total = 0;\n for (Item item : invoice.getItems()) {\n total += item.getPrice() * item.getQuantity();\n }\n double discount = total > 100 ? total * 0.1 : 0;\n double finalTotal = total - discount;\n System.out.println("Total: " + finalTotal);\n}\n\nبعد (مع استخراج الطرق):
\npublic void printInvoice(Invoice invoice) {\n double total = calculateTotal(invoice);\n double discount = calculateDiscount(total);\n double finalTotal = total - discount;\n printTotal(finalTotal);\n}\n\nprivate double calculateTot