راهنمای جامع پیاده‌سازی اصول SOLID در پروژه‌های .NET Core

در دنیای توسعه نرم‌افزار، نوشتن کدی که فقط "کار کند" کافی نیست. چالش اصلی زمانی آغاز می‌شود که نیاز به تغییر، توسعه یا رفع خطا در پروژه‌های بزرگ پیدا می‌کنیم. اصول SOLID مجموعه‌ای از پنج اصل طراحی شیءگرا هستند که توسط رابرت سی. مارتین (Uncle Bob) معرفی شدند تا نرم‌افزارها را انعطاف‌پذیرتر، قابل‌فهم‌تر و نگهداری آن‌ها را آسان‌تر کنند. در این مقاله، هر یک از این پنج اصل را با مثال‌های کاربردی در اکوسیستم .NET Core بررسی می‌کنیم.
کینگتو - آموزش برنامه نویسی تخصصصی - دات نت - سی شارپ - بانک اطلاعاتی و امنیت

راهنمای جامع پیاده‌سازی اصول SOLID در پروژه‌های .NET Core

13 بازدید 0 نظر ۱۴۰۴/۰۹/۲۶

اصل مسئولیت واحد (Single Responsibility Principle - SRP)

تعریف: یک کلاس فقط باید یک دلیل برای تغییر داشته باشد. به عبارت دیگر، هر کلاس باید فقط یک وظیفه یا مسئولیت مشخص را بر عهده بگیرد.

 

در .NET Core چه می‌گذرد؟

بسیاری از توسعه‌دهندگان عادت دارند منطق تجاری (Business Logic)، دسترسی به پایگاه داده و لاگ کردن را در یک Controller یا Service قرار دهند. این نقض صریح SRP است.

مثال نقض: کلاسی که هم فاکتور را محاسبه می‌کند و هم آن را در دیتابیس ذخیره کرده و ایمیل می‌فرستد.

راهکار پیاده‌سازی: جدا کردن وظایف در لایه‌های مختلف (Services, Repositories, Helpers).

// به جای یک کلاس شلوغ، وظایف را تقسیم می‌کنیم
public class InvoiceService {
    public void CreateInvoice(Invoice inv) { /* محاسبه منطق فاکتور */ }
}

public class EmailService {
    public void SendEmail(string message) { /* ارسال ایمیل */ }
}

 

اصل باز/بسته (Open/Closed Principle - OCP)

تعریف: موجودیت های نرم‌افزاری (کلاس‌ها، ماژول‌ها و ...) باید برای توسعه باز اما برای تغییر بسته باشند.

 

پیاده‌سازی با Interface و Inheritance

در .NET Core، ما نباید برای اضافه کردن یک قابلیت جدید، کدهای قبلی را که تست شده‌اند دستکاری کنیم. به جای استفاده از if-else یا switch برای چک کردن نوع اشیاء، از Interface یا Abstract Class استفاده می‌کنیم.

مثال کاربردی: سیستم درگاه پرداخت. اگر بخواهیم درگاه "ملت" را اضافه کنیم، نباید کد کلاس PaymentProcessor را تغییر دهیم. بلکه باید یک Interface به نام IPaymentGateway بسازیم.

public interface IPaymentGateway {
    void ProcessPayment(decimal amount);
}

public class MellatGateway : IPaymentGateway {
    public void ProcessPayment(decimal amount) { /* پیاده‌سازی اختصاصی */ }
}

public class SamanGateway : IPaymentGateway {
    public void ProcessPayment(decimal amount) { /* پیاده‌سازی اختصاصی */ }
}

 

اصل جایگزینی لیسکوف (Liskov Substitution Principle - LSP)

تعریف: کلاس‌های فرزند باید بتوانند بدون تغییر در صحت برنامه، جایگزین کلاس‌های پدر خود شوند.

 

نکته کلیدی در .NET

اگر شما یک متد را در کلاس پدر تعریف کنید اما در کلاس فرزند برای آن throw new NotImplementedException() بنویسید، شما اصل LSP را نقض کرده‌اید.

مثال کلاسیک: مستطیل و مربع. مربع یک مستطیل است، اما اگر تغییر عرض مربع باعث تغییر طول آن شود (در حالی که در مستطیل اینطور نیست)، رفتار برنامه در صورت جایگزینی به هم می‌ریزد.

در پروژه واقعی: همیشه اطمینان حاصل کنید که کلاس‌های مشتق شده، قرارداد (Contract) کلاس پایه را حفظ می‌کنند.

 

اصل جداسازی اینترفیس (Interface Segregation Principle - ISP)

تعریف: کلاینت‌ها نباید مجبور شوند به متدهایی وابسته باشند که از آن‌ها استفاده نمی‌کنند.

پیاده‌سازی در .NET Core

به جای ساختن اینترفیس‌های غول‌آسا (Fat Interfaces) که ده‌ها متد دارند، آن‌ها را به اینترفیس‌های کوچک‌تر و تخصصی‌تر تقسیم کنید.

مثال: فرض کنید یک دستگاه چندکاره دارید.

// اشتباه: همه مجبور به پیاده سازی همه چیز هستند
public interface IMachine {
    void Print();
    void Scan();
    void Fax();
}

// درست: جداسازی بر اساس نیاز
public interface IPrinter { void Print(); }
public interface IScanner { void Scan(); }

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

 

اصل وارونگی وابستگی (Dependency Inversion Principle - DIP)

تعریف: ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشند؛ هر دو باید به "انتزاع" (Abstraction) وابسته باشند.

قدرت Dependency Injection در .NET Core

این مهم‌ترین اصل در معماری .NET Core است. فریم‌ورک .NET Core به صورت داخلی دارای یک کانتینر Dependency Injection (DI) است که به ما کمک می‌کند این اصل را به بهترین شکل پیاده کنیم.

چرا مهم است؟ وابستگی مستقیم به یک کلاس خاص (مثل SqlRepository) باعث می‌شود تست‌نویسی (Unit Testing) غیرممکن شود. با استفاده از DIP، ما به Interface وابسته می‌شویم.

نحوه ثبت در Program.cs:

builder.Services.AddScoped();

در کنترلر، ما فقط به اینترفیس درخواست می‌دهیم:

public class UserController : ControllerBase {
    private readonly IUserRepository _repository;
    
    public UserController(IUserRepository repository) {
        _repository = repository; // کلاینت نمی‌داند دیتابیس چیست، فقط با قرارداد کار می‌کند
    }
}

 

مزایای استفاده از SOLID در پروژه‌های دات‌نت

۱. تست‌پذیری (Testability): به دلیل استفاده از DI و Interfaceها، به راحتی می‌توان از کتابخانه‌هایی مثل Moq برای نوشتن Unit Test استفاده کرد. ۲. نگهداری آسان: وقتی کدها تفکیک شده باشند، تغییر در یک بخش باعث خرابی در بخش‌های دیگر نمی‌شود. ۳. توسعه تیمی: اعضای تیم می‌توانند همزمان روی بخش‌های مختلف (که از طریق اینترفیس به هم وصل شده‌اند) کار کنند بدون اینکه تداخلی ایجاد شود.

 

نتیجه‌گیری

اصول SOLID قوانینی سفت و سخت نیستند، بلکه ابزاری هستند تا شما را از "کد کثیف" نجات دهند. در .NET Core، ابزارهایی مثل Middlewareها، Dependency Injection و Genericها کاملاً هماهنگ با این اصول طراحی شده‌اند. پیاده‌سازی این اصول شاید در ابتدا زمان‌بر به نظر برسد، اما در طولانی مدت، هزینه‌های نگهداری پروژه را به شدت کاهش می‌دهد.

 
 
لینک استاندارد شده: pzflCMdE

0 نظر

    هنوز نظری برای این مقاله ثبت نشده است.
جستجوی مقاله و آموزش
دوره‌ها با تخفیفات ویژه