TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 548 subscribers
Post #103 128
5️⃣ اصل پنجم SOLID: وارونگی وابستگی (Dependency Inversion Principle)

تا حالا شده یه کلاس بنویسید که داخلش یه کلاس دیگه رو با new می‌سازید و بعداً برای تغییر اون کلاس داخلی، مجبور میشید کلاس اصلی رو هم دستکاری کنید؟ این یعنی کدهای شما به هم سفت و سخت (Tightly Coupled) وصل شدن.

اصل وارونگی وابستگی (DIP) برای حل همین مشکل و ایجاد کدهای انعطاف‌پذیر طراحی شده.

این اصل چی میگه؟ 🎯
این اصل دو بخش مهم داره:
ماژول‌های سطح بالا نباید به ماژول‌های سطح پایین وابسته باشند. هر دو باید به انتزاع (Abstraction) وابسته باشند.

انتزاع‌ها نباید به جزئیات وابسته باشند. این جزئیات هستن که باید به انتزاع‌ها وابسته باشند.
به زبان ساده: کلاس‌های اصلی و سطح بالای شما (مثلاً بیزنس لاجیک) نباید به جزئیات پیاده‌سازی (مثلاً نحوه کار با دیتابیس یا ارسال ایمیل) وابسته باشن. در عوض، هر دو باید به یک قرارداد مشترک (Interface) وابسته باشن.

مثال عملی: سیستم اطلاع‌رسانی
فرض کنید یه سیستمی برای اطلاع‌رسانی به کاربر داریم.

مثال بد (نقض اصل وارونگی وابستگی):
اینجا کلاس سطح بالای Notification مستقیماً به کلاس سطح پایین EmailSender وابسته است. اگه فردا بخوایم به جای ایمیل، با SMS اطلاع‌رسانی کنیم، مجبوریم کلاس Notification رو تغییر بدیم. این یعنی وابستگی سفت و سخت.
// ❌ این کلاس سطح پایین است
public class EmailSender
{
public void Send() => Console.WriteLine("Email sent!");
}

// ❌ این کلاس سطح بالاست و مستقیماً به کلاس پایینی وابسته است
public class Notification
{
private readonly EmailSender _emailSender = new EmailSender();

public void SendNotification()
{
_emailSender.Send();
}
}


مثال خوب (رعایت اصل وارونگی وابستگی):
حالا با استفاده از یک Interface، این وابستگی رو "وارونه" می‌کنیم.

قدم اول: ساختن قرارداد (Interface)
این قرارداد در لایه سطح بالا تعریف میشه.
public interface IMessageSender
{
void SendMessage();
}

قدم دوم: کلاس‌های سطح پایین از قرارداد پیروی می‌کنند
public class EmailSender : IMessageSender
{
public void SendMessage() => Console.WriteLine("Email sent!");
}

public class SmsSender : IMessageSender
{
public void SendMessage() => Console.WriteLine("SMS sent!");
}

قدم سوم: کلاس سطح بالا به قرارداد وابسته است، نه به جزئیات
public class Notification
{
private readonly IMessageSender _sender;

// وابستگی از طریق Constructor تزریق می‌شود (Dependency Injection)
public Notification(IMessageSender sender)
{
_sender = sender;
}

public void SendNotification()
{
_sender.SendMessage();
}
}

جادو اینجا اتفاق میفته: حالا کلاس Notification دیگه کاری نداره که پیام چطوری ارسال میشه (با ایمیل یا SMS). اون فقط "قرارداد" رو می‌شناسه. ما می‌تونیم موقع ساختن آبجکت Notification، هر نوع IMessageSender که دوست داریم رو بهش پاس بدیم، بدون اینکه یک کلمه از کدش رو تغییر بدیم!

🤔 حرف حساب و تجربه شما
این DIP قلب معماری‌های تمیز و مدرنه و اساس کار تزریق وابستگی (Dependency Injection) هست. رعایت این اصل، کد شما رو فوق‌العاده انعطاف‌پذیر، قابل تست و توسعه‌پذیر می‌کنه.

شما چقدر به این اصل در پروژه‌هاتون اهمیت میدید؟ بهترین مثالی که از کاربرد این اصل تو ذهنتون دارید چیه؟

💬 بحث و گفتگوی بیشتر در گروه کامیونیتی:
[C# Geeks Community]

🔖 هشتگ‌ها:
#CSharp #Programming #Developer #SOLID #SoftwareArchitecture #CleanCode #DIP
More from @csharpgeeks
  1. Sep 22, 2026یه مدتی قراره از دنیای NET. فاصله بگیرم، چون وقتشه برم سربازی. راستش نمیدونم این مدت رو چج…
  2. Sep 20, 2026🔥 حالا مشکل اصلی: Alert Storm فرض کن Database از دسترس خارج شده. ۱۰۰ Pod داری. هر Pod می‌…
  3. Sep 20, 2026🚨 طراحی سیستم Monitoring و Alerting در یک سیستم بزرگ فرض کن ساعت ۳ صبح است. سیستم شما با…
  4. Sep 19, 2026#Engineering_Leadership تصمیم نگرفتن هم یک تصمیم است یه چیز عجیب توی تیم‌های مهندسی: گاهی…
  5. Sep 19, 2026☑ چک‌لیست آماده‌سازی تیم، فرایندها و زیرساخت برای توسعه با AI توجه: هیچ چک‌لیستی جهان‌شمول…
  6. Sep 19, 2026📌پایان یک انتظار طولانی: اعتبارسنجی ناهمگام (Async Validation) در NET 11.
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →