0Pricing
PHP Academy · درس

مبادئ SOLID في التطبيق

طبّق مبادئ SOLID الخمسة على أصناف PHP واقعية.

مبادئ SOLID في التطبيق درس مجاني في PHP Academy على CoddyKit. هذا هو الدرس 1 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في PHP Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة PHP Academy 4 دروس في المجموع.

لماذا SOLID

SOLID هي خمسة مبادئ تصميم تحافظ على PHP كائنية التوجه مرنة وقابلة للاختبار ومقاومة للتدهور. وليست هذه المبادئ قواعد ينبغي اتباعها بشكل أعمى، بل إرشادات تساعد على تقليل الاقتران وتوضيح المسؤوليات. في هذا الدرس، نطبّق كل مبدأ على أصناف PHP عملية يمكنكم شحنها فعلًا.

  • Sالمسؤولية الواحدة
  • Oالانفتاح/الإغلاق
  • Lاستبدال ليسكوف
  • Iفصل الواجهات
  • Dعكس الاعتماديات

المسؤولية الواحدة

ينبغي أن يكون للصنف سبب واحد للتغيير. فالصنف الذي ينشئ تقريرًا، وينسقه بصيغة HTML، ويرسله بالبريد الإلكتروني لديه ثلاثة أسباب للتغيير. افصل بين التخزين والتنسيق والنقل.

في المثال أدناه، يمثّل Invoice البيانات فقط؛ أما العرض والحفظ فموجودان في موضعين آخرين.

<?php
final class Invoice {
    public function __construct(
        public readonly string $number,
        public readonly int $cents
    ) {}
    public function total(): float { return $this->cents / 100; }
}

final class InvoiceRenderer {
    public function toText(Invoice $i): string {
        return sprintf('Invoice %s: $%.2f', $i->number, $i->total());
    }
}

$i = new Invoice('INV-1', 12500);
echo (new InvoiceRenderer())->toText($i), PHP_EOL;

SRP: اكتشاف الرائحة البرمجية

تتمثل مخالفة SRP التقليدية في صنف يحتوي اسمه على and أو في Manager يتولى كل شيء. انتبه إلى الأساليب التي تتغير لأسباب تجارية غير مترابطة. فإذا كان تغيير قاعدة ضريبية وتغيير تخطيط PDF يؤثران في الصنف نفسه، فهذا يعني أن مسؤولياته كثيرة جدًا.

مبدأ الانفتاح/الإغلاق

ينبغي أن تكون كيانات البرمجيات مفتوحة للتمديد ومغلقة أمام التعديل. يجب ألا تؤدي إضافة نوع خصم جديد إلى إجباركم على تعديل switch ضخم. استخدموا تعدد الأشكال: يكون كل منطق في صنف مستقل يطبّق واجهة مشتركة.

<?php
interface Discount { public function apply(float $total): float; }

final class PercentOff implements Discount {
    public function __construct(private float $pct) {}
    public function apply(float $t): float { return $t * (1 - $this->pct / 100); }
}
final class FlatOff implements Discount {
    public function __construct(private float $amount) {}
    public function apply(float $t): float { return max(0, $t - $this->amount); }
}

function checkout(float $total, Discount ...$discounts): float {
    foreach ($discounts as $d) { $total = $d->apply($total); }
    return $total;
}
echo checkout(100, new PercentOff(10), new FlatOff(5)), PHP_EOL; // 85

استبدال ليسكوف

يجب أن تكون الأنواع الفرعية قابلة للاستخدام في أي موضع يُتوقع فيه النوع الأساسي، من دون مفاجأة المستدعي. المثال الشهير: يخالف Square extends Rectangle مبدأ LSP، لأن ضبط العرض يجب ألا يغير الارتفاع بصمت. يُفضّل تمثيلهما كنوعين منفصلين خلف واجهة Shape مشتركة.

<?php
interface Shape { public function area(): float; }

final class Rectangle implements Shape {
    public function __construct(private float $w, private float $h) {}
    public function area(): float { return $this->w * $this->h; }
}
final class Square implements Shape {
    public function __construct(private float $side) {}
    public function area(): float { return $this->side ** 2; }
}

$shapes = [new Rectangle(2, 3), new Square(4)];
foreach ($shapes as $s) { echo $s->area(), PHP_EOL; }

LSP والعقود

يفرض مبدأ LSP قيودًا على عقود الأساليب أيضًا. يمكن للنوع الفرعي إضعاف الشروط المسبقة وتقوية الشروط اللاحقة، ولكن ليس العكس. إن طرح نوع استثناء جديد لم يعلنه النوع الأساسي، أو إرجاع null في موضع يضمن فيه النوع الأساسي كائنًا، يخالف قابلية الاستبدال. وتفرض أنواع الإرجاع المتغايرة وأنواع المعاملات المتباينة عكسيًا في PHP جزءًا من ذلك على مستوى الأنواع.

فصل الواجهات

ينبغي ألا تعتمد العملاء على أساليب لا يستخدمونها. فواجهة Worker الضخمة التي تحتوي على work() وeat() تجبر RobotWorker على إنشاء تنفيذ شكلي لـ eat(). قسّموا الواجهة إلى واجهات أدوار مركزة، بحيث يلتزم كل منفّذ بما ينفذه فعليًا فقط.

<?php
interface Workable { public function work(): string; }
interface Feedable { public function eat(): string; }

final class Human implements Workable, Feedable {
    public function work(): string { return 'coding'; }
    public function eat(): string { return 'lunch'; }
}
final class Robot implements Workable {
    public function work(): string { return 'welding'; }
}

foreach ([new Human(), new Robot()] as $w) { echo $w->work(), PHP_EOL; }

عكس الاعتماديات

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

<?php
interface Mailer { public function send(string $to, string $body): void; }

final class SmtpMailer implements Mailer {
    public function send(string $to, string $body): void {
        echo "SMTP -> $to: $body" . PHP_EOL;
    }
}

final class SignupService {
    public function __construct(private Mailer $mailer) {}
    public function register(string $email): void {
        $this->mailer->send($email, 'Welcome!');
    }
}

(new SignupService(new SmtpMailer()))->register('a@b.com');

DIP وحاوية الاعتماديات

يُعد عكس الاعتماديات مبدأً، بينما يُعد حقن الاعتماديات إحدى التقنيات لتحقيقه. توصل حاوية DI (PSR-11) الصنف الملموس SmtpMailer بتجريد Mailer عند جذر التركيب. ولا يستدعي المستهلك new SmtpMailer() أبدًا، لذا يتجه اعتماد الشيفرة المصدرية نحو التجريد لا التفصيل.

<?php
// Composition root wiring (pseudo-container)
$bindings = [
    Mailer::class => fn() => new SmtpMailer(),
];
$resolve = fn(string $id) => $bindings[$id]();

$service = new SignupService($resolve(Mailer::class));
$service->register('user@example.com');

مبادئ SOLID مجتمعة

تعزز المبادئ بعضها بعضًا. يحافظ ISP على صغر الواجهات، فتظل عمليات حقن DIP مركزة؛ ويعتمد OCP على تعدد أشكال يحافظ LSP على سلامته؛ ويوفر SRP الأصناف الصغيرة التي تجعل كل ذلك ممكنًا. استهدفوا تماسكًا داخليًا واقترانًا ضعيفًا بين المكونات.

  • لا تفرطوا في تجريد صنف يُستخدم مرة واحدة.
  • قدّموا واجهة عندما يظهر تنفيذ ثانٍ أو بديل اختباري.

البراغماتية

SOLID وسيلة لا غاية. فالواجهة المبكرة ذات التنفيذ الواحد تضيف طبقة من الإحالة من دون فائدة («التعميم التخميني»). طبّقوا المبادئ عندما يطرأ التغيير فعلًا أو يصبح وشيكًا بوضوح. تكون إعادة الهيكلة باتجاه SOLID رخيصة عند توفر الاختبارات؛ أما إعادة الهيكلة العمياء باتجاهها منذ اليوم الأول فهي هدر.

تحقق سريع

أي مبدأ تنتهكه مشكلة التوريث بين Square وRectangle؟

مراجعة

طبّقتم مبادئ SOLID الخمسة كلها على PHP حقيقية:

  • SRP: سبب واحد للتغيير لكل صنف.
  • OCP: التمديد عبر أصناف جديدة متعددة الأشكال، لا عبر تعديل switch.
  • LSP: تلتزم الأنواع الفرعية بعقد النوع الأساسي.
  • ISP: واجهات أدوار صغيرة بدلًا من الواجهات الضخمة.
  • DIP: الاعتماد على التجريدات وحقن التفاصيل عند جذر التركيب.

استخدموها لتوجيه إعادة الهيكلة، لا كإجراء شكلي.

الأسئلة الشائعة

هل درس «مبادئ SOLID في التطبيق» مجاني؟

نعم — نص درس «مبادئ SOLID في التطبيق» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة PHP Academy، انتقل إلى CoddyKit PRO. تتضمن دورة PHP Academy 4 دروس في المجموع.

ماذا ستتعلم في «مبادئ SOLID في التطبيق»؟

طبّق مبادئ SOLID الخمسة على أصناف PHP واقعية. تتمرن على PHP Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.

هل أحتاج إلى خبرة سابقة لأبدأ PHP Academy؟

لا تُشترط خبرة سابقة. PHP Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 1 من أصل 4.

كم من الوقت يستغرق درس «مبادئ SOLID في التطبيق»؟

معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.

هل يمكنني كتابة وتشغيل أكواد في درس PHP Academy هذا؟

نعم. كل درس في PHP Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.

جميع الدروس في هذه الدورة

  1. مبادئ SOLID في التطبيق
  2. الأنماط الإنشائية: Factory وBuilder وSingleton
  3. الأنماط الهيكلية: Adapter وDecorator وFacade
  4. الأنماط السلوكية: Strategy وObserver وCommand
← العودة إلى PHP Academy