بررسی سه الگو معماری نرم افزار Hexagonal، Onion و Clean

روش های مختلفی برای طراحی سیستم در مهندسی نرم افزار وجود دارد و هر طراحی محاسن و چالش های خاص خود را دارد. گاهی اوقات رویکردهای مختلف طراحی سعی در دستیابی به اهداف مشابه دارند. وقتی به طراحی معماری نرم افزار فکر می کنیم، به خصوص در دنیای شی گرا، سه الگوی که بیشتر در مورد آنها صحبت می شود عبارتند از: معماری Clean، معماری Hexagonal و معماری Onion.وقتی این الگوها را مشاهده می‌کنم، احساس می‌کنم که هر سه الگو سعی در طرفداری از ایده‌های مشابه دارند. همه این الگوها از نوع layered architecture هستند. همه آنها یک سیستم آزمایش پذیرِ loosely coupled را تعریف می کنند که از هر گونه وابستگی مستقیم از نظر پیاده سازی اجتناب می کند، اما این کار را با استفاده از اصطلاحات خاص خود و هر کدام با تفاوت های ظریف خاص انجام می دهند. همه آنها رویکردهایی را برای مدیریت پذیرتر و آزمایش پذیرتر کردن معماری نرم افزار پیشنهاد می کنند، اما این کار را به روش خود انجام می دهند.اگر همه آنها را با هم نگاه کنیم، برخی از نکات مفید معماری را ارائه می دهند که صرف نظر از رویکرد طراحی که انتخاب می کنید قابل اجرا هستند. ما به زودی آنها را بررسی خواهیم کرد، اما ابتدا اجازه دهید نگاهی به هر یک از این الگوها به صورت جداگانه و مقایسه آنها با یکدیگر بیندازیم.معماری Hexagonalمعماری شش ضلعی گاهی اوقات به عنوان معماری پورت ها و آداپتورها نیز شناخته می شود. آلیستر کاکبرن آن را در سال 2005 معرفی کرد و ایده اصلی آن این بود که برنامه ها مستقل از وابستگی مستقیم به رابط کاربری و پایگاه داده باشد. این جداسازی از طریق مفهوم پورت ها و آداپتورها پشتیبانی می شود.بیایید یک مثال بزنیم. به عنوان یک توسعه دهنده، شما باید یک business logic مرتبط با کاربر را طراحی کنید، که در پایگاه داده باقی بماند. هدف این است که هر کدام از business logic و persistence ایزوله باشند تا هر دو بتوانند مسئولیت های اصلی خود را انجام دهند و رشد کنند. برای این هدف انجام اقدامات زیر لازم است:یک منطق مختص پایگاه داده در یک کلاس آداپتور قرار می گیرد، به عنوان مثال، UserDataAdapterکلاس business logic مختص کاربر، مانند Userقراردادی بین User و UserDataAdapter به طوری که آنها بتوانند با یکدیگر تعامل داشته باشند - به عنوان مثال: IUserDataPort. این قرارداد یک پورت است.همانطور که کاکبرن توضیح می دهد، کلمه "hexagon" به این دلیل انتخاب نشده است که عدد شش مهم است، بلکه به افرادی که معماری را طراحی می کنند اجازه می دهد تا فضای کافی برای قرار دادن پورت ها و آداپتورها در صورت لزوم داشته باشند و اطمینان حاصل شود که آنها توسط یک طراحی لایه ای یک بعدی محدود نمی شوند.برای مشاهده تمپلیت معماری Hexagonal اینجا کلیک کنید.معماری Onionجفری پالرمو مفهوم معماری Onion را در سال 2008 معرفی کرد. او می خواست با تأکید بر separation of concerns در سراسر سیستم، یک رویکرد طراحی برای نرم افزارهای تجاری پیچیده ایجاد کند. این الگو گام‌های مهمی فراتر از معماری Hexagonal برداشت زیرا ایده تعریف لایه Core Business در یک برنامه کاربردی و لایه‌های مختلف اطراف آن را گسترش داد، به طوری که لایه هسته مستقل از لایه‌های بیرونی و وابستگی‌های آن‌ها است.لایه مرکزی - domain model - شامل تمام قوانین کسب و کار است. در سطح بعدی domain services ها قرار دارند که مانند قراردادهای repository و سایر وابستگی ها هستند. خارجی ترین لایه شامل رابط کاربری و اتصال به زیرساخت خارجی است.به طور خلاصه، تفاوت اصلی بین معماری Onion و معماری Hexagonal این است که معماری Onion لایه‌های مختلفی را به همراه لایه کسب و کار اصلی (core business) در برنامه معرفی می‌کند و اتصالات را به وابستگی‌های خارجی مانند پایگاه‌های داده و UI به دایره بیرونی منتقل می‌کند. این بدان معناست که در صورت نیاز می توان آنها را به راحتی تعویض کرد.برای مشاهده تمپلیت معماری Onion اینجا کلیک کنید.معماری Cleanرابرت مارتین Clean Architecture را در سال 2012 معرفی کرد. مفاهیم اصلی مشابه معماری Onion است، اما اصطلاحات آن کمی متفاوت است. در اینجا، domain model به عنوان یک "موجودیت" شناخته می شود. موجودیت شامل قوانین و منطق مختص کسب و کار است، در حالی که منطق مختص عملیات برنامه کاربردی در use case قرار می گیرد. این use case، عملیات را در بالای موجودیت ها می چیند تا آنها را به اجرای قوانین کسب و کار خود برای دستیابی به اهداف use case هدایت کند.در نگاه اول، معماری Clean درک بهتری از مرزها و تفکیک واضح تری از concernها را در مقایسه با معماری Onion ارائه می دهد. آنها بسیار نزدیک به هم مرتبط هستند و از ایده های مشابه، اما با لایه های مختلف طرفداری می کنند. معماری Clean به طور مشخص دلیل وجود هر لایه و وظایف مربوط به آنها را مشخص می کند. به همین دلیل است که به Screaming architecture نیز معروف است - همه چیز را واضح می کند.برای مشاهده تمپلیت معماری Clean اینجا کلیک کنید.الگوهای معماری به ما چه می آموزند؟همانطور که دیدیم، هر سه سبک معماری اصول loose coupling را به اشتراک می گذارند و سعی می کنند با لایه بندی مناسب برنامه، قطعات متحرک را به حداقل برسانند.بنابراین، نکات کلیدی که این سه الگو به ما ارائه می دهند چیست؟ چه اصول اساسی معماری را باید در نظر داشته باشیم؟مرکزیت قوانین کسب و کارقرار دادن قوانین کسب و کار در یک مکان متمرکز چیزی است که هم توسط معماری Clean و هم معماری Onion پیشنهاد شده است. اگرچه آنها از نام‌های متفاوتی برای مفاهیم بسیار مشابه استفاده می‌کنند، اما هر دو ما را تشویق می‌کنند که در مورد منطق کسب و کار به یک روش فکر کنیم.قوانین برنامه کاربردی (Application Rules)باز هم، هر دو معماری Clean و Onion به جهت های مشابهی اشاره می کنند. آنها پیشنهاد می‌کنند که باید لایه‌ای وجود داشته باشد که در آن منطق خاص برنامه کاربردی را در کنار قوانین کسب و کار مدیریت کنید.این لایه شامل ترتیب عملیات و منطق مربوط به برنامه کاربردی خواهد بود.قانون وابستگیهر سه الگو بر اساس این اصل هماهنگ هستند که تاکید می کند که وابستگی های source code فقط باید به سمت داخل باشد. لایه بیرونی فقط می تواند به لایه داخلی اشاره داشته باشد و نه برعکس.جداسازی بین لایه های مختلفهر سه الگو قویاً از این امر حمایت می کنند که بخش های مختلف برنامه باید بتوانند به صورت ایزوله و جداگانه با یکدیگر رشد کنند و باید انتزاع مناسبی بین هر لایه از برنامه وجود داشته باشد.مهمتر از همه، قوانین اصلی کسب و کار باید مستقل از موارد زیر باشد:چگونه آن را ذخیره می کنید:انتخاب پایگاه داده شما نباید بر دامنه اصلی تأثیر بگذارد.اگر نوع پایگاه داده را تغییر دهید، به عنوان مثال: از SQL به NoSQL، نباید هیچ تغییری در منطق کسب و کار شما ایجاد شود.تعامل بین دامنه و persistence از یک استاندارد تعریف شده پیروی می کند و مستقل از جزئیات persistence خواهد بود.چگونه آن را نمایش می کنید:منطق UI و use case ها هرگز نباید شما را به تغییر دامنه اصلی ترغیب کند.چه آن را از طریق JSON، XML یا GraphQL نمایش دهید، core نباید تحت تأثیر قرار گیرد.از کدام framework استفاده می کنید:در حالت ایده آل، دامنه اصلی باید مستقل از framework مورد استفاده باشد. این ممکن است خیلی ساده نباشد، اما می توان از طریق انتزاعات دقیق به آن دست یافت.به عنوان مثال، اگر از Springboot به Micronaut در جاوا، Zin به Martini در Golang، از WebAPI به Nancy در NETCore تغییر دهید، نباید از نظر نحوه تعریف دامنه اصلی تغییری ایجاد شود.وابستگی های خارجی شما چیست:حوزه اصلی نباید تحت تأثیر زیرساخت ها و وابستگی های مرتبط قرار گیرد. به عنوان مثال، اگر از AWS Kinesis استفاده می کنید و باید آن را با Kafka streams جایگزین کنید، دامنه اصلی به هیچ وجه نباید تحت تأثیر قرار گیرد.ایمیل، پیامک و رویدادها چند نمونه از این وابستگی ها هستند.نتیجهالگوهای معماری هسته اصلی نحوه طراحی برنامه های کاربردی ما هستند. اگرچه ممکن است الگوهای مختلفی را انتخاب کنیم، اما با شناسایی و شناخت شباهت‌های آنها، می‌توانیم از برخی اصول اساسی پیروی کنیم که پایه محکمی برای طراحی یک برنامه کاربردی کسب و کار فراهم می‌کند. درک این قوانین به من کمک کرده است تا سیستم های نرم افزاری قابل توسعه، قابل آزمایش و جامع ایجاد کنم.برگرفته ازhttps://www.thoughtworks.com/insights/blog/architecture/demystify-software-architecture-patternshttps://www.c-sharpcorner.com/article/hexagonal-architecture-in-net-c-sharp-api-development-a-comprehensive-guide/https://github.com/jasontaylordev/CleanArchitecture/tree/main/src/Domainhttps://github.com/ardalis/CleanArchitecture/tree/main/srchttps://medium.com/%40omid-ahmadpour/clean-architecture-template-with-net-and-its-importance-e5b3b97a6e48