دیروز

Clean Architecture چیست؟ معماری تمیز برنامه‌نویسی

Clean Architecture چیست؟ راهنمای ساده معماری تمیز در برنامه‌نویسی

 
فرض کنید یک اپلیکیشن فروش آنلاین دارید که در آن کاربر می‌تواند محصول جست‌وجو کند، سفارش ثبت کند و آنلاین هزینه آن را پرداخت کند.
 
همه‌چیز در ابتدا ساده به نظر می‌رسد؛ چند صفحه، چند API و یک دیتابیس.
 
اما بعد از مدتی امکانات جدیدی اضافه می‌شوند:
 
پرداخت آنلاین
ارسال پیامک
ورود با گوگل
سیستم تخفیف
کیف پول
اعلان‌های لحظه‌ای
گزارش‌گیری
اتصال به چند سرویس خارجی
 
حالا اگر همه این بخش‌ها مستقیماً به یکدیگر وابسته باشند، کوچک‌ترین تغییر می‌تواند چند قسمت مختلف برنامه را تحت تأثیر قرار دهد.
 
مثلاً تصمیم می‌گیرید دیتابیس را از SQL Server به PostgreSQL تغییر دهید؛ ناگهان بخش‌هایی از منطق برنامه، سرویس‌ها و حتی کدهای مربوط به سفارش با مشکل مواجه می‌شوند.
 
اینجاست که یک سؤال مهم مطرح می‌شود:
 
چطور می‌توانیم برنامه‌ای بسازیم که با بزرگ‌تر شدن، همچنان قابل فهم، قابل تست و قابل تغییر باقی بماند؟
 
یکی از پاسخ‌های مهم به این سؤال، Clean Architecture یا معماری تمیز است.
 

Clean Architecture چیست؟

 
Clean Architecture یک روش برای سازمان‌دهی ساختار نرم‌افزار است که هدف آن جدا کردن بخش‌های مختلف برنامه و کاهش وابستگی بین آن‌هاست.
 
به زبان ساده، در Clean Architecture تلاش می‌کنیم:
 
منطق اصلی برنامه به تکنولوژی‌های خاص وابسته نباشد.
 
یعنی منطق اصلی فروشگاه شما نباید به SQL Server، ASP.NET، یک API خاص یا حتی یک سرویس پرداخت خاص وابسته باشد.
 
در این معماری، هر بخش وظیفه مشخصی دارد و وابستگی‌ها به شکلی کنترل می‌شوند که تغییر یک قسمت، کل برنامه را به هم نریزد.
 

چرا Clean Architecture به وجود آمد؟

 
فرض کنید در یک پروژه کوچک، تمام کدها را داخل چند فایل قرار داده‌اید:
 
Controllers
Services
Database
Models
 
در ابتدای کار شاید مشکلی وجود نداشته باشد.
 
اما پروژه بزرگ‌تر می‌شود.
 
تعداد کاربران افزایش پیدا می‌کند، قابلیت‌های بیشتری اضافه می‌شوند و تعداد برنامه‌نویسان تیم نیز بیشتر می‌شود.
 
بعد از مدتی ممکن است یک تغییر ساده مثل:
 
«روش پرداخت را عوض کنیم»
 
باعث شود چندین فایل مختلف را تغییر دهید.
 
یا حتی بدتر:
 
«دیتابیس را تغییر دهیم»
 
و ناگهان بخش زیادی از منطق برنامه از کار بیفتد.
 
Clean Architecture تلاش می‌کند چنین وابستگی‌هایی را کاهش دهد.
 

ایده اصلی Clean Architecture چیست؟

 
برای درک Clean Architecture لازم نیست ابتدا با اصطلاحات پیچیده شروع کنیم.
 

یک مثال واقعی را تصور کنید.

 
فرض کنید در یک رستوران هستید.
 
مشتری سفارش خود را ثبت می‌کند.
 
سفارش به آشپزخانه می‌رود.
 
آشپز غذا را آماده می‌کند.
 
صندوقدار هزینه را دریافت می‌کند.
 
در این فرایند، قانون اصلی کسب‌وکار این است که:
 
مشتری باید غذای سفارش‌داده‌شده را دریافت کند و هزینه آن پرداخت شود.
 
حالا مهم نیست رستوران از چه دستگاه کارت‌خوانی استفاده می‌کند یا سفارش‌ها روی کاغذ نوشته می‌شوند یا داخل یک تبلت ثبت می‌شوند.
 
منطق اصلی رستوران نباید به برند کارت‌خوان وابسته باشد.
 
Clean Architecture نیز تقریباً همین ایده را در نرم‌افزار پیاده می‌کند.
 

لایه‌های Clean Architecture

 
Clean Architecture معمولاً به چند لایه اصلی تقسیم می‌شود.
 
مهم‌ترین آن‌ها عبارت‌اند از:
 
Entities
Use Cases / Application
Interface Adapters
Frameworks & Infrastructure
 
البته در پروژه‌های مختلف ممکن است نام‌گذاری یا تعداد لایه‌ها کمی متفاوت باشد، اما ایده اصلی مشابه است.
 

1. Entities؛ قلب برنامه

 
Entities شامل مهم‌ترین قوانین و مفاهیم اصلی سیستم هستند.
 
برای مثال در یک فروشگاه اینترنتی می‌توانیم موجودیت‌هایی مانند این‌ها داشته باشیم:
 
User
Product
Order
Payment
Cart
 
مثلاً یک Order می‌تواند قوانینی داشته باشد که مشخص کند سفارش چگونه ایجاد یا تغییر کند.
 
نکته مهم این است که این بخش نباید به تکنولوژی خاصی وابسته باشد.
 
برای مثال، Entity مربوط به سفارش نباید بداند:
 
SQL Server چیست.
ASP.NET Core چیست.
HTTP چیست.
API چگونه کار می‌کند.
اطلاعات دقیقاً در کدام دیتابیس ذخیره می‌شوند.
 
این بخش باید فقط روی قوانین اصلی سیستم تمرکز کند.
 

2. Use Cases؛ برنامه چه کاری باید انجام دهد؟

 
در این لایه مشخص می‌کنیم برنامه قرار است چه کارهایی انجام دهد.
 
مثلاً در فروشگاه اینترنتی:
 
ثبت سفارش
لغو سفارش
افزودن محصول به سبد خرید
محاسبه قیمت نهایی
اعمال کد تخفیف
پرداخت سفارش
 
برای مثال:
 
CreateOrder
CancelOrder
ApplyDiscount
PayOrder
 
فرض کنید کاربر می‌خواهد یک سفارش ثبت کند.
 
Use Case می‌تواند این فرایند را مدیریت کند:
 
دریافت اطلاعات سفارش
       ↓
بررسی موجودی محصول
       ↓
 محاسبه قیمت
       ↓
 اعمال تخفیف
       ↓
 ثبت سفارش
       ↓
   پرداخت
 
نکته مهم این است که Use Case نباید درگیر جزئیات غیرضروری مانند نحوه ذخیره اطلاعات در SQL Server باشد.
 

3. Interface Adapters؛ مترجم بین بخش‌ها

 
حالا فرض کنید Use Case شما اطلاعات سفارش را می‌خواهد، اما اطلاعات در یک دیتابیس ذخیره شده است.
 
اینجا Interface Adapters وارد عمل می‌شوند.
 
این لایه می‌تواند اطلاعات را بین قسمت‌های مختلف برنامه تبدیل و منتقل کند.
 
برای مثال:
 
Database
      ↓
Repository
      ↓
Use Case
      ↓
Controller
      ↓
API Response
 
در این بخش معمولاً با مفاهیمی مانند موارد زیر مواجه می‌شویم:
 
Controllers
Presenters
Repositories
DTOs
Mappers

4. Frameworks & Infrastructure؛ جزئیات بیرونی برنامه

 
در بیرونی‌ترین بخش معماری، تکنولوژی‌هایی قرار می‌گیرند که برنامه برای اجرا به آن‌ها نیاز دارد.
 
برای مثال:
 
ASP.NET Core
SQL Server
PostgreSQL
Redis
Entity Framework Core
سرویس پرداخت
سرویس ارسال پیامک
سرویس ایمیل
 
این قسمت‌ها مهم هستند، اما نباید قلب برنامه را کنترل کنند.
 
مثلاً اگر امروز از SQL Server استفاده می‌کنید و چند ماه بعد تصمیم بگیرید PostgreSQL را جایگزین آن کنید، ideally نباید مجبور شوید منطق اصلی سفارش را از ابتدا بنویسید.
 

قانون مهم Clean Architecture چیست؟

 
یکی از مهم‌ترین مفاهیم Clean Architecture، Dependency Rule یا قانون وابستگی است.
 
به زبان ساده:
 
وابستگی‌ها باید به سمت داخل معماری حرکت کنند.
 
یعنی لایه‌های بیرونی می‌توانند به لایه‌های داخلی وابسته باشند، اما لایه‌های داخلی نباید به جزئیات بیرونی وابسته شوند.
 

مثلاً:

 
Infrastructure
      ↓
Application
      ↓
Domain
 
اما نباید به این شکل باشد:
 
Domain
     ↓
SQL Server
 

چرا؟

چون Domain نباید اهمیتی بدهد که اطلاعات در SQL Server ذخیره می‌شوند یا PostgreSQL یا حتی یک فایل ساده.
 

یک مثال ساده با کدنویسی

 
فرض کنید می‌خواهیم سفارش یک کاربر را ذخیره کنیم.
 
به جای اینکه Use Case مستقیماً با دیتابیس کار کند، یک قرارداد یا Interface تعریف می‌کنیم:
 
public interface IOrderRepository
{
    Task SaveAsync(Order order);
}
 
حالا Use Case می‌تواند از این Interface استفاده کند:
 
public class CreateOrder
{       
    private readonly IOrderRepository _repository;
 
    public CreateOrder(IOrderRepository repository)
    {   
        _repository = repository;
    }     
 
    public async Task Execute(Order order)
    {     
        // قوانین ثبت سفارش
        await _repository.SaveAsync(order);
    }  
 
در اینجا Use Case نمی‌داند سفارش دقیقاً کجا ذخیره می‌شود.
 
ممکن است در پشت این Interface از SQL Server استفاده کنیم:
 
IOrderRepository
       ↓
SqlOrderRepository
       ↓
SQL Server
 
یا بعدها آن را به PostgreSQL متصل کنیم:
 
IOrderRepository
       ↓
PostgresOrderRepository
       ↓
PostgreSQL
 
در هر دو حالت، منطق اصلی CreateOrder تقریباً بدون تغییر باقی می‌ماند.
 
این یکی از قدرت‌های مهم Clean Architecture است.
 

Clean Architecture چه مشکلی را حل می‌کند؟

 
فرض کنید یک اپلیکیشن فروش بلیت هواپیما ساخته‌اید.
 
در نسخه اول فقط یک شرکت هواپیمایی وجود دارد.
 
اما بعداً تصمیم می‌گیرید سیستم را به چند شرکت مختلف متصل کنید.
 
اگر منطق برنامه مستقیماً داخل API یک شرکت نوشته شده باشد، تغییر سیستم بسیار سخت می‌شود.
 
اما اگر ساختار برنامه به‌درستی طراحی شده باشد:
 
Business Rules
      ↓
Application
      ↓
Interfaces
      ↓
Airline API / Database / Payment
 
می‌توانیم سرویس‌های بیرونی را راحت‌تر تغییر دهیم.
 
به همین دلیل Clean Architecture بیشتر از اینکه درباره «پوشه‌بندی کدها» باشد، درباره مدیریت وابستگی‌ها و جداسازی مسئولیت‌ها است.
 

مزایای Clean Architecture چیست؟

 
استفاده درست از Clean Architecture می‌تواند مزایای مهمی داشته باشد:
 

1. تست‌پذیری بیشتر

 
وقتی منطق اصلی برنامه به دیتابیس و سرویس‌های خارجی وابسته نباشد، تست کردن آن ساده‌تر می‌شود.
 

2. تغییر آسان‌تر تکنولوژی‌ها

 
اگر بخواهید دیتابیس، سرویس پرداخت یا حتی بعضی ابزارهای زیرساختی را تغییر دهید، تأثیر تغییرات کمتر می‌شود.
 

3. نگهداری راحت‌تر پروژه

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

4. مناسب برای پروژه‌های بزرگ

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

5. همکاری بهتر تیمی

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

آیا Clean Architecture برای همه پروژه‌ها لازم است؟

خیر.
 
این یکی از نکات مهمی است که هنگام یادگیری Clean Architecture باید بدانید.
 
اگر می‌خواهید یک پروژه بسیار کوچک بسازید؛ مثلاً:
 
یک برنامه تمرینی ساده
یک پروژه شخصی کوچک
یک API با چند Endpoint
یک نمونه آموزشی
 
استفاده از ساختار بسیار پیچیده ممکن است فقط کدهای بیشتری ایجاد کند.
 
Clean Architecture زمانی ارزش بیشتری پیدا می‌کند که:
 
پروژه بزرگ باشد.
قرار باشد مدت زیادی توسعه پیدا کند.
چند برنامه‌نویس روی پروژه کار کنند.
قوانین کسب‌وکار پیچیده باشند.
تست‌نویسی اهمیت داشته باشد.
احتمال تغییر تکنولوژی‌ها وجود داشته باشد.
 
پس هدف Clean Architecture این نیست که هر پروژه‌ای را پیچیده کنیم.
 
هدف این است که وقتی پیچیدگی پروژه زیاد شد، بتوانیم آن را مدیریت کنیم.
 

تفاوت Clean Architecture با MVC چیست؟

 
یکی از سؤال‌های رایج برنامه‌نویسان این است که:
 

آیا Clean Architecture همان MVC است؟

خیر.
 
MVC بیشتر یک الگوی معماری برای جدا کردن بخش‌های مرتبط با رابط کاربری و درخواست‌ها است.
 
در MVC معمولاً با این مفاهیم روبه‌رو هستیم:
 
Model
View
Controller
 
اما Clean Architecture نگاه گسترده‌تری به ساختار کل برنامه دارد و تلاش می‌کند منطق کسب‌وکار را از جزئیات فنی و زیرساختی جدا کند.
 
در یک پروژه ASP.NET Core حتی می‌توانیم از MVC در کنار Clean Architecture استفاده کنیم.
 
برای مثال:
 
Clean Architecture                        
│                                                
├── Domain                             
├── Application                       
├── Infrastructure                   
└── Presentation                     
       └── ASP.NET Core MVC
 
بنابراین این دو الزاماً رقیب یکدیگر نیستند.
 

Clean Architecture و Dependency Injection

 
یکی دیگر از مفاهیمی که معمولاً در پروژه‌های دارای Clean Architecture زیاد با آن مواجه می‌شویم، Dependency Injection یا DI است.
 
برای مثال، Use Case ما به این وابسته است:
 
IOrderRepository
 
اما خودش نمی‌داند پیاده‌سازی واقعی این Interface چیست.
 
در زمان اجرای برنامه، می‌توانیم مشخص کنیم:
 
IOrderRepository
        ↓
SqlOrderRepository
 
این کار باعث می‌شود وابستگی‌ها انعطاف‌پذیرتر شوند.
 
به همین دلیل در پروژه‌های مدرن .NET، Clean Architecture و Dependency Injection معمولاً در کنار یکدیگر دیده می‌شوند.
 

آیا Clean Architecture فقط برای C# است؟

خیر.
 
Clean Architecture یک مفهوم معماری است، نه یک ویژگی مخصوص یک زبان برنامه‌نویسی.
 
می‌توان از ایده‌های آن در پروژه‌های مختلف استفاده کرد؛ مانند:
 
C#
Java
JavaScript
TypeScript
Python
Kotlin
PHP
Go
 
ممکن است ساختار پوشه‌ها و ابزارها متفاوت باشند، اما ایده اصلی همچنان ثابت است:
 
جدا کردن منطق اصلی برنامه از جزئیات و وابستگی‌های بیرونی.
 

اشتباه رایج در استفاده از Clean Architecture

 
یکی از اشتباهات رایج این است که تصور کنیم هرچه تعداد پوشه‌ها و Interfaceها بیشتر باشد، معماری پروژه تمیزتر است!
 
مثلاً برای یک پروژه کوچک، ممکن است ده‌ها فایل بسازیم:
 
Interfaces
Repositories
Services
Managers
Factories
Handlers
Adapters
DTOs
Mappers
...
 
اما اگر این ساختار واقعاً نیازی به آن نداشته باشد، فقط پروژه را پیچیده‌تر کرده‌ایم.
 
Clean Architecture یعنی مدیریت پیچیدگی، نه ایجاد پیچیدگی.
 
بنابراین باید بر اساس اندازه و نیاز پروژه تصمیم بگیریم که چه میزان از این معماری را استفاده کنیم.
 

چه زمانی یادگیری Clean Architecture مهم می‌شود؟

 
اگر تازه برنامه‌نویسی را شروع کرده‌اید، بهتر است ابتدا مفاهیم پایه را به‌خوبی یاد بگیرید:
 
متغیرها
شرط‌ها
حلقه‌ها
توابع
کلاس‌ها
شی‌گرایی
Interface
Dependency Injection
کار با دیتابیس
API
 
بعد از آن، یادگیری معماری نرم‌افزار و مفاهیمی مانند Clean Architecture بسیار ساده‌تر خواهد شد.
 
چون در نهایت Clean Architecture بیشتر درباره این سؤال است:
 
چطور کدهای مختلف پروژه را طوری کنار هم قرار دهیم که تغییر و نگهداری آن‌ها آسان‌تر باشد؟
 

جمع‌بندی

 
Clean Architecture یا معماری تمیز روشی برای طراحی نرم‌افزار است که تلاش می‌کند منطق اصلی برنامه را از دیتابیس، فریم‌ورک‌ها، APIها و سایر جزئیات فنی جدا کند.
 
در این معماری، بخش‌های اصلی برنامه مانند Domain و Use Caseها نباید به تکنولوژی‌های بیرونی وابستگی شدیدی داشته باشند.
 
مزیت اصلی این کار این است که با بزرگ‌تر شدن پروژه، تغییر، تست و نگهداری نرم‌افزار ساده‌تر می‌شود.
 
البته Clean Architecture برای هر پروژه‌ای ضروری نیست. در پروژه‌های کوچک ممکن است یک ساختار ساده انتخاب بهتری باشد؛ اما در پروژه‌های متوسط و بزرگ، مدیریت وابستگی‌ها اهمیت بسیار زیادی پیدا می‌کند.
 
اگر قصد دارید به‌صورت حرفه‌ای وارد دنیای توسعه نرم‌افزار، ASP.NET Core، Web API یا معماری نرم‌افزار شوید، آشنایی با Clean Architecture می‌تواند یکی از قدم‌های مهم مسیر شما باشد.
 
فرایانه؛ جایی که مفاهیم پیچیده برنامه‌نویسی را به زبان ساده، کاربردی و قابل فهم آموزش می‌دهیم. 💚
Clean Architecture چیست؟ معماری تمیز برنامه‌نویسی