اتخطّى للمحتوى

المرحلة 00 · الأساس — قبل ما تبدأدرس 1 من 2111 دقيقة قراءةآخر تحديث:

Lesson 01 / 21

OOP & SOLIDشرح عام.

الأساس النظري اللي كل الـ frameworks الحديثة (ومنها Magento) مبنية عليه. هنفهم مبادئ الـ OOP الأربعة، وبعدين مبادئ SOLID الخمسة — بأمثلة كود بسيطة وتشبيهات، مع ربط كل مبدأ بـ Magento.

● Concepts 4 OOP pillars 5 SOLID principles + Magento links

الـ OOP طريقة لتنظيم الكود حوالين objects بتجمع البيانات والسلوك، وبتقوم على أربع أعمدة: Encapsulation و Inheritance و Polymorphism و Abstraction. ومبادئ SOLID الخمسة بتوجّهك تكتب classes سهلة التعديل والاختبار. Magento 2 مبني على الأفكار دي، زي الـ Dependency Injection اللي بتطبّق مبدأ Dependency Inversion، والـ interfaces اللي بتفصل الطبقات عن بعض.

// ليه ده مهم الأسئلة دي بتيجي في بداية أي إنترفيو backend تقريبًا. وكمان لو فهمت المبادئ دي، هتفهم ليه Magento متصمّم بالشكل ده — مش هتحفظ، هتستوعب. الأمثلة عامة (مش خاصة بـ Magento) عشان المبدأ يترسّخ الأول.
◆ Part 1 — Object Oriented Programming
A

يعني إيه OOP؟

الفكرة الأساسية قبل المبادئ الأربعة.

التعريف

الـ OOP (البرمجة الكائنية) هي أسلوب بننظّم بيه الكود حوالين "objects" — كل object بيجمع البيانات (properties) والسلوك (methods) اللي بيشتغل عليها في مكان واحد.

ليه؟

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

a simple classphp
class Car
{
    // properties (data)
    public string $color;
    public int $speed = 0;

    // method (behavior)
    public function accelerate(int $amount): void
    {
        $this->speed += $amount;
    }
}

// an object = an instance of the class
$myCar = new Car();
$myCar->color = 'red';
$myCar->accelerate(50);
تشبيه الـ class زي "الاستمارة/المخطط" لبناء عربية. الـ object زي عربية حقيقية اتصنعت من المخطط ده. تقدر تعمل عربيات كتير (objects) من نفس المخطط (class).
i
الـ OOP بتقوم على 4 أعمدة (pillars): Encapsulation، Inheritance، Polymorphism، Abstraction. هنشرحهم واحد واحد.
• • •
01

Encapsulation — التغليف

إخفاء التفاصيل الداخلية، وكشف اللي محتاج يتكشف بس.

التعريف

الـ Encapsulation معناها إنك تخفي البيانات الداخلية للـ object، وتخلي التعامل معاها يتم بس عن طريق methods محددة. بتستخدم private وprotected عشان تمنع الوصول المباشر.

ليه؟

عشان تحمي البيانات من التعديل الغلط. لو خليت أي حد يعدّل الـ property مباشرة، ممكن يحط قيمة غلط. لكن لو خليته يعدّلها عن طريق method، تقدر تتحقق من القيمة الأول.

encapsulation ✓php
class BankAccount
{
    // hidden — can't touch directly
    private float $balance = 0;

    public function deposit(float $amount): void
    {
        // validation protects the data
        if ($amount <= 0) {
            throw new \InvalidArgumentException();
        }
        $this->balance += $amount;
    }

    public function getBalance(): float
    {
        return $this->balance;
    }
}

// $account->balance = -999;  ❌ not allowed
$account->deposit(100); // ✓ only safe way
تشبيه زي ماكينة الـ ATM. مبتوصلش للفلوس في الخزنة مباشرة — بتتعامل عن طريق أزرار (methods) بتتحقق من كل عملية. الخزنة (البيانات) محمية جوّه.
في Magento عشان كده الـ Model بيستخدم getData() / setData() والـ properties بتكون protected. مبتعدّلش البيانات مباشرة — بتمر عن طريق methods.
• • •
02

Inheritance — الوراثة

class بياخد خصائص وسلوك class تاني ويبني عليه.

التعريف

الـ Inheritance بتخلّي class (الابن/child) يورّث الـ properties والـ methods من class تاني (الأب/parent)، ويقدر يضيف عليها أو يعدّلها. بتستخدم كلمة extends.

ليه؟

عشان متكررش الكود (DRY - Don't Repeat Yourself). لو عندك خصائص مشتركة بين كذا class، بتحطها في parent واحد والكل بيورّثها.

inheritancephp
class Animal
{
    public function breathe(): string
    {
        return 'breathing...';
    }
}

// Dog inherits everything from Animal
class Dog extends Animal
{
    // adds its own behavior
    public function bark(): string
    {
        return 'Woof!';
    }
}

$dog = new Dog();
$dog->breathe(); // inherited
$dog->bark();    // its own
تشبيه زي وراثة الصفات في العيلة. الابن بيورّث صفات من الأب (لون العين مثلًا)، بس ليه كمان صفاته الخاصة.
في Magento الـ Model بيورّث من AbstractModel، والـ ResourceModel من AbstractDb. عشان كده ملفاتك بسيطة — الشغل الأساسي موروث من الـ parent.
!
الوراثة قوية بس متسرفش فيها. القاعدة الحديثة: "favor composition over inheritance" — أحيانًا حقن object أحسن من الوراثة منه. الـ plugins في Magento مثال على ده.
• • •
03

Polymorphism — تعدد الأشكال

نفس الـ method بتتصرّف بشكل مختلف حسب الـ object.

التعريف

الـ Polymorphism (تعدد الأشكال) معناها إن objects مختلفة تقدر تستجيب لـ نفس النداء بطرق مختلفة. بتنادي makeSound() على أي حيوان، وكل واحد بيرد بصوته.

ليه؟

عشان تكتب كود يتعامل مع أنواع مختلفة بنفس الطريقة. الكود بتاعك مش محتاج يعرف نوع الـ object بالظبط — بيعرف بس إنه يقدر يعمل makeSound().

polymorphismphp
interface Animal
{
    public function makeSound(): string;
}

class Dog implements Animal {
    public function makeSound(): string { return 'Woof'; }
}
class Cat implements Animal {
    public function makeSound(): string { return 'Meow'; }
}

// same call, different behavior
function printSound(Animal $a) {
    echo $a->makeSound();
}
printSound(new Dog()); // Woof
printSound(new Cat()); // Meow
تشبيه زي زرار "تشغيل" في أجهزة مختلفة. بتضغط "تشغيل" على التلفزيون، الراديو، والغسالة — نفس الزرار، بس كل جهاز بيعمل حاجة مختلفة.
في Magento ده أساس الـ preferences. أي كود بيطلب interface، وأي class بيطبّقه بيشتغل مكانه. الكود مش عارف الـ implementation بالظبط، بس واثق إنها بتحترم الـ interface.
• • •
04

Abstraction — التجريد

تعرض "إيه بيتعمل" وتخفي "إزاي بيتعمل".

التعريف

الـ Abstraction معناها إنك تركّز على "إيه اللي الـ object بيعمله" وتخفي التفاصيل المعقدة لـ "إزاي بيعمله". بتحققه عن طريق interfaces وabstract classes.

ليه؟

عشان تبسّط التعامل مع الكود المعقّد. المستخدم بيشوف واجهة نظيفة بس، والتعقيد مخفي. وكمان بيسمح بتغيير التفاصيل الداخلية بدون ما يتأثر اللي بيستخدمها.

abstraction via interfacephp
// the "what" — a clean contract
interface PaymentInterface
{
    public function pay(float $amount): bool;
}

// the "how" — hidden complexity
class StripePayment implements PaymentInterface
{
    public function pay(float $amount): bool
    {
        // complex Stripe API calls hidden here
        return true;
    }
}

// caller only knows "pay" exists
function checkout(PaymentInterface $p) {
    $p->pay(100);
}
تشبيه زي سواقة العربية. بتعرف تلف العجلة وتدوس البنزين (الواجهة)، من غير ما تعرف إزاي المحرك بيشتغل جوّه (التفاصيل). التعقيد مخفي عنك.
i
الفرق بين Abstraction و Encapsulation: الـ Encapsulation بتخفي البيانات (حماية). الـ Abstraction بتخفي التعقيد/التنفيذ (تبسيط). مترابطين بس مختلفين.
• • •
◆ Part 2 — SOLID Principles
B

يعني إيه SOLID؟

خمس مبادئ لكتابة كود OOP نظيف وقابل للصيانة.

التعريف

SOLID اختصار لخمس مبادئ تصميم في الـ OOP، لما تتبعها بيبقى كودك سهل الفهم، مرن، وقابل للتوسعة من غير ما يتكسر.

  • S — Single Responsibility (مسؤولية واحدة)
  • O — Open/Closed (مفتوح للتوسعة، مقفول للتعديل)
  • L — Liskov Substitution (قابلية الاستبدال)
  • I — Interface Segregation (فصل الـ interfaces)
  • D — Dependency Inversion (عكس الاعتماد)
في Magento Magento كله عبارة عن تطبيق حي لمبادئ SOLID. لما تفهمهم، هتفهم ليه الـ DI والـ plugins والـ repositories موجودين — كلهم حلول لمشاكل بتحلها SOLID.
• • •
S

Single Responsibility

كل class ليه سبب واحد بس للتغيير.

المبدأ

كل class المفروض يعمل حاجة واحدة بس، ويكون ليه سبب واحد للتغيير. لو الـ class بيعمل أكتر من مسؤولية، افصلهم.

violation ❌php
class User
{
    public function save() { /* DB logic */ }
    public function sendEmail() { /* email logic */ }
    public function generateReport() { /* report */ }
    // 3 responsibilities in one class!
}
fixed ✓php
class User { /* just user data */ }
class UserRepository { public function save() {} }
class EmailService { public function send() {} }
class ReportGenerator { public function generate() {} }
في Magento عشان كده الـ Model (بيانات) منفصل عن الـ ResourceModel (DB) عن الـ Block (view). كل واحد مسؤولية واحدة.
• • •
O

Open / Closed

مفتوح للتوسعة، مقفول للتعديل.

المبدأ

الكود المفروض يكون مفتوح للإضافة عليه (extension)، بس مقفول للتعديل فيه. يعني تقدر تضيف سلوك جديد من غير ما تغيّر الكود الموجود.

ليه؟

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

open for extension ✓php
interface Discount {
    public function apply(float $total): float;
}

// add new discounts WITHOUT touching old code
class SummerDiscount implements Discount {
    public function apply(float $total): float {
        return $total * 0.9;
    }
}
class VipDiscount implements Discount {
    public function apply(float $total): float {
        return $total * 0.8;
    }
}
في Magento ده جوهر نظام الـ plugins والـ events. بتوسّع سلوك الـ core من غير ما تلمس ملفاته — عشان كده الـ upgrades بتفضل آمنة.
• • •
L

Liskov Substitution

الـ child لازم يقدر ياخد مكان الـ parent من غير مشاكل.

المبدأ

لو عندك class أب، أي class ابن المفروض يقدر ياخد مكانه من غير ما يكسّر البرنامج. الابن لازم يحترم "العقد" بتاع الأب.

المثال الكلاسيكي

لو عندك class Bird فيه fly()، وعملت Penguin extends Bird — البطريق ميطيرش! فلو كود بيتوقع أي Bird يطير، البطريق هيكسّره. ده كسر للمبدأ.

violation ❌php
class Bird {
    public function fly() { return 'flying'; }
}
class Penguin extends Bird {
    public function fly() {
        throw new \Exception("Can't fly!");
        // breaks code expecting a Bird to fly
    }
}
i
الحل: صمّم الـ hierarchy صح. اعمل FlyingBird وFlightlessBird منفصلين، بدل ما تجبر البطريق يورّث سلوك مش بتاعه.
في Magento عشان كده أي preference لازم يحترم الـ interface اللي بيستبدله بالكامل. لو الكلاس البديل بيكسر سلوك متوقع، هيكسّر كل اللي بيعتمد على الـ interface.
• • •
I

Interface Segregation

interfaces صغيرة مركّزة أحسن من واحد ضخم.

المبدأ

الـ class مالوش يتجبر إنه يطبّق methods هو مش محتاجها. الأحسن interfaces صغيرة ومركّزة بدل interface واحد ضخم فيه كل حاجة.

violation ❌php
interface Worker {
    public function work();
    public function eat();
    public function sleep();
}

// A robot must implement eat() & sleep()?!
class Robot implements Worker {
    public function eat() { /* useless */ }
    public function sleep() { /* useless */ }
}
fixed ✓php
interface Workable { public function work(); }
interface Eatable   { public function eat(); }

// Robot only takes what it needs
class Robot implements Workable {
    public function work() {}
}
في Magento عشان كده الـ interfaces مركّزة زي ProductRepositoryInterface، مش interface عملاق فيه كل العمليات. كل واحد بياخد اللي محتاجه بس.
• • •
D

Dependency Inversion

اعتمد على abstractions مش على تفاصيل. أهم مبدأ في Magento.

المبدأ

الكود المفروض يعتمد على abstractions (interfaces)، مش على تفاصيل (concrete classes). يعني اطلب "interface" مش class معيّن.

ليه؟

عشان تفكّ الارتباط بين الكود. لو اعتمدت على interface، تقدر تغيّر الـ implementation في أي وقت (للتخصيص أو الـ testing) من غير ما تلمس الكود اللي بيستخدمه.

violation ❌php
class OrderService
{
    private $mailer;
    public function __construct() {
        // locked to a specific class
        $this->mailer = new GmailMailer();
    }
}
fixed ✓php
class OrderService
{
    // depends on abstraction — any mailer works
    public function __construct(
        private readonly MailerInterface $mailer
    ) {}
}
تشبيه زي منفذ الكهربا. الأجهزة (الكود) بتعتمد على "شكل المنفذ" (interface)، مش على شركة كهربا معيّنة. تقدر تغيّر مصدر الكهربا من غير ما تغيّر أجهزتك.
في Magento ده السبب المباشر لوجود الـ Dependency Injection والـ di.xml. بتطلب interfaces في الـ constructor، والـ DI بيوصّل الـ implementation. المبدأ ده هو أساس Magento كله.

OOP & SOLID ✓

دلوقتي عندك الأساس النظري كامل: 4 أعمدة OOP و5 مبادئ SOLID، مع ربط كل واحد بـ Magento. المبادئ دي مش خاصة بـ Magento — دي أساس أي كود OOP محترم.

الخلاصة: SOLID بيفسّر ليه Magento متصمّم بالشكل ده. الـ DI جاي من D، الـ plugins من O، فصل الطبقات من S. مش صدفة — تصميم مقصود.

// fundamentals · oop & solid · 4 pillars + 5 principles

خلّصت الدرس؟علّمه عشان تتابع تقدّمك في الكورس.

كاتب الدرس

Abdulrahman Masoud

عندك سؤال على الدرس أو محتاج مساعدة في مشروع Magento؟ كلّمني.

أسئلة شائعة

ما هي أعمدة الـ OOP الأربعة؟

الـ OOP بتقوم على 4 أعمدة: Encapsulation (إخفاء البيانات وحمايتها)، Inheritance (class بيورّث من class تاني بـ extends)، Polymorphism (نفس النداء بيتصرّف مختلف حسب الـ object)، وAbstraction (تعرض "إيه بيتعمل" وتخفي "إزاي"). الأربعة مع بعض بيخلّوا الكود منظّم وقابل لإعادة الاستخدام وأسهل في الصيانة.

ما الفرق بين Abstraction و Encapsulation؟

الـ Encapsulation بتخفي البيانات الداخلية للحماية، بتستخدم private وprotected وتخلّي التعديل يتم عن طريق methods بتتحقق من القيمة. الـ Abstraction بتخفي التعقيد والتنفيذ للتبسيط، وبتتحقق عن طريق interfaces وabstract classes. الاتنين مترابطين بس هدفهم مختلف.

يعني إيه SOLID في البرمجة؟

SOLID اختصار لخمس مبادئ تصميم في الـ OOP: Single Responsibility، وOpen/Closed، وLiskov Substitution، وInterface Segregation، وDependency Inversion. لما تتبعهم بيبقى كودك سهل الفهم، مرن، وتقدر توسّعه من غير ما يتكسر.

إيه مثال على كسر مبدأ Liskov Substitution؟

المثال الكلاسيكي: class Bird فيه fly()، وتعمل Penguin extends Bird وترمي exception جوّه fly()، فأي كود متوقع إن أي Bird بيطير هيتكسر. الحل إنك تصمّم الـ hierarchy صح وتعمل FlyingBird وFlightlessBird منفصلين بدل ما تجبر البطريق يورّث سلوك مش بتاعه.

إزاي أطبّق Dependency Inversion في PHP؟

بدل ما تعمل new GmailMailer() جوّه الكلاس وتتربط بيه، اطلب interface في الـ constructor زي private readonly MailerInterface $mailer. كده تقدر تغيّر الـ implementation في أي وقت للتخصيص أو الـ testing من غير ما تلمس الكود اللي بيستخدمه.

إمتى أستخدم Interface Segregation؟

لما تلاقي interface ضخم بيجبر classes تطبّق methods مش محتاجاها، زي Robot مجبور يطبّق eat() وsleep() من interface اسمه Worker. قسّمه لـ interfaces صغيرة مركّزة زي Workable وEatable، وكل class ياخد اللي محتاجه بس.

إيه علاقة مبادئ SOLID بتصميم Magento 2؟

Magento متصمّم على SOLID بشكل مقصود: الـ Dependency Injection والـ di.xml جايين من Dependency Inversion، والـ plugins والـ events تطبيق لـ Open/Closed، وفصل الـ Model عن الـ ResourceModel عن الـ Block تطبيق لـ Single Responsibility. وأي preference لازم يحترم الـ interface اللي بيستبدله بالكامل عشان Liskov.