TGViewer
C# Geeks (.NET) C# Geeks (.NET) @csharpgeeks · 550 subscribers
Post #794 300
🏗 راز معماری نابودنشدنی با Coupling و Cohesion

اگر بخواهیم فقط با دو مفهوم بفهمیم یک طراحی نرم‌افزاری چقدر سالم است، یکی از بهترین نقاط شروع این دو مفهوم‌اند:
🔗 Coupling
🧩 Cohesion
خیلی وقت‌ها این دو را کنار هم می‌شنویم، اما دقیقاً نمی‌دانیم چه مشکلی را حل می‌کنند.
بیایید از یک سؤال ساده شروع کنیم:
اگر فردا بخواهیم یک قسمت از سیستم را تغییر بدهیم، چند قسمت دیگر مجبور می‌شوند همراه آن تغییر کنند؟

پاسخ این سؤال، ما را مستقیماً به سمت Coupling می‌برد.
🔗 ءCoupling چیست؟

ءCoupling یعنی میزان وابستگی بین Components مختلف سیستم.
هرچه دو Component برای کار کردن بیشتر به جزئیات یکدیگر وابسته باشند، Coupling آن‌ها بیشتر است.
مثلاً:
{

    private readonly PaymentService _payment;
    private readonly InventoryService _inventory;
    private readonly EmailService _email;
    public async Task CreateOrder()
    {
        await _payment.Pay();
        await _inventory.Reserve();
        await _email.Send();
    }
}
اینجا OrderService مستقیماً به سه Component دیگر وابسته است.
حالا فرض کنید API مربوط به PaymentService تغییر کند.
احتمالاً باید OrderService را هم تغییر بدهیم.
این یعنی یک تغییر محلی، اثر خود را به بیرون منتقل کرده است.
این همان چیزی است که در معماری می‌خواهیم تا حد امکان کنترلش کنیم.
🧩 ءCohesion چیست؟

ءCohesion تقریباً سؤال برعکس را می‌پرسد:
چیزهایی که داخل یک Component قرار داده‌ایم، واقعاً چقدر به یکدیگر مربوط هستند؟

اگر یک کلاس، Module یا Service روی یک هدف مشخص متمرکز باشد، Cohesion بالاتری دارد.
مثلاً:
 ├── AddItem()
 ├── RemoveItem()
 ├── CalculateTotal()
 └── ApplyDiscount()

تمام این رفتارها حول یک مفهوم مشترک قرار گرفته‌اند:🎯 Order
این یعنی Cohesion مناسب.
اما اگر همان کلاس تبدیل شود به:
 ├── CreateOrder()
 ├── SendEmail()
 ├── ResizeImage()
 ├── GenerateReport()
 ├── CreateUser()
 ├── ProcessPayment()
 └── ClearCache()

دیگر یک مسئولیت مشخص نداریم.
کلاس به یک محل تجمع Business Logicهای نامرتبط تبدیل شده است.
اینجا Cohesion پایین آمده است.

🎯 پس هدف معماری چیست؟
یک قاعده بسیار مهم:
High Cohesion + Low Coupling

یعنی:
🧩 داخل هر Component، چیزهایی که واقعاً به هم مربوط‌اند کنار هم باشند.
و:
🔗 بین Componentها، وابستگی غیرضروری حداقل باشد.
این ترکیب یکی از اصول مهم در طراحی سیستم‌های قابل نگهداری و قابل تغییر است. AWS نیز در راهنمای معماری خود برای Microservices صراحتاً بر Loose Coupling و High Functional Cohesion تأکید می‌کند.
💣 اما یک نکته مهم وجود دارد... Low Coupling به معنی:
«هیچ وابستگی‌ای نباید وجود داشته باشد»

نیست.
این تصور اشتباه است.
یک سیستم بدون وابستگی عملاً وجود ندارد.
مثلاً:
   ↓
Payment

ءOrderبرای انجام یک فرآیند ممکن است واقعاً به Payment نیاز داشته باشد.
مسئله این نیست که Dependency را صفر کنیم.
مسئله این است که:
ءDependencyها را در مرزهای درست قرار دهیم.

🎯 یک معیار بسیار کاربردی
وقتی می‌خواهی تصمیم بگیری دو Component باید کنار هم باشند یا جدا، این سؤال‌ها را بپرس:
🔹 آیا معمولاً با هم تغییر می‌کنند؟
🔹 آیا برای انجام یک Business Capability به یکدیگر نیاز دارند؟
🔹 آیا داده‌هایشان به شدت به هم وابسته است؟
🔹 آیا Transactionهای مشترک دارند؟
🔹 آیا یکی بدون دیگری می‌تواند مستقل Deploy شود؟
🔹 آیا یکی باید بتواند بدون دیگری کار کند؟
🔹 آیا تیم‌های متفاوت مسئول آن‌ها هستند؟
این سؤال‌ها به ما کمک می‌کنند Boundary را بر اساس رفتار واقعی سیستم پیدا کنیم، نه بر اساس سلیقه.
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 →