در طول چند سال گذشته ما شاهد طیف وسیعی از ایده ها در رابطه با معماری سیستم ها بوده ایم. برخی از این معماری ها نسبت به سایر معماری ها بیشتر مورد توجه قرار گرفته و اقبال بیشتری داشتند. ایده هایی همچون :
معماری شش ضلعی (Hexagonal Architecture) توسط آلیستر کاکبرن (Alistair Cockburn) و تصویب شده توسط استیو فریمن (Steve Freeman) و نات پریس (Nat Pryce) در کتاب شگفت انگیز خود به نام Growing Object Oriented Software
معماری پیاز (Onion Architecture) توسط جفری پالرمو (Jeffrey Palermo)
معماری ناب (Lean Architecture) از جیمز کوپلین (James Coplien) و تریگوی رنسکاگ (Trygve Reenskaug) و ....
اگرچه همه این معماری ها در جزئیات خود تا حدودی متفاوت هستند، اما در واقع بسیار شبیه به هم هستند. همه آن ها یک هدف یکسان دارند و آن separation of concerns (جدایی نگرانی ها) است. همه این معماری ها اعم از معماری پیاز ، معماری تمیز و دیگر معماری ها با تقسیم نرم افزار به لایه های مختلف به separation of concerns دست می یابند. هر کدام از این معماری ها حداقل یک لایه برای قوانین کسب و کار (business rules) و یک لایه Interface دارند.
هر یک از این معماری ها سیستم هایی تولید می کنند که عبارتند از:
Independent of Frameworks (مستقل از فریمورک)
این معماری به برخی از کتابخانه های نرم افزاری موجود وابسته نیست. در این سیستم ها معماری ها به مثابه tools هستند و در صورت امکان به صورت plugin قابلیت استفاده دارند، به طوری که هیچ وابستگی شدیدی بین سیستم با این tools ها وجود ندارد و به راحتی قابلیت تعویض وجود دارد.
Testable (تست پذیر بودن)
در این معماری ها business rules یا همان قوانین کسب و کار را می توان بدون UI، بانک اطلاعاتی ، وب سرور یا هر عنصر خارجی دیگر آزمایش کرد.
Independent of UI (مستقل از رابط کاربری)
UI بدون تغییر بقیه سیستم می تواند به راحتی تغییر کند. به عنوان مثال در این معماری ها به راحتی می توان یک رابط کاربری web را با یک رابط کاربری console جایگزین کرد، بدون این که business rules تغییر کند.
Independent of Database (مستقل از پایگاه داده)
در همه این معماری ها شما به راحتی می توانید Oracle یا SQL Server را با Mongo ، BigTable ، CouchDB یا هر چیز دیگری جایگزین کنید. business rules شما به پایگاه داده محدود نمی شود.
Independent of any external agency (مستقل از دنیای بیرونی)
دنیای بیرون یعنی هر چیز و اتفاقی خارج از لایه Business Rule که این لایه کاملا مستقل و بدون اطلاع از آن ها طراحی و پیاده سازی می شود.
Robert C. Martin معروف به Uncle Bob تلاش کرد با بررسی و جمع آوری خصوصیات مشترک این معماری ها یک معماری جدید به نام Clean Architecture معروف به معماری تمیز معرفی کند که تجمیع همه خصوصیات این معماری ها در یک ایده واحد است.
تصویر زیر معماری پیشنهادی Robert C. Martin را نشان می دهد :
معماری تمیز (Clean Architecture)
در این معماری هر لایه، به لایه ی داخلی تر وابسته بوده و به آن دسترسی دارد. لایه های داخلی هیچ Reference و اشاره ای به لایه های بالاتر ندارند. هرچند می توانند با ارسال Event آن ها را از وقوع رویدادی باخبر کنند. همانطور که در شکل مشاهده می کنید لایه ی Entity، داخلی ترین لایه بوده و به هیچ لایه ی بیرونی وابستگی ندارد.
The Dependency Rule
در تصویر بالا دایره های متحدالمرکز مناطق مختلف نرم افزار را نشان می دهد. به طور کلی، هرچه میزان پیشرفت شما بیشتر باشد، سطح نرم افزار بالاتر می رود. دایره های بیرونی مکانیسم ها و دایره های درونی سیاست ها هستند. قانون اساسی که باعث می شود این معماری کار کند، The Dependency Rule است. این قانون می گوید وابستگی سورس کد فقط می تواند به سمت داخل باشد. هیچ چیزی در دایره های درونی نمی تواند از موارد موجود در دایره های بیرونی چیزی بفهمد و بی اطلاع از آن ها و محیط آن ها است. از سمت مرکز این معماری به سمت بیرون که حرکت کنیم سطح انتزاع کمتر شده و بیشتر وارد جزییات پیاده سازی خواهیم شد. در واقع حرکت به سمت درون دایره باعث رسیدن به Policy های سیستم شده و حرکت به سمت بیرون این دایره ما را به مکانیزم های سیستم خواهد رساند. در این معماری ما نمی خواهیم چیزی در یک لایه بیرونی جهت تأثیرگذاری بر بخش داخلی که Business rule را شامل می شود، وجود داشته باشد.
Entities
Robert C. Martin در کتاب Clean architecture خود Entity را این طور بیان می کند:
.Entities encapsulate Enterprise wide business rules
Entityها قوانین كسب و كار سیستم های بزرگ را احاطه می كنند. Entityها می توانند یک کلاس یا Object باشند که دارای متد هم هست و هم می توانند فقط شامل ساختار خود موجودیت باشند. منظور از Enterprise در این جمله اشاره به سیستم های بزرگی دارد که از sub system ها و یا application های مختلفی تشکیل شده اند، در نتیجه این موجودیت ها می توانند توسط سیستم های مختلفی مورد استفاده قرار بگیرند و بنابراین مهم نیست که چه تعداد سیستم مختلف ممکن است از یک entity استفاده کنند. Entity ها در واقع همان Domain Entity ها در Domain driven Design هستند.
اگر سیستم Enterprise ای ندارید و فقط یک Application تنها را می نویسید، Entity ها Business object های این اپلیکیشن هستند. آن ها قوانین high-level و General را در بر می گیرند. Entity ها هنگام تغییر چیزی در بیرون، کمترین احتمال تغییر را دارند. به عنوان مثال شما انتظار ندارید که این objectها تحت تأثیر تغییر page navigation یا security قرار بگیرند. هیچ تغییر عملیاتی در هر برنامه خاص نباید روی لایه Entity تأثیر بگذارد.
Use Case
این لایه شامل business rule های مختص هر application می باشد. این business rule ها در واقع همان use case و قوانین تعاملات کاربر نهایی با سیستم می باشد. این use case ها همانند یک هماهنگ کننده (Orchestrate) جریان داده به entity ها یا از entity ها عمل می کنند. این لایه نباید هیچ تاثیری در وضعیت مربوط به entity ها داشته باشد. کار این لایه صرفا هماهنگ کردن جریان داده به Entity ها یا از Entity ها بر اساس Business Rule و Use Case ها می باشد. موارد خارجی مانند UI یا Database نیز نباید تغییری بر لایه Use Case داشته باشد. این لایه از چنین نگرانی هایی جدا شده است. با این حال ما انتظار داریم تغییرات در عملکرد برنامه روی Use case ها و بنابراین نرم افزار موجود در این لایه تأثیر بگذارد. اگر جزئیات یک Use Case تغییر کند، مطمئناً برخی از کدهای این لایه تحت تأثیر قرار می گیرند.
Interface Adapter
برنامه موجود در این لایه مجوعه ای از Adapter ها است که وظیفه تبدیل Data قابل استفاده در لایه های use case و entity را به فرمت مناسب external tools ها مانند Database یا Web و برعکس برعهده دارد . برای مثال، این لایه کاملاً شامل معماری MVC یک رابط کاربری گرافیکی است. همه ارائه کنندگان ، Viewها و Controllerها در اینجا قرار دارند. این Model ها به احتمال زیاد ساختار داده هایی هستند که از Controllerها به Use Case ها منتقل می شوند و سپس از Use Case ها به Presenter ها و View ها باز می گردند. داده هایی که در این لایه رد و بدل می شود غالبا ساختار داده های ساده، بدون Method و Business هستند. هیچ کدی از داخل این لایه نباید به هیچ وجه از پایگاه داده چیزی بداند. واضح است که تغییرات در عملیات هر application منجر به تغییر use case های مربوط به آن عملیات شده و در نتیجه منجر به ایجاد تغییراتی در این لایه خواهد شد.
Frameworks and Drivers
بیرونی ترین لایه به طور کلی از framework ها و ابزارهایی مانند بانک اطلاعاتی، Web Framework و غیره تشکیل شده است. جزییات اصلی کار ما اینجا هست و اینجا پیاده سازی خواهد شد. پیاده سازی UI جزئیات است، Database جزئیات است.
در معماری تمیز (Clean Architecture) تعداد چهار لایه بررسی شده در بالا یک الزام قطعی نیست. این فقط یک ایده است و شما می توانید بسته به نیاز و نوع سیستم تعداد لایه های موجود در معماری تمیز را افزایش دهید. چیزی که مهم است و می بایست رعایت شود Dependency rule و حفظ رعایت آن می باشد. با حرکت به سمت لایه های درونی این معماری سطح انتزاع افزایش پیدا می کند و لایه های بیرونی شامل جزییات پیاده سازی بیشتری خواهند بود.