سی ام اس نویسسی ام اس نویسیاد بگیر، سیستم خودتو بنویس
مجلهتماس با ما
سی ام اس نویسسی ام اس نویس

CMS نویس مرجعی برای آموزش برنامه نویسی وب و PHP، توسعه افزونه‌های اختصاصی وردپرس، طراحی ورک‌فلو و اتوماسیون با n8n و توسعه CMS های اختصاصی است. هدف ما ارائه آموزش‌های کاربردی و راهکارهای حرفه‌ای برای توسعه‌دهندگان، کسب‌وکارها و علاقه‌مندان به دنیای برنامه‌نویسی است.

پیوندهای سریع
محصولات فیزیکیمحصولات دیجیتالدوره‌های آموزشی
سی ام اس نویس
مجله سی ام اس نویستماس با ماپنل کاربری
سی ام اس نویس — تمامی حقوق برای سی ام اس نویس محفوظ است. © 1406 تماس با ما09307711941
اصول SOLID در PHP چیست؟ آموزش ۵ اصل SOLID با مثال

اصول SOLID در PHP چیست؟ آموزش ۵ اصل SOLID با مثال

ممدیر کل سیستم ۱۹ شهریور ۱۴۰۵ ۲۱ دقیقه مطالعه ۳ بازدید
اصول SOLID در PHP چیست؟ آموزش ۵ اصل SOLID با مثال

وقتی پروژه‌های PHP کوچک هستند، معمولاً نوشتن چند کلاس و متد ساده مشکل خاصی ایجاد نمی‌کند. اما هرچه پروژه بزرگ‌تر شود، تغییر یک بخش از برنامه ممکن است روی چندین بخش دیگر تأثیر بگذارد.

کلاس‌های بزرگ، وابستگی شدید بین قسمت‌های مختلف برنامه، کدهای تکراری، تست‌پذیری پایین و دشواری اضافه کردن قابلیت‌های جدید، معمولاً نشانه این هستند که معماری پروژه نیاز به بهبود دارد.

اینجاست که SOLID اهمیت پیدا می‌کند.

SOLID مجموعه‌ای از پنج اصل مهم در طراحی برنامه‌های شی‌گرا است که به ما کمک می‌کند کدی:

  • قابل نگهداری‌تر
  • قابل توسعه‌تر
  • تست‌پذیرتر
  • انعطاف‌پذیرتر
  • و کم‌وابسته‌تر

بنویسیم.

در این مقاله از مجموعه آموزش PHP در سی ام اس نویس، هر پنج اصل SOLID را با مثال‌های واقعی PHP بررسی می‌کنیم و در پایان می‌بینیم چطور می‌توان از این اصول در پروژه‌های بزرگ PHP و Laravel استفاده کرد.


# SOLID چیست؟

SOLID مخفف پنج اصل مهم در برنامه‌نویسی شی‌گرا است:


S → Single Responsibility Principle

O → Open/Closed Principle

L → Liskov Substitution Principle

I → Interface Segregation Principle

D → Dependency Inversion Principle

این پنج اصل به ما کمک می‌کنند کلاس‌ها و وابستگی‌های پروژه را بهتر طراحی کنیم.

هدف SOLID این نیست که برای هر پروژه ده‌ها کلاس ایجاد کنیم.

هدف اصلی این است که:

> با افزایش اندازه پروژه، تغییر و توسعه کد تا حد امکان ساده و قابل کنترل باقی بماند.


# چرا SOLID در PHP مهم است؟

فرض کنید یک کلاس بزرگ داریم:


class Order

{

    public function create()

    {

        // create order

    }



    public function calculatePrice()

    {

        // calculate price

    }



    public function sendEmail()

    {

        // send email

    }



    public function sendSms()

    {

        // send SMS

    }



    public function saveToDatabase()

    {

        // save database

    }



    public function generatePdf()

    {

        // generate PDF

    }

}

این کلاس مسئولیت‌های بسیار زیادی دارد.

اگر سیستم ایمیل تغییر کند، باید همین کلاس را تغییر دهیم.

اگر دیتابیس تغییر کند، باز همین کلاس تغییر می‌کند.

اگر سیستم PDF تغییر کند، دوباره همین کلاس تغییر خواهد کرد.

با بزرگ‌تر شدن پروژه، چنین ساختاری به‌سرعت مشکل‌ساز می‌شود.

SOLID کمک می‌کند مسئولیت‌ها و وابستگی‌ها بهتر تفکیک شوند.


# پنج اصل SOLID چیست؟

پنج اصل SOLID عبارت‌اند از:

حرفاصلمفهوم ساده
SSingle Responsibilityهر کلاس یک مسئولیت اصلی داشته باشد
OOpen/Closedبرای توسعه باز و برای تغییر بسته باشد
LLiskov Substitutionفرزند باید قابل جایگزینی با والد باشد
IInterface SegregationInterfaceهای کوچک و تخصصی ایجاد کنیم
DDependency Inversionبه abstraction وابسته باشیم، نه implementation

حالا هر اصل را جداگانه بررسی کنیم.


# اصل اول SOLID: Single Responsibility Principle

SRP چیست؟

اصل اول SOLID یعنی:

Single Responsibility Principle

یا اصل تک‌مسئولیتی.

این اصل می‌گوید:

> یک کلاس باید یک مسئولیت اصلی داشته باشد و تغییرات مرتبط با همان مسئولیت را مدیریت کند.

به زبان ساده، نباید یک کلاس را مسئول همه چیز کنیم.


# مثال اشتباه برای SRP

فرض کنید:


class User

{

    public function create()

    {

        // create user

    }



    public function sendEmail()

    {

        // send email

    }



    public function generateReport()

    {

        // generate report

    }



    public function saveLog()

    {

        // save log

    }

}

این کلاس چند وظیفه دارد:


User

├── مدیریت کاربر

├── ارسال ایمیل

├── تولید گزارش

└── ثبت Log

در نتیجه تغییر در هرکدام از این قسمت‌ها ممکن است باعث تغییر کلاس User شود.


# اصلاح کد با SRP

می‌توانیم مسئولیت‌ها را جدا کنیم:


class UserService

{

    public function create()

    {

        // create user

    }

}

ارسال ایمیل:


class EmailService

{

    public function send()

    {

        // send email

    }

}

گزارش:


class UserReportService

{

    public function generate()

    {

        // generate report

    }

}

Log:


class Logger

{

    public function log()

    {

        // save log

    }

}

حالا هر کلاس یک مسئولیت مشخص‌تر دارد.


# نکته مهم درباره SRP

SRP به این معنی نیست که هر کلاس باید فقط یک متد داشته باشد.

مثلاً این کلاس می‌تواند کاملاً منطقی باشد:


class UserService

{

    public function create()

    {

    }



    public function update()

    {

    }



    public function delete()

    {

    }

}

زیرا تمام متدها حول یک مسئولیت اصلی یعنی مدیریت کاربران هستند.

بنابراین سؤال بهتر این است:

> آیا تغییر در یک حوزه مشخص باعث تغییر این کلاس می‌شود؟

اگر یک کلاس به دلایل کاملاً متفاوت زیادی باید تغییر کند، احتمالاً SRP در آن رعایت نشده است.


# اصل دوم SOLID: Open/Closed Principle

OCP چیست؟

اصل دوم:

Open/Closed Principle

یا اصل باز/بسته است.

مفهوم آن این است:

> موجودیت‌های نرم‌افزاری باید برای توسعه باز و برای تغییر کد موجود تا حد امکان بسته باشند.

یعنی وقتی قابلیت جدید اضافه می‌کنیم، بهتر است به جای دستکاری مداوم کد موجود، implementation جدید اضافه کنیم.


# مثال اشتباه برای OCP

فرض کنید سیستم پرداخت داریم:


class Payment

{

    public function pay(

        string $type,

        float $amount

    ): bool {

        if ($type === 'bank') {

            // bank payment

        }



        if ($type === 'wallet') {

            // wallet payment

        }



        if ($type === 'paypal') {

            // paypal payment

        }



        return true;

    }

}

حالا اگر روش پرداخت جدید اضافه کنیم:


crypto

باید کلاس Payment را تغییر دهیم.

اگر تعداد روش‌های پرداخت زیاد شود، این کلاس بزرگ‌تر و پیچیده‌تر می‌شود.


# اصلاح OCP با Interface

ابتدا Interface:


interface PaymentGateway

{

    public function pay(float $amount): bool;

}

درگاه بانکی:


class BankPayment implements PaymentGateway

{

    public function pay(float $amount): bool

    {

        // bank payment



        return true;

    }

}

کیف پول:


class WalletPayment implements PaymentGateway

{

    public function pay(float $amount): bool

    {

        // wallet payment



        return true;

    }

}

حالا اگر درگاه جدید اضافه کنیم:


class CryptoPayment implements PaymentGateway

{

    public function pay(float $amount): bool

    {

        // crypto payment



        return true;

    }

}

لازم نیست کلاس‌های قبلی را تغییر دهیم.

قابلیت جدید را با یک implementation جدید اضافه کرده‌ایم.


# OCP چه مشکلی را حل می‌کند؟

با OCP، اضافه کردن قابلیت جدید کمتر باعث خراب شدن قابلیت‌های قبلی می‌شود.

ساختار به این شکل است:


PaymentGateway

      ↑

 ┌────┼─────────┐

 │    │         │

Bank Wallet   Crypto

هر implementation قرارداد مشترک را رعایت می‌کند.


# اصل سوم SOLID: Liskov Substitution Principle

LSP چیست؟

اصل سوم:

Liskov Substitution Principle

یا اصل جایگزینی لیسکوف است.

مفهوم ساده آن:

> اگر کلاس B از کلاس A ارث‌بری می‌کند، باید بتوانیم در جاهایی که A انتظار می‌رود از B استفاده کنیم، بدون اینکه رفتار برنامه به شکل غیرمنتظره خراب شود.

به عبارت ساده‌تر:

کلاس فرزند باید واقعاً قابل جایگزینی با کلاس والد باشد.


# یک مثال ساده برای LSP

فرض کنید:


class Bird

{

    public function fly(): void

    {

        echo 'Flying';

    }

}

حالا:


class Sparrow extends Bird

{

}

این منطقی است.

گنجشک می‌تواند پرواز کند.

اما اگر بنویسیم:


class Penguin extends Bird

{

    public function fly(): void

    {

        throw new Exception(

            'Penguins cannot fly'

        );

    }

}

طراحی ما مشکل دارد.

چون Penguin یک Bird است، اما قرارداد رفتاری والد را نقض کرده است.


# مشکل LSP در این مثال چیست؟

کد زیر را تصور کنید:


function makeBirdFly(Bird $bird): void

{

    $bird->fly();

}

اگر بنویسیم:


makeBirdFly(

    new Penguin()

);

برنامه با Exception مواجه می‌شود.

بنابراین Penguin نمی‌تواند به شکل صحیح جایگزین Bird شود.


# اصلاح مثال با طراحی بهتر

می‌توانیم قابلیت پرواز را جدا کنیم:


class Bird

{

}

و:


interface Flyable

{

    public function fly(): void;

}

گنجشک:


class Sparrow extends Bird implements Flyable

{

    public function fly(): void

    {

        echo 'Flying';

    }

}

پنگوئن:


class Penguin extends Bird

{

}

حالا فقط پرنده‌هایی که قابلیت پرواز دارند Flyable را پیاده‌سازی می‌کنند.

این طراحی با اصل LSP سازگارتر است.


# LSP فقط درباره Inheritance نیست

LSP در عمل درباره رفتار قراردادها است.

اگر یک کلاس Interface خاصی را implement کند اما رفتار آن Interface را به شکل غیرمنتظره‌ای بشکند، باز هم می‌توانیم با مشکل LSP مواجه شویم.

مثلاً اگر Interface می‌گوید:


interface PaymentGateway

{

    public function pay(float $amount): bool;

}

ولی یک implementation برای هر مبلغ مثبت Exception غیرمنتظره ایجاد کند، باید بررسی کنیم آیا واقعاً قرارداد مورد انتظار را رعایت کرده است یا خیر.


# اصل چهارم SOLID: Interface Segregation Principle

ISP چیست؟

اصل چهارم:

Interface Segregation Principle

یا اصل تفکیک Interfaceها است.

مفهوم آن:

> کلاس‌ها نباید مجبور باشند Interfaceهایی را implement کنند که به آن‌ها نیازی ندارند.

به زبان ساده:

به جای یک Interface بسیار بزرگ، چند Interface کوچک و تخصصی ایجاد کنیم.


# مثال اشتباه برای ISP

فرض کنید:


interface Worker

{

    public function work();



    public function eat();



    public function sleep();

}

حالا:


class Human implements Worker

{

    public function work()

    {

    }



    public function eat()

    {

    }



    public function sleep()

    {

    }

}

مشکلی وجود ندارد.

اما اگر:


class Robot implements Worker

{

    public function work()

    {

    }



    public function eat()

    {

        throw new Exception(

            'Robot cannot eat'

        );

    }



    public function sleep()

    {

        throw new Exception(

            'Robot does not sleep'

        );

    }

}

طراحی Interface مناسب نیست.

Robot مجبور شده متدهایی را پیاده‌سازی کند که به آن‌ها نیازی ندارد.


# اصلاح ISP

Interface را تقسیم می‌کنیم:


interface Workable

{

    public function work();

}

و:


interface Eatable

{

    public function eat();

}

و:


interface Sleepable

{

    public function sleep();

}

حالا Human:


class Human implements

    Workable,

    Eatable,

    Sleepable

{

    public function work()

    {

    }



    public function eat()

    {

    }



    public function sleep()

    {

    }

}

Robot:


class Robot implements Workable

{

    public function work()

    {

    }

}

اکنون Robot فقط قابلیت مورد نیاز خودش را پیاده‌سازی می‌کند.


# مزیت ISP

Interfaceهای کوچک‌تر باعث می‌شوند:

  • وابستگی کمتر شود.
  • کلاس‌ها ساده‌تر شوند.
  • تغییرات محدودتر شوند.
  • تست‌نویسی ساده‌تر شود.
  • implementationها انعطاف بیشتری داشته باشند.

# اصل پنجم SOLID: Dependency Inversion Principle

DIP چیست؟

اصل پنجم:

Dependency Inversion Principle

یا اصل وارونگی وابستگی است.

مفهوم آن به صورت ساده:

> ماژول‌های سطح بالا نباید به جزئیات سطح پایین وابسته باشند؛ هر دو باید به abstraction وابسته باشند.

همچنین abstraction نباید به جزئیات وابسته باشد؛ جزئیات باید به abstraction وابسته باشند.

این اصل ارتباط بسیار نزدیکی با Dependency Injection دارد.


# مثال اشتباه برای DIP

فرض کنید:


class OrderService

{

    public function checkout(): bool

    {

        $payment = new BankPayment();



        return $payment->pay(500000);

    }

}

اینجا OrderService مستقیماً به BankPayment وابسته است.


OrderService

      ↓

BankPayment

اگر درگاه پرداخت تغییر کند، باید OrderService را تغییر دهیم.


# اصلاح DIP با Interface

ابتدا:


interface PaymentGateway

{

    public function pay(float $amount): bool;

}

سپس:


class BankPayment implements PaymentGateway

{

    public function pay(float $amount): bool

    {

        return true;

    }

}

و OrderService:


class OrderService

{

    public function __construct(

        private PaymentGateway $payment

    ) {

    }



    public function checkout(): bool

    {

        return $this->payment->pay(500000);

    }

}

حالا:


        PaymentGateway

          ↑       ↑

          │       │

       Bank    Wallet

          ↑

          │

    OrderService

OrderService دیگر به یک implementation خاص وابسته نیست.


# ارتباط DIP و Dependency Injection

در مقاله قبلی درباره Dependency Injection در PHP دیدیم که Dependency را می‌توان از بیرون وارد کلاس کرد.

مثلاً:


class OrderService

{

    public function __construct(

        private PaymentGateway $payment

    ) {

    }

}

اینجا:

  • PaymentGateway یک abstraction است.
  • Dependency از بیرون تزریق می‌شود.
  • OrderService به implementation خاص وابسته نیست.

پس Dependency Injection یکی از تکنیک‌هایی است که می‌تواند به پیاده‌سازی طراحی مبتنی بر Dependency Inversion کمک کند.


# تفاوت SOLID با Design Pattern چیست؟

SOLID و Design Pattern یک چیز نیستند.

SOLID مجموعه‌ای از اصول طراحی است.

Design Pattern الگوهای حل مسائل رایج طراحی نرم‌افزار است.

مثلاً:


SOLID

 ↓

اصول طراحی

 ↓

کمک به تصمیم‌گیری معماری

اما:


Design Pattern

 ↓

الگوهای آماده برای مسائل رایج

الگوهایی مانند:

  • Factory
  • Strategy
  • Observer
  • Adapter
  • Repository

می‌توانند در کنار اصول SOLID استفاده شوند.


# آیا باید همیشه تمام اصول SOLID را رعایت کنیم؟

خیر.

SOLID یک قانون مطلق نیست که برای هر کلاس و هر پروژه بدون استثنا اجرا شود.

اگر یک پروژه بسیار کوچک دارید، ایجاد Interface و چندین کلاس برای یک عملیات ساده ممکن است فقط پیچیدگی اضافه ایجاد کند.

هدف این است که از اصول SOLID برای مدیریت پیچیدگی استفاده کنیم.

نه اینکه صرفاً تعداد کلاس‌ها را افزایش دهیم.


# یک مثال واقعی: سیستم تخفیف فروشگاه

فرض کنید ابتدا چنین کدی داریم:


class DiscountService

{

    public function calculate(

        string $type,

        float $price

    ): float {

        if ($type === 'percentage') {

            return $price * 0.9;

        }



        if ($type === 'fixed') {

            return $price - 100000;

        }



        return $price;

    }

}

هر بار که نوع تخفیف جدیدی اضافه شود، باید این کلاس را تغییر دهیم.

مثلاً:


Percentage

Fixed

Black Friday

VIP

Coupon

Seasonal

این طراحی به مرور بزرگ می‌شود.


# طراحی بهتر با Strategy و SOLID

می‌توانیم Interface داشته باشیم:


interface DiscountStrategy

{

    public function calculate(float $price): float;

}

تخفیف درصدی:


class PercentageDiscount implements DiscountStrategy

{

    public function calculate(float $price): float

    {

        return $price * 0.9;

    }

}

تخفیف ثابت:


class FixedDiscount implements DiscountStrategy

{

    public function calculate(float $price): float

    {

        return max(0, $price - 100000);

    }

}

سرویس:


class DiscountService

{

    public function __construct(

        private DiscountStrategy $strategy

    ) {

    }



    public function calculate(float $price): float

    {

        return $this->strategy->calculate($price);

    }

}

حالا اضافه کردن Strategy جدید نیازی به تغییر DiscountService ندارد.

مثلاً:


class VipDiscount implements DiscountStrategy

{

    public function calculate(float $price): float

    {

        return $price * 0.8;

    }

}

این مثال نشان می‌دهد چطور چند اصل SOLID می‌توانند همزمان در یک طراحی استفاده شوند.


# SOLID در پروژه‌های Laravel

اصول SOLID در Laravel اهمیت زیادی دارند؛ مخصوصاً در پروژه‌های متوسط و بزرگ.

مثلاً به جای قرار دادن تمام منطق در Controller:


class OrderController

{

    public function store()

    {

        // validate

        // calculate price

        // create order

        // payment

        // send notification

        // logging

    }

}

می‌توانیم مسئولیت‌ها را جدا کنیم:


Controller

    ↓

OrderService

    ↓

PaymentGateway

    ↓

Repository / Model

البته این به معنی آن نیست که هر Controller حتماً باید Service و Repository داشته باشد.

ساختار مناسب به پیچیدگی واقعی پروژه بستگی دارد.


# SOLID و Service Layer در Laravel

یکی از جاهایی که SOLID بسیار کاربردی می‌شود، Service Layer است.

مثلاً:


class OrderService

{

    public function __construct(

        private PaymentGateway $payment,

        private NotificationService $notification

    ) {

    }



    public function createOrder(): void

    {

        // business logic

    }

}

Controller فقط مسئول دریافت درخواست و هماهنگی اولیه است:


class OrderController

{

    public function store(

        OrderService $service

    ) {

        $service->createOrder();



        return response()->json([

            'success' => true

        ]);

    }

}

این ساختار می‌تواند خوانایی و تست‌پذیری پروژه را بهتر کند.


# SOLID و Repository Pattern

فرض کنید:


interface UserRepository

{

    public function find(int $id): ?User;

}

پیاده‌سازی:


class EloquentUserRepository implements UserRepository

{

    public function find(int $id): ?User

    {

        return User::find($id);

    }

}

سرویس:


class UserService

{

    public function __construct(

        private UserRepository $users

    ) {

    }



    public function findUser(int $id): ?User

    {

        return $this->users->find($id);

    }

}

در این ساختار، UserService مستقیماً به Eloquent implementation وابسته نیست.

البته استفاده از Repository Pattern در همه پروژه‌های Laravel ضروری نیست و باید متناسب با نیاز واقعی پروژه تصمیم گرفت.


# چطور بفهمیم کدمان با SOLID مشکل دارد؟

هیچ ابزار ساده‌ای وجود ندارد که فقط با یک دکمه بگوید «این پروژه SOLID است یا نیست».

اما چند نشانه هشداردهنده وجود دارد.

کلاس بسیار بزرگ

مثلاً کلاسی با صدها یا هزاران خط کد.

Constructor بسیار بزرگ

مثلاً:


public function __construct(

    A $a,

    B $b,

    C $c,

    D $d,

    E $e,

    F $f,

    G $g

) {

}

شرط‌های زیاد برای نوع Object

مثلاً:


if ($type === 'a') {

}



if ($type === 'b') {

}



if ($type === 'c') {

}



if ($type === 'd') {

}

وابستگی مستقیم به implementation

مثلاً:


new BankPayment();

در بخش‌های مختلف Business Logic.

Interface بسیار بزرگ

مثلاً Interfaceای با ۳۰ یا ۴۰ متد که هر implementation فقط تعداد کمی از آن‌ها را استفاده می‌کند.

این موارد می‌توانند نشانه‌هایی برای بازبینی طراحی باشند.


# مزایای استفاده از SOLID

اگر اصول SOLID به شکل صحیح و متناسب با پروژه استفاده شوند، می‌توانند مزایایی مثل موارد زیر ایجاد کنند:

  • افزایش خوانایی کد
  • کاهش Coupling
  • افزایش قابلیت تست
  • ساده‌تر شدن توسعه
  • ساده‌تر شدن تغییر implementation
  • کاهش تأثیر تغییرات
  • افزایش قابلیت نگهداری
  • ایجاد ساختار بهتر برای پروژه‌های بزرگ

اما باید توجه داشت که SOLID به‌تنهایی تضمین نمی‌کند یک پروژه معماری خوبی داشته باشد.

طراحی خوب به عوامل بیشتری بستگی دارد.


# معایب استفاده افراطی از SOLID

SOLID اگر بدون توجه به اندازه و نیاز پروژه استفاده شود، می‌تواند نتیجه معکوس داشته باشد.

مثلاً برای یک تابع ساده:


function calculateTax(float $price): float

{

    return $price * 0.1;

}

لازم نیست الزاماً این ساختار را ایجاد کنیم:


TaxInterface

TaxService

TaxFactory

TaxRepository

TaxStrategy

TaxManager

گاهی یک تابع ساده، بهترین راه‌حل است.

بنابراین:

> SOLID برای مدیریت پیچیدگی است، نه ایجاد پیچیدگی.


# چطور SOLID را در PHP یاد بگیریم؟

برای یادگیری صحیح SOLID بهتر است ترتیب زیر را دنبال کنید:

مرحله اول: OOP

ابتدا مفاهیم:

  • Class
  • Object
  • Encapsulation
  • Inheritance
  • Polymorphism

را یاد بگیرید.

مرحله دوم: Interface و Abstract Class

بعد:

  • Interface
  • Abstract Class
  • Trait

را به خوبی درک کنید.

مرحله سوم: Dependency Injection

سپس یاد بگیرید Dependencyها چگونه مدیریت و تزریق می‌شوند.

مرحله چهارم: SOLID

حالا پنج اصل SOLID بسیار قابل فهم‌تر خواهند شد.

مرحله پنجم: Design Pattern

بعد از درک SOLID، یادگیری Design Patternها بسیار منطقی‌تر می‌شود.


# خلاصه پنج اصل SOLID

بیایید همه اصول را در یک مثال ذهنی خلاصه کنیم.

S — Single Responsibility

هر کلاس مسئولیت مشخص و متمرکزی داشته باشد.


OrderService

PaymentService

EmailService

Logger

نه یک کلاس که همه این کارها را انجام دهد.


O — Open/Closed

برای اضافه کردن قابلیت جدید، تا جای ممکن implementation جدید اضافه کنیم و کد موجود را کمتر تغییر دهیم.


PaymentInterface

├── BankPayment

├── WalletPayment

└── CryptoPayment


L — Liskov Substitution

کلاس فرزند باید بتواند در جایگاه والد استفاده شود بدون اینکه قرارداد رفتاری را خراب کند.


I — Interface Segregation

Interfaceهای کوچک و تخصصی بهتر از یک Interface بزرگ و عمومی هستند.


D — Dependency Inversion

کلاس‌های سطح بالا را به abstraction وابسته کنیم، نه implementationهای خاص.


OrderService

      ↓

PaymentInterface

      ↑

BankPayment


# جمع‌بندی اصول SOLID در PHP

SOLID یکی از مهم‌ترین مفاهیم طراحی نرم‌افزار شی‌گرا است که به‌خصوص در پروژه‌های متوسط و بزرگ PHP اهمیت پیدا می‌کند.

این پنج اصل عبارت‌اند از:


S → Single Responsibility Principle

O → Open/Closed Principle

L → Liskov Substitution Principle

I → Interface Segregation Principle

D → Dependency Inversion Principle

اما نکته مهم این است که SOLID را نباید به یک قانون خشک تبدیل کنیم.

هدف SOLID این نیست که برای هر بخش کوچک پروژه Interface، Factory و چندین کلاس بسازیم.

هدف این اصول، مدیریت وابستگی، کاهش پیچیدگی و افزایش قابلیت توسعه و نگهداری کد است.

اگر از PHP ساده به سمت پروژه‌های حرفه‌ای PHP و Laravel حرکت می‌کنید، درک SOLID به شما کمک می‌کند دلیل بسیاری از الگوهای معماری را بهتر بفهمید.

بعد از یادگیری SOLID، قدم منطقی بعدی آشنایی با Design Pattern در PHP است؛ زیرا Design Patternها ابزارهایی هستند که می‌توانند در کنار اصول SOLID برای حل مسائل رایج طراحی نرم‌افزار استفاده شوند.


# سوالات متداول درباره SOLID در PHP

SOLID در PHP چیست؟

SOLID مجموعه‌ای از پنج اصل طراحی برای برنامه‌نویسی شی‌گرا است که به ایجاد کدی قابل توسعه، تست‌پذیر و قابل نگهداری کمک می‌کند.

پنج اصل SOLID چیست؟

پنج اصل SOLID عبارت‌اند از:

  1. Single Responsibility Principle
  2. Open/Closed Principle
  3. Liskov Substitution Principle
  4. Interface Segregation Principle
  5. Dependency Inversion Principle

مهم‌ترین اصل SOLID کدام است؟

هیچ‌کدام را نمی‌توان به‌صورت مطلق مهم‌ترین اصل دانست. اهمیت هر اصل به مسئله‌ای که در معماری پروژه با آن مواجه هستید بستگی دارد.

آیا SOLID فقط برای PHP است؟

خیر. SOLID مجموعه‌ای از اصول عمومی طراحی نرم‌افزار شی‌گرا است و در زبان‌های مختلف برنامه‌نویسی قابل استفاده است.

آیا برای پروژه‌های کوچک هم باید SOLID را رعایت کنیم؟

اصول SOLID می‌توانند در پروژه‌های کوچک هم مفید باشند، اما نباید باعث پیچیدگی غیرضروری شوند. میزان استفاده از این اصول باید با اندازه و پیچیدگی پروژه متناسب باشد.

تفاوت SOLID و Design Pattern چیست؟

SOLID مجموعه‌ای از اصول طراحی است، در حالی که Design Patternها الگوهای حل مسائل رایج در طراحی نرم‌افزار هستند.

ارتباط Dependency Injection با SOLID چیست؟

Dependency Injection یکی از تکنیک‌هایی است که می‌تواند برای پیاده‌سازی طراحی منطبق با Dependency Inversion Principle استفاده شود.

آیا Laravel از اصول SOLID استفاده می‌کند؟

Laravel در بخش‌های مختلف معماری خود از مفاهیمی مانند Dependency Injection، Service Container و abstraction استفاده می‌کند که با بسیاری از اصول طراحی شی‌گرا ارتباط دارند.

آیا رعایت SOLID کد را همیشه بهتر می‌کند؟

خیر. اگر SOLID بدون توجه به نیاز واقعی پروژه و به شکل افراطی استفاده شود، می‌تواند تعداد کلاس‌ها و پیچیدگی پروژه را افزایش دهد. اصل مهم، استفاده متناسب و هدفمند از این اصول است.


# پیشنهاد لینک‌سازی داخلی

برای این مقاله، لینک‌سازی داخلی اهمیت زیادی دارد، چون SOLID در واقع نقطه اتصال چند مقاله قبلی و چند مقاله بعدی کلاستر OOP است.

لینک به مقالات قبلی

  • Class و Object در PHP
  • انکرتکست: Class و Object در PHP

  • Inheritance در PHP
  • انکرتکست: ارث‌بری در PHP

  • Interface در PHP
  • انکرتکست: Interface در PHP

  • Abstract Class در PHP
  • انکرتکست: Abstract Class در PHP

  • Trait در PHP
  • انکرتکست: Trait در PHP

  • Dependency Injection در PHP
  • انکرتکست: Dependency Injection در PHP

لینک به مقالات بعدی

  • Design Pattern در PHP
  • انکرتکست: Design Pattern در PHP

  • MVC چیست؟
  • انکرتکست: معماری MVC در PHP

  • REST API با PHP
  • انکرتکست: ساخت REST API با PHP

لینک به Pillar

یک لینک طبیعی به صفحه اصلی کلاستر:

آموزش برنامه نویسی وب از صفر تا پیشرفته؛ PHP، Laravel، MySQL و توسعه وب

قرار دهید.


# ساختار این مقاله در Topic Cluster


آموزش برنامه نویسی وب و PHP

│

└── آموزش PHP

    │

    └── برنامه‌نویسی شی‌گرا (OOP)

        │

        ├── Class و Object

        ├── Inheritance

        ├── Interface

        ├── Trait

        ├── Abstract Class

        ├── Dependency Injection

        ├── SOLID ← این مقاله

        └── Design Pattern

در این ساختار، مقاله SOLID نقش مهمی دارد؛ چون مفاهیمی که در مقالات Interface، Abstract Class و Dependency Injection یاد گرفته شده‌اند را به سطح بالاتری از طراحی نرم‌افزار متصل می‌کند.

نظرات (0)

نظرات پس از تأیید مدیر نمایش داده می‌شوند

هنوز نظری ثبت نشده است؛ اولین نفر باشید!

مقالات مرتبط

ساخت CMS با Laravel 12؛ آموزش ساخت سیستم مدیریت محتوا از صفر

ساخت CMS با Laravel 12؛ آموزش ساخت سیستم مدیریت محتوا از صفر

۲۴ دقیقه
ساخت فروشگاه اینترنتی با Laravel 12؛ آموزش پروژه‌محور از صفر تا طراحی هسته فروشگاه

ساخت فروشگاه اینترنتی با Laravel 12؛ آموزش پروژه‌محور از صفر تا طراحی هسته فروشگاه

۲۲ دقیقه
ساخت Marketplace با Laravel؛ آموزش طراحی فروشگاه چندفروشندگی

ساخت Marketplace با Laravel؛ آموزش طراحی فروشگاه چندفروشندگی

۲۲ دقیقه
مدیریت Queueهای سنگین در Laravel؛ آموزش پردازش کارهای طولانی

مدیریت Queueهای سنگین در Laravel؛ آموزش پردازش کارهای طولانی

۲۲ دقیقه