مبادئ SOLID في PHP: تطبيق متقدم وأمثلة عملية

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

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

ابدأ الدورة

مقدمة: لماذا SOLID ليس مجرد عقيدة، بل أداة

\n

معظم المطورين يعرفون أن SOLID هي خمسة مبادئ للبرمجة كائنية التوجه: Single Responsibility، Open-Closed، Liskov Substitution، Interface Segregation و Dependency Inversion. لكن عمليًا، غالبًا ما يقتصر الفهم على اتباع القواعد بشكل آلي. في هذه المقالة سنذهب أبعد من ذلك: سنستعرض سيناريوهات متقدمة لتطبيق SOLID في PHP، ونناقش الأنماط المضادة التي تخالف المبادئ، ونوضح كيف أن إعادة الهيكلة وفقًا لـ SOLID تجعل الكود مرنًا وقابلًا للاختبار.

\n

المادة موجهة للمطورين من مستوى Middle+ و Senior الذين يكتبون بالفعل بلغة PHP ويرغبون في تحسين بنية مشاريعهم.

\n\n

1. مبدأ المسؤولية الواحدة (SRP): عندما "يعرف الفصل أكثر من اللازم"

\n

الصيغة الكلاسيكية: "يجب أن يكون للفصل سبب واحد فقط للتغيير". على المستوى المتقدم، من المهم فهم أن "سبب التغيير" هو متطلب عمل. إذا تغير فصلك بسبب تغيير قواعد التحقق، أو تنسيق الإخراج، أو منطق الحفظ - فهذا انتهاك لـ SRP.

\n\n

مثال على الانتهاك (God Object)

\n
class OrderProcessor {\n    public function process(array $data): void {\n        // 1. التحقق من البيانات\n        if (empty($data['user_id']) || empty($data['items'])) {\n            throw new InvalidArgumentException('Invalid order data');\n        }\n        \n        // 2. حساب التكلفة\n        $total = 0;\n        foreach ($data['items'] as $item) {\n            $total += $item['price'] * $item['quantity'];\n        }\n        \n        // 3. الحفظ في قاعدة البيانات\n        $sql = "INSERT INTO orders (user_id, total, status) VALUES (?, ?, 'pending')";\n        // ... تنفيذ الاستعلام\n        \n        // 4. إرسال البريد الإلكتروني\n        mail($data['user_email'], 'Order confirmation', "Total: $total");\n    }\n}
\n\n

إعادة الهيكلة مع SRP

\n

نقسم إلى ثلاثة فصول بمناطق مسؤولية واضحة:

\n
class OrderValidator {\n    public function validate(array $data): void {\n        if (empty($data['user_id']) || empty($data['items'])) {\n            throw new InvalidArgumentException('Invalid order data');\n        }\n    }\n}\n\nclass OrderCalculator {\n    public function calculateTotal(array $items): float {\n        return array_reduce($items, function ($carry, $item) {\n            return $carry + $item['price'] * $item['quantity'];\n        }, 0.0);\n    }\n}\n\nclass OrderRepository {\n    public function save(int $userId, float $total, string $status = 'pending'): int {\n        // منطق الحفظ في قاعدة البيانات\n        return 42; // معرف الطلب\n    }\n}\n\nclass OrderProcessor {\n    public function __construct(\n        private OrderValidator $validator,\n        private OrderCalculator $calculator,\n        private OrderRepository $repository,\n        private Mailer $mailer\n    ) {}\n    \n    public function process(array $data): void {\n        $this->validator->validate($data);\n        $total = $this->calculator->calculateTotal($data['items']);\n        $orderId = $this->repository->save($data['user_id'], $total);\n        $this->mailer->send($data['user_email'], 'Order #' . $orderId);\n    }\n}
\n\n

2. مبدأ الانفتاح/الإغلاق (OCP): التوسع دون تعديل

\n

جوهر OCP: يجب أن تكون الفصول مفتوحة للتوسع، ولكن مغلقة للتعديل. عمليًا، هذا يعني استخدام تعدد الأشكال والتجريدات بدلاً من الهياكل الشرطية.

\n\n

انتهاك OCP: switch-case لكل نوع جديد

\n
class PaymentProcessor {\n    public function pay(string $type, float $amount): void {\n        switch ($type) {\n            case 'credit_card':\n                // معالجة البطاقة\n                break;\n            case 'paypal':\n                // معالجة PayPal\n                break;\n            // عند إضافة نوع جديد - نعدل الفصل!\n        }\n    }\n}                

المدونات

توصيات الكتب