إعادة هيكلة الكود القديم بلغة PHP: تقنيات واستراتيجيات متقدمة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

إعادة هيكلة الكود القديم بلغة PHP: مستوى متقدم



العمل مع الكود القديم (legacy) بلغة PHP هو واقع لا مفر منه للعديد من المطورين. غالبًا ما يمثل هذا الكود تطبيقًا متجانسًا بدون اختبارات، مع تبعيات عامة وخلط بين منطق الأعمال والعرض التقديمي. يمكن أن تؤدي إعادة الهيكلة البسيطة "بشكل حدسي" إلى أخطاء قاتلة. في هذه المقالة، سننظر في تقنيات إعادة الهيكلة المتقدمة التي تسمح بتحديث الأنظمة القديمة بأمان وفعالية.



1. استراتيجية "Seam": إنشاء نقاط الفصل



الخطوة الأولى في إعادة هيكلة الكود القديم هي إنشاء الدرزات (seams). الدرز هو مكان يمكنك فيه تغيير سلوك الكود دون تحريره مباشرة. هذا مهم بشكل خاص عندما لا يكون الكود مغطى بالاختبارات ولا يمكنك تشغيله بشكل منعزل.



لنأخذ مثالًا كلاسيكيًا: العمل المباشر مع قاعدة البيانات داخل دالة.



<?php// كود قديمclass UserReport {    public function getActiveUsers() {        $db = new PDO('mysql:host=localhost;dbname=test', 'root', '');        $stmt = $db->query("SELECT * FROM users WHERE active = 1");        return $stmt->fetchAll();    }}?>


المشكلة: new PDO(...) ينشئ تبعية صلبة. لاختبار هذه الدالة، تحتاج إلى قاعدة بيانات حقيقية.



الحل: حقن التبعية عبر المُنشئ.



<?php// إعادة الهيكلة: إنشاء درز عبر DIclass UserReport {    private PDO $pdo;

public function __construct(PDO $pdo) { $this->pdo = $pdo; }

public function getActiveUsers(): array { $stmt = $this->pdo->query("SELECT * FROM users WHERE active = 1"); return $stmt->fetchAll(); }}

// الاستخدام$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '');$report = new UserReport($pdo);?>


الآن يمكنك استبدال PDO بكائن وهمي (mock) في الاختبارات. هذا درز بسيط ولكنه فعال.



2. نمط "Sprout Method" و"Sprout Class"



عندما لا تستطيع تغيير دالة موجودة (على سبيل المثال، بسبب عدم وجود اختبارات)، استخدم استراتيجية "Sprout" — أنشئ كودًا جديدًا بجانب القديم، مع تحويل الاستدعاءات تدريجيًا.



مثال: لدينا دالة ضخمة تقوم بالتحقق من صحة المستخدم وحفظه.



<?phpclass UserService {    public function saveUser(array $data): bool {        // 100 سطر من التحقق والتسجيل والحفظ        $email = $data['email'] ?? '';        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {            throw new InvalidArgumentException('Invalid email');        }        // ... الكثير من الكود الآخر        $db = new PDO(...);        $stmt = $db->prepare("INSERT INTO users ...");        // ...    }}?>


بدلاً من إعادة هيكلة الدالة بأكملها مرة واحدة، أنشئ فئة جديدة للتحقق من الصحة.



<?phpclass UserValidator {    public function validate(array $data): void {        if (!filter_var($data['email'] ?? '', FILTER_VALIDATE_EMAIL)) {            throw new InvalidArgumentException('Invalid email');        }        // أضف فحوصات أخرى    }}

class UserService { private UserValidator $validator;

public function __construct(UserValidator $validator) { $this->validator = $validator; }

public function saveUser(array $data): bool { $this->validator->validate($data); // باقي الكود يبقى كما هو مؤقتًا }}?>


الآن يمكنك كتابة اختبارات الوحدة لـ UserValidator دون لمس الكود القديم. تدريجيًا، ستقوم بنقل المنطق من saveUser إلى فئات جديدة.



3. التخلص من الحالات العامة والثابتة



غالبًا ما يستخدم الكود القديم متغيرات عامة، ومفردات (singletons)، ودوالًا ثابتة. هذا يجعل الكود غير قابل للاختبار تقريبًا.

المدونات

توصيات الكتب