۰ دیدگاه نظر محسن موحد
معماری Hexagonal چیست؟ (پیاده‌سازی یک مثال با معماری Hexagonal)
سرفصل‌های مقاله
  • معماری Hexagonal چیست؟
  • چرا به معماری Hexagonal نیاز داریم؟
  • مزایا و معایب معماری Hexagonal
  • بخش‌های مختلف معماری Hexagonal
  • پیاده‌سازی یک مثال با معماری Hexagonal در پایتون
  • مقایسه معماری Hexagonal با سایر معماری‌ها
  • سوالات متداول
  • جمع‌بندی

اوایل که نرم‌افزارها تازه داشتن شکل می‌گرفتن، معمولاً به‌صورت یه سیستم یکپارچه و درهم‌تنیده طراحی می‌شدن. می‌تونیم این رو مثل یه ساختمون در نظر بگیریم که توش همه چیز به هم وصله، از لوله‌کشی‌ها گرفته تا سیم‌کشی برق و سازه اصلی. حالا فکر کن اگه بخوایم یه قسمت کوچیک مثل دستشویی رو تعمیر کنیم، باید بخش‌های دیگه ساختمون رو هم دستکاری کنیم چون همه چیز به هم وابسته‌ست. این دقیقاً همون مشکلیه که برنامه‌نویس‌ها باهاش سروکار داشتن: توی یه سیستم نرم‌افزاری، لایه‌های مختلف - از رابط کاربری گرفته تا پایگاه داده و منطق کسب‌وکار - طوری به هم چسبیده بودن که هر تغییر کوچیکی می‌تونست یه زنجیره‌ای از تغییرات ناخواسته رو تو کل سیستم ایجاد کنه.

با پیچیده‌تر شدن نیازهای نرم‌افزاری و بزرگ‌تر شدن پروژه‌ها، این مدل یکپارچه به یه مشکل اساسی تبدیل شد. تصور کن فقط برای اینکه رنگ یه دکمه توی رابط کاربری عوض بشه، مجبور باشی توی لایه‌های دیگه برنامه هم تغییرات اعمال کنی، یا برای تست یه قابلیت ساده، کل سیستم رو راه‌اندازی کنی. این سختی‌ها باعث شد معماری Hexagonal یا همون Ports and Adapters به وجود بیاد، که یه روش جدید و انقلابی برای طراحی نرم‌افزار بود. این معماری با الهام از روش‌های مهندسی مدرن، یه راه‌حل هوشمندانه ارائه می‌داد که بخش‌های مختلف نرم‌افزار رو از هم جدا می‌کرد و باعث می‌شد بتونیم راحت‌تر تغییرات رو مدیریت کنیم.

این معماری مثل ساختمون‌های مدرن و پیشرفته‌ایه که سیستم‌های مختلفش مستقل و ماژولار طراحی شدن؛ یعنی می‌تونیم هر بخش رو بدون تأثیر روی بقیه قسمت‌ها تغییر بدیم یا به‌روزرسانی کنیم. این روش به توسعه‌دهنده‌ها اجازه می‌ده که خیلی آسون‌تر برنامه رو توسعه بدن، بخش‌های جدید اضافه کنن و باگ‌ها رو برطرف کنن، بدون اینکه لازم باشه نگران تأثیر منفی این تغییرات روی کل سیستم باشن.

معماری Hexagonal چیست؟

معماری Hexagonal، که بهش معماری Ports and Adapters هم می‌گن، یه مدل طراحی نرم‌افزاریه که توسط Alistair Cockburn تو سال ۲۰۰۵ معرفی شد. این معماری برای ساختن سیستم‌هایی طراحی شده که هم انعطاف‌پذیرن، هم راحت تست می‌شن و هم وابستگی خاصی به زیرساخت‌ها ندارن. در این مدل، منطق اصلی برنامه یا همون Domain Logic درست در مرکز قرار می‌گیره و از طریق پورت‌ها (که همون اینترفیس‌ها هستن) با دنیای بیرون ارتباط برقرار می‌کنه. آداپتورها هم وظیفه دارن که پروتکل‌های بیرونی رو طوری تبدیل کنن که برای منطق کسب‌وکار قابل فهم باشه.

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

دروازه اول مخصوص پذیرش مهمان‌هاست (مثل رابط کاربری وب).
دروازه دوم برای ورود کالاها و تدارکاته (شبیه ارتباط با پایگاه داده).
دروازه سوم مخصوص پیک‌های پیام‌رسانه (مشابه APIهای خارجی).
دروازه چهارم مخصوص نگهبان‌ها و نیروهای امنیته (مانند سیستم‌های امنیتی).
دروازه پنجم برای ورود تجار و بازرگانانه (مثل سیستم‌های پرداخت).
دروازه ششم مخصوص هنرمندان و صنعتگرانه (مشابه سرویس‌های گزارش‌گیری).
حالا هر کدوم از این دروازه‌ها، مثل همون پورت‌ها، یه سری قوانین و پروتکل‌های خاص خودشون رو دارن. کنار هر دروازه هم یه نگهبان (همون آداپتورها) وایساده که می‌دونه چطور درخواست‌های ورودی رو به زبون تالار مرکزی ترجمه کنه تا اون بتونه پیام‌ها رو راحت بفهمه. این ساختار به شکلی هوشمندانه طراحی شده که:

تالار مرکزی یا همون منطق کسب‌وکار بدون اینکه درگیر جزئیات دنیای بیرون بشه، کار خودش رو انجام بده.
هر دروازه رو بشه بدون اینکه بقیه بخش‌ها تحت تأثیر قرار بگیرن، تعمیر یا حتی عوض کرد.
امنیت و کنترل دسترسی‌ها به صورت منظم و قابل مدیریت اعمال بشه.
اگه نیاز به یه دروازه جدید باشه، ساختار اصلی قلعه دست‌نخورده بمونه و فقط دروازه جدید اضافه بشه.
این مثال به خوبی نشون می‌ده که معماری Hexagonal چطور با جداسازی هوشمندانه اجزای مختلف سیستم، به ساختن سیستمی انعطاف‌پذیر، راحت‌تر برای نگهداری و قابل مقیاس کمک می‌کنه. با این مدل، می‌تونیم خیلی آسون‌تر سیستم رو توسعه بدیم، بخش‌های جدیدی بهش اضافه کنیم و مطمئن باشیم که همه چیز به‌خوبی و بدون اختلال در کنار هم کار می‌کنن.

چرا به معماری Hexagonal نیاز داریم؟

قبل از اینکه معماری Hexagonal معرفی بشه، توسعه نرم‌افزار با یه سری چالش‌های بزرگ ساختاری روبرو بود. بیاید به بعضی از مشکلات اصلی تو معماری‌های سنتی نگاهی بندازیم و ببینیم چی بود که باعث شد این معماری جدید به‌وجود بیاد.

1. وابستگی‌های تنگاتنگ بین اجزا

توی سیستم‌های قدیمی، لایه‌های مختلف نرم‌افزار مثل رابط کاربری، منطق کسب‌وکار و پایگاه داده، به همدیگه کاملاً وابسته بودن. این یعنی اگه توی یکی از این لایه‌ها تغییری ایجاد می‌شد، ممکن بود مجبور بشی کل کد رو دست‌کاری کنی. مثلاً فرض کن بخوای پایگاه داده رو عوض کنی، این کار ممکن بود باعث بشه بخش بزرگی از کد رو از نو بنویسی تا با سیستم جدید سازگار بشه. همه این‌ها به خاطر وابستگی شدیدی بود که بین بخش‌های مختلف وجود داشت.

2. چالش‌های تست و توسعه

از طرفی، تست کردن این سیستم‌ها هم خیلی سخت بود. به خاطر همین وابستگی‌های پیچیده، تست واحد (Unit Testing) به یه چالش بزرگ تبدیل می‌شد. برای اینکه یه ماژول کوچیک رو تست کنی، اغلب مجبور بودی کل سیستم رو راه بندازی و این باعث می‌شد تست‌ها پیچیده و زمان‌بر بشن. همچنین، اگه چند تا تیم مختلف بخوان همزمان روی بخش‌های متفاوتی از نرم‌افزار کار کنن، هماهنگی بینشون خیلی سخت می‌شد.

3. انعطاف‌پذیری محدود

اضافه کردن قابلیت‌های جدید یا تغییرات بزرگ توی معماری این سیستم‌ها هم همیشه کار پیچیده‌ای بود. چون همه چیز به هم وصل بود، هر تغییری می‌تونست کلی از قسمت‌های دیگه رو هم تحت تأثیر بذاره. همین موضوع مقیاس‌پذیری و نگهداری سیستم رو سخت‌تر می‌کرد و اگه نیازهای کسب‌وکار یا تکنولوژی‌ها عوض می‌شد، تغییر سیستم هم خیلی زمان‌بر و هزینه‌بر بود.

راه‌حل معماری Hexagonal

اینجاست که معماری Hexagonal وارد عمل می‌شه و یه راه‌حل عالی برای این مشکلات ارائه می‌ده. این معماری با معرفی مفهوم پورت‌ها و آداپتورها، اجزای مختلف سیستم رو از هم جدا می‌کنه. تو این مدل، برای هر بخش یه رابط مشخص (پورت) تعریف می‌شه که بخش‌های دیگه از طریق اون با هم ارتباط برقرار می‌کنن. اینجوری می‌تونیم هر قسمت رو بدون وابستگی به بقیه توسعه بدیم، راحت‌تر تست کنیم و اگه نیاز شد، تغییرات مورد نظر رو توی هر بخش اعمال کنیم.

همون‌طور که Robert C. Martin می‌گه: "معماری خوب اون معماری‌ایه که تصمیم‌های مهم رو به تأخیر میندازه." و معماری Hexagonal دقیقاً همین کار رو می‌کنه. با جدا کردن دغدغه‌ها و تعریف رابط‌های مستقل، این معماری به ما اجازه می‌ده که در مورد هر بخش تصمیم‌های جداگانه بگیریم، بدون اینکه کل سیستم رو تحت تأثیر قرار بدیم.

مزایا و معایب معماری Hexagonal

معماری Hexagonal مثل هر چیزی، خوبی‌ها و بدی‌های خودش رو داره. از خوبی‌هاش می‌شه به قابلیت توسعه و تست راحت اشاره کرد، اما خب، برای پروژه‌های کوچیک ممکنه زیادی پیچیده باشه و زمان بیشتری برای پیاده‌سازی بخواد. اینجا می‌خوایم یه نگاه کلی به مزایا و معایبش بندازیم.

مزایای معماری Hexagonal

  • جداسازی منطق کسب‌وکار از بخش‌های خارجی: این معماری کمک می‌کنه تا منطق اصلی برنامه از وابستگی به تکنولوژی‌ها و ابزارهای بیرونی مثل دیتابیس‌ها، APIها و سیستم‌های دیگه جدا بشه. این یعنی توسعه‌دهنده‌ها می‌تونن بدون دست زدن به بخش اصلی برنامه، تکنولوژی‌های مختلف رو جایگزین کنن.
  • افزایش قابلیت تست: به خاطر جداسازی کاملی که توی این معماری داریم، می‌تونیم منطق کسب‌وکار رو بدون نیاز به دیتابیس یا سرویس‌های خارجی تست کنیم. این یعنی تست‌های واحد برنامه راحت‌تر و سریع‌تر انجام می‌شن و می‌تونیم مطمئن باشیم که همه چیز مستقل و دقیق کار می‌کنه.
  • انعطاف‌پذیری بالا: به کمک پورت‌ها و آداپتورها، می‌شه بخش‌های مختلف سیستم رو بدون اینکه روی بقیه قسمت‌ها تاثیر بذاره تغییر داد یا توسعه داد. این ویژگی کار رو توی نگهداری و ارتقاء سیستم خیلی آسون می‌کنه.
  • قابلیت نگهداری و توسعه: به‌خاطر ساختار ماژولار و جداسازی دقیقی که در این معماری داریم، سیستم به‌راحتی قابل نگهداری و گسترشه. هر بخش رو می‌تونیم جداگانه آپدیت کنیم یا تغییر بدیم، بدون اینکه به کل برنامه دست بزنیم.
  • همخوانی با اصول SOLID: معماری Hexagonal با استفاده از اصول طراحی شی‌گرا مثل جداسازی رابط‌ها و وابستگی معکوس، کاملاً با اصول SOLID همخوانی داره. این موضوع باعث می‌شه کدها تمیزتر و انعطاف‌پذیرتر باشن.

معایب معماری Hexagonal

  • پیچیدگی برای پروژه‌های کوچیک: توی پروژه‌های کوچیک، ممکنه معماری Hexagonal یه کم پیچیده به نظر بیاد. این پیچیدگی می‌تونه سرعت توسعه رو کم کنه و حتی ممکنه نیاز به طراحی بیش از حد داشته باشیم.
  • نیاز به زمان بیشتر برای پیاده‌سازی: برای طراحی این معماری، باید روی پورت‌ها و آداپتورها وقت گذاشت، که نسبت به معماری‌های ساده‌تر، زمان بیشتری می‌طلبه. این موضوع به‌ویژه توی پروژه‌های ساده می‌تونه زمان توسعه رو بیشتر کنه.
  • نیاز به دانش عمیق‌تر: درک و پیاده‌سازی معماری Hexagonal نیازمند دانش عمیق‌تری از معماری نرم‌افزار و الگوهای طراحی هست. توسعه‌دهنده‌های تازه‌کار ممکنه توی پیاده‌سازی درست این معماری با چالش روبه‌رو بشن.
  • سربار اضافی توی پروژه‌های ساده: اگه پروژه‌ای نیاز به تعاملات پیچیده نداشته باشه، استفاده از پورت‌ها و آداپتورها ممکنه پیچیدگی غیرضروری و کد اضافی ایجاد کنه.
  • وابستگی به برنامه‌نویسی شی‌گرا: این معماری خیلی به اصول برنامه‌نویسی شی‌گرا وابسته هست. اگه از زبانی استفاده می‌کنی که شی‌گرایی توش خیلی کاربرد نداره، پیاده‌سازی این معماری می‌تونه چالش‌برانگیز باشه.

بخش‌های مختلف معماری Hexagonal

معماری Hexagonal یه جور ساختار برنامه‌نویسیه که توش سیستم رو به چند بخش مستقل تقسیم می‌کنیم تا هر بخش کار خودش رو انجام بده، بدون اینکه بقیه قسمت‌ها بهش وابسته باشن. این معماری یه سری بخش اصلی داره که اگه درست باهاشون آشنا بشی، دیگه تغییرات و مدیریت نرم‌افزار برات خیلی راحت‌تر میشه. بیا این بخش‌ها رو با هم مرور کنیم:

۱. هسته یا منطق برنامه (Core Logic)

این بخش قلب سیستم توئه. جایی که کل منطق کسب‌وکار یا همون قوانین و اصول اصلی نرم‌افزار قرار می‌گیره. مثلاً اگه داری یه اپلیکیشن برای ثبت سفارش می‌نویسی، اینجا مشخص می‌کنی که چطور سفارش‌ها ثبت بشن، چه قوانینی برای قیمت‌ها هست و... در واقع هسته هیچ وابستگی به دیتابیس، رابط کاربری یا هر چیز دیگه نداره. فقط کار خودش رو انجام میده.

۲. پورت‌ها (Ports)

پورت‌ها همون دروازه‌هایی هستن که سیستم از طریقشون با دنیای بیرون ارتباط برقرار می‌کنه. مثلاً درخواست‌هایی که از رابط کاربری میاد، یا دیتایی که باید بره تو دیتابیس، از طریق این پورت‌ها عبور می‌کنه. یه جورایی میشه گفت اینا واسطه‌های بین هسته اصلی برنامه و بقیه قسمت‌ها هستن.

۳. آداپتورها (Adapters)

آداپتورها مثل مبدل‌ها هستن. وقتی یه پورت می‌گه "بیا این اطلاعات رو تو دیتابیس ذخیره کن"، این آداپتور وظیفه داره که دستور پورت رو بگیره و اونو به زبان دیتابیس یا سرویس خارجی ترجمه کنه. آداپتورها مسئول همه این ارتباطاتن. مثلاً اگه بخوای از دیتابیس MySQL به MongoDB تغییر بدی، فقط آداپتور دیتابیس رو عوض می‌کنی، بدون اینکه به منطق اصلی دست بزنی.

۴. رابط‌ها (Interfaces)

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

به طور خلاصه، معماری Hexagonal کمک می‌کنه که نرم‌افزار خیلی تمیز و قابل تغییر باشه. هر بخش کار خودش رو می‌کنه و هیچ وابستگی عجیبی به بقیه نداره. حالا هر وقت خواستی یه تغییر یا به‌روزرسانی بدی، فقط باید بخش مربوط به خودش رو عوض کنی.

پیاده‌سازی یک مثال با معماری Hexagonal در پایتون

برای اینکه معماری Hexagonal رو بهتر درک کنیم، بیایید یه مثال عملی توی زبان پایتون داشته باشیم. فرض کنید داریم یه سیستم ساده برای مدیریت سفارش‌های یه فروشگاه آنلاین طراحی می‌کنیم. هدف اینه که با استفاده از معماری Hexagonal، بتونیم هر بخش از سیستم رو مستقل از بقیه توسعه بدیم، به‌راحتی تغییرات ایجاد کنیم و بدون دردسر تست کنیم.

توی این سیستم، سه تا عنصر اصلی داریم:

  • پورت‌ها (Ports): اینا مثل دروازه‌های ارتباطی هستن که سیستم از طریق اونا با دنیای بیرون تعامل می‌کنه. مثلاً، یه پورت برای ثبت سفارش و یه پورت دیگه برای ذخیره داده‌ها داریم.
  • آداپتورها (Adapters): این‌ها نقش واسطه‌ها رو دارن و درخواست‌های خارجی رو برای سیستم پردازش می‌کنن. مثلاً، یه آداپتور داریم که سفارش رو تو دیتابیس ذخیره می‌کنه و یه آداپتور دیگه که اطلاعات رو به کاربر نمایش می‌ده.
  • منطق اصلی (Core Logic): این بخش قلب سیستم ماست و وظیفه مدیریت منطق کسب‌وکار رو داره. تو این مثال، منطق اصلی سیستم مربوط به ثبت سفارش جدیده.

حالا بریم سراغ مراحل پیاده‌سازی این سیستم.

1. تعریف مدل سفارش (Order Model)

اولین چیزی که نیاز داریم، یه مدل برای سفارش‌هاست. این مدل، اطلاعات یه سفارش مثل شناسه سفارش، نام مشتری و آیتم‌هایی که سفارش داده شده رو نگه می‌داره.

# order.py
class Order:
    def __init__(self, order_id, customer_name, items):
        self.order_id = order_id
        self.customer_name = customer_name
        self.items = items
    def __repr__(self):
        return f"Order({self.order_id}, {self.customer_name}, {self.items})"

این مدل کمک می‌کنه تا سفارش‌ها به‌صورت ساختارمند نگهداری بشن. مثلاً اگه یه مشتری به اسم "John Doe" یه سفارش شامل "لپ‌تاپ" و "موس" ثبت کنه، این اطلاعات به‌صورت یه شیء Order ذخیره می‌شه و آماده پردازش توسط سایر بخش‌هاست.

2. تعریف پورت‌ها (Ports)

پورت‌ها توی معماری Hexagonal مشخص می‌کنن که سیستم ما چطور باید با دنیای بیرون ارتباط برقرار کنه. پورت‌ها مثل یه سری قرارداد هستن که هر دروازه‌ای (آداپتور) برای ارتباط باید از اون‌ها پیروی کنه. توی این مثال، یه پورت داریم که مسئول ذخیره و بازیابی سفارش‌هاست.

# ports.py
from abc import ABC, abstractmethod
class OrderRepositoryPort(ABC):
    @abstractmethod
    def save_order(self, order):
        pass
    @abstractmethod
    def get_order(self, order_id):
        pass

این پورت یا اینترفیس، وظیفه تعیین روش ذخیره و بازیابی سفارش‌ها رو داره. با تعریف این پورت، سیستم دیگه نگرانی از اینکه اطلاعات کجا ذخیره می‌شن نداره. هر آداپتوری که با این پورت کار می‌کنه، باید این روش‌ها رو پیاده‌سازی کنه.

3. پیاده‌سازی آداپتور دیتابیس (Adapters)

آداپتورها وظیفه دارن که ارتباط بین سیستم و پایگاه داده یا API‌های خارجی رو برقرار کنن. توی این مثال، از یه آداپتور ساده استفاده می‌کنیم که به‌جای پایگاه داده واقعی، اطلاعات رو توی یه دیکشنری نگه می‌داره.

# adapters.py
from ports import OrderRepositoryPort
class InMemoryOrderRepositoryAdapter(OrderRepositoryPort):
    def __init__(self):
        self.orders_db = {}
    def save_order(self, order):
        self.orders_db[order.order_id] = order
        print(f"Order {order.order_id} saved successfully!")
    def get_order(self, order_id):
        return self.orders_db.get(order_id, None)

این آداپتور به ما اجازه می‌ده که سفارش‌ها رو توی یه دیکشنری ساده ذخیره کنیم. در واقع، InMemoryOrderRepositoryAdapter داده‌ها رو توی حافظه نگه می‌داره، ولی توی یه پروژه واقعی، می‌تونیم به‌راحتی یه آداپتور جدید برای کار با دیتابیس‌هایی مثل MySQL یا MongoDB بسازیم.

4. منطق اصلی سیستم (Core Logic)

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

# services.py
from order import Order
from ports import OrderRepositoryPort
class OrderService:
    def __init__(self, order_repository: OrderRepositoryPort):
        self.order_repository = order_repository
    def create_order(self, order_id, customer_name, items):
        order = Order(order_id, customer_name, items)
        self.order_repository.save_order(order)
        return order
    def fetch_order(self, order_id):
        return self.order_repository.get_order(order_id)

اینجا OrderService یه سرویس مرکزی برای مدیریت سفارش‌هاست که می‌تونه سفارش جدید ثبت کنه یا سفارش‌های قبلی رو بازیابی کنه. این سرویس هیچ وابستگی مستقیمی به جزئیات ذخیره‌سازی نداره؛ بلکه از پورت‌ها برای انجام این کار استفاده می‌کنه. همین جداسازی باعث می‌شه که اگه نیاز باشه نوع ذخیره‌سازی رو تغییر بدیم، فقط کافیه یه آداپتور جدید پیاده‌سازی کنیم.

5. استفاده از سیستم

حالا که تمام اجزا پیاده‌سازی شدن، وقتشه یه سناریوی کامل از ثبت و بازیابی سفارش رو تست کنیم. در اینجا از InMemoryOrderRepositoryAdapter استفاده می‌کنیم که سفارش‌ها رو توی حافظه ذخیره می‌کنه.

# main.py
from adapters import InMemoryOrderRepositoryAdapter
from services import OrderService
# ایجاد آداپتور ذخیره‌سازی
order_repository = InMemoryOrderRepositoryAdapter()
# ایجاد سرویس سفارش
order_service = OrderService(order_repository)
# ثبت یک سفارش جدید
order_service.create_order(1, "John Doe", ["Laptop", "Mouse"])
# بازیابی سفارش
retrieved_order = order_service.fetch_order(1)
print(retrieved_order)

بعد از اجرای برنامه، خروجی زیر رو می‌بینیم:

Order 1 saved successfully!
Order(1, John Doe, ['Laptop', 'Mouse'])

در این مثال ساده، دیدیم که معماری Hexagonal چطور به ما کمک کرد که منطق کسب‌وکار رو از اجزای خارجی جدا کنیم. تو این مدل، هسته سیستم (OrderService) نیازی نداره که نگران جزئیات ذخیره‌سازی باشه؛ فقط با پورت‌ها کار می‌کنه. حالا اگه تصمیم بگیریم که اطلاعات به جای ذخیره در حافظه، تو یه دیتابیس واقعی ذخیره بشه، تنها کاری که باید بکنیم اینه که یه آداپتور جدید بسازیم که با دیتابیس کار کنه، بدون اینکه نیازی به تغییر تو هسته سیستم باشه. این جداسازی نه تنها انعطاف‌پذیری بیشتری به سیستم می‌ده، بلکه تست‌پذیری رو هم آسون‌تر می‌کنه، چون هر بخش به‌طور مستقل قابل آزمایش و توسعه‌ست. این ویژگی‌ها از دلایل اصلی محبوبیت معماری Hexagonal بین توسعه‌دهنده‌هاست.

مقایسه معماری Hexagonal با سایر معماری‌ها

معماری Hexagonal یا همون معماری Ports and Adapters به خاطر مزایایی مثل جدا کردن منطق تجاری از جزئیات خارجی، انعطاف‌پذیری و تست‌پذیری بالایی که داره، به یکی از گزینه‌های محبوب برای توسعه نرم‌افزار تبدیل شده. اما اگه بخوایم درک بهتری از کاربردها و قابلیت‌های این معماری داشته باشیم، بهتره اونو با چند معماری دیگه که خیلی توی صنعت شناخته‌شده هستن مقایسه کنیم. معماری‌هایی که با Hexagonal مقایسه می‌کنیم، معماری لایه‌ای (Layered Architecture)، میکروسرویس (Microservices Architecture) و پیازی (Onion Architecture) هستن. بیاید نگاهی به ویژگی‌های هرکدوم از این معماری‌ها بندازیم و ببینیم کدوم یکی در چه موقعیتی بهتر عمل می‌کنه.

۱. معماری لایه‌ای (Layered Architecture)

این مدل یکی از ساده‌ترین و قدیمی‌ترین معماری‌هاست که سیستم رو به چندین لایه مستقل تقسیم می‌کنه و هر لایه مسئول یه بخش خاص از سیستم می‌شه. معمولاً توی این معماری، یه لایه دیتابیس داریم که وظیفه ذخیره و بازیابی داده‌ها رو به عهده داره، یه لایه سرویس که منطق کسب‌وکار رو مدیریت می‌کنه و یه لایه نمایش که همون رابط کاربریه. مزیت این معماری اینه که خیلی سرراست و ساده‌ست و پیاده‌سازی آسونی داره. اما یه مشکل مهمش اینه که لایه‌ها به همدیگه وابستن. یعنی اگه توی یکی از لایه‌ها تغییری ایجاد بشه، ممکنه مجبور بشی چند لایه دیگه رو هم تغییر بدی.

۲. معماری میکروسرویس (Microservices Architecture)

توی معماری میکروسرویس، سیستم از چندین سرویس مستقل تشکیل شده که هر کدوم مسئول یه بخش خاص از سیستم هستن و می‌تونن به‌صورت مستقل توسعه و اجرا بشن. این معماری خیلی محبوبه، مخصوصاً توی پروژه‌های بزرگ که نیاز به مقیاس‌پذیری بالا دارن، چون هر سرویس می‌تونه به‌صورت جداگانه مقیاس‌پذیر بشه و تیم‌ها هم می‌تونن روی سرویس‌های مختلف به‌طور موازی کار کنن. از طرف دیگه، پیاده‌سازی و مدیریت میکروسرویس‌ها می‌تونه پیچیدگی بیشتری نسبت به معماری Hexagonal ایجاد کنه. اگه یه تیم بزرگ داری و پروژت خیلی وسیعه، این معماری می‌تونه انتخاب خوبی باشه، اما نیاز به ابزارهای مدیریتی و هماهنگی زیادی داره.

۳. معماری پیازی (Onion Architecture)

معماری پیازی یه شباهت زیادی به Hexagonal داره و تمرکزش روی جدا کردن منطق تجاری از جزئیات فنیه. توی این معماری، منطق تجاری توی مرکز قرار داره و هر چی به سمت بیرون حرکت کنیم به تعاملات و زیرساخت‌های خارجی می‌رسیم. مثلاً در لایه‌های بیرونی ارتباط با دیتابیس یا سرویس‌های خارجی قرار داره و هر چی به مرکز نزدیک‌تر بشیم، بیشتر با منطق کسب‌وکار اصلی سروکار داریم. این ساختار به درد سیستم‌هایی می‌خوره که می‌خوایم منطق تجاریشون مستقل از اجزای خارجی باشه، و خیلی شبیه Hexagonal عمل می‌کنه، ولی توی اون بعضی از مفاهیم دقیق Hexagonal مثل پورت‌ها و آداپتورها دیده نمی‌شه.

تفاوت‌های کلیدی معماری‌ها

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

از طرف دیگه، معماری لایه‌ای بر اساس ارتباط نزدیک بین لایه‌ها طراحی شده و در نتیجه، اگه توی یکی از لایه‌ها تغییری ایجاد بشه، معمولاً باید بقیه لایه‌ها رو هم در نظر بگیری. این موضوع باعث می‌شه انعطاف‌پذیری سیستم کمتر بشه. میکروسرویس‌ها هم مقیاس‌پذیری خیلی خوبی دارن، اما پیاده‌سازیشون پیچیدگی مدیریتی زیادی داره و نیاز به هماهنگی دقیق بین سرویس‌ها داره.

ویژگی

معماری Hexagonal

معماری لایه‌ای

معماری میکروسرویس

معماری پیازی

انعطاف‌پذیری

بالا

محدود

بسیار بالا

بالا

قابلیت تست‌پذیری

بسیار بالا

متوسط

بالا

بالا

جداسازی منطق تجاری

بسیار بالا

کم

متوسط

بسیار بالا

مقیاس‌پذیری

متوسط

کم

بسیار بالا

متوسط

سادگی پیاده‌سازی

متوسط

بالا

پایین

متوسط

مدیریت پیچیدگی

متوسط

کم

بالا

متوسط

وابستگی بین اجزا

کم

بالا

متوسط

کم

مناسب برای سیستم‌های بزرگ

بله

خیر

بله

بله

با توجه به این مقایسه، می‌بینیم که معماری Hexagonal به خاطر جداسازی قوی منطق تجاری از اجزای خارجی، انعطاف‌پذیری و تست‌پذیری بالایی داره. این ویژگی‌ها باعث می‌شه که Hexagonal برای پروژه‌های پیچیده و بزرگ، که نیاز به تغییرات مداوم دارن، انتخاب خوبی باشه. اما اگه پروژت کوچیک‌تره و نمی‌خوای با پیچیدگی‌های جداسازی اجزا سروکله بزنی، شاید معماری لایه‌ای گزینه مناسبی باشه. از طرف دیگه، اگه پروژه خیلی بزرگی داری و باید اون رو به‌راحتی مقیاس‌پذیر کنی، میکروسرویس‌ها می‌تونن بهتر جواب بدن.

در نهایت، انتخاب بهترین معماری بستگی به نیازهای خاص پروژه و سطح انعطاف‌پذیری و مقیاس‌پذیری مورد نظر داره. Hexagonal یه گزینه عالی برای پروژه‌هاییه که نیاز به تست‌پذیری بالا و جداسازی قوی اجزا دارن، اما اگه پروژه‌ای با ساختار ساده‌تر داری، معماری‌های دیگه مثل لایه‌ای هم می‌تونن گزینه‌های مناسبی باشن.

سوالات متداول

1. معماری Hexagonal چیست؟

معماری Hexagonal که با اسم معماری Ports and Adapters هم شناخته می‌شه، یه روش طراحی برای سیستم‌های نرم‌افزاریه که کمک می‌کنه بخش‌های مختلف برنامه مستقل از همدیگه کار کنن و ارتباطشون فقط از طریق ورودی و خروجی‌های مشخص باشه.

2. چه مشکلاتی باعث پیدایش معماری Hexagonal شد؟

این معماری برای رفع مشکلاتی مثل وابستگی زیاد بین بخش‌های مختلف نرم‌افزار، سختی توی ایجاد تغییرات و مشکل توی تست کردن برنامه‌ها به وجود اومده. Hexagonal کمک می‌کنه که سیستم‌ها منعطف‌تر و راحت‌تر قابل تغییر باشن.

3. پورت‌ها در معماری Hexagonal چه نقشی دارند؟

پورت‌ها همون ورودی‌ها و خروجی‌های اصلی سیستم هستن که سیستم از طریق اونا می‌تونه با دنیای بیرون تعامل کنه. پورت‌ها ارتباط سیستم رو با بخش‌های خارجی مثل دیتابیس، رابط کاربری یا سرویس‌های دیگه برقرار می‌کنن.

4. آداپتورها در معماری Hexagonal چه هستند؟

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

5. آیا معماری Hexagonal پیچیده است؟

شاید اولش یه کم پیچیده به نظر بیاد، ولی برای پروژه‌های بزرگ و پیچیده خیلی مفیده. برای پروژه‌های کوچیک شاید ساختارهای ساده‌تر هم جواب بده.

6. چه مزایایی در استفاده از معماری Hexagonal وجود دارد؟

از مزایای این معماری می‌شه به جدا بودن منطق برنامه از تکنولوژی‌های خاص، راحتی توی تغییر و توسعه سیستم، و قابلیت تست راحت‌تر اشاره کرد.

7. آیا معماری Hexagonal فقط در پروژه‌های بزرگ استفاده می‌شود؟

این معماری برای پروژه‌های بزرگ و پیچیده عالیه، ولی تو پروژه‌های کوچیک هم می‌تونه به کار بره، مخصوصاً اگه قرار باشه تو آینده تغییرات و توسعه بیشتری داشته باشه.

8. چگونه می‌توان معماری Hexagonal را پیاده‌سازی کرد؟

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

9. آیا شرکت‌های بزرگ هم از معماری Hexagonal استفاده می‌کنند؟

بله، شرکت‌هایی مثل توییتر، اوبر و نتفلیکس از این معماری برای مدیریت سیستم‌های پیچیده‌شون استفاده می‌کنن.

10. آیا این معماری باعث کاهش هزینه‌های توسعه می‌شود؟

بله، چون به‌خاطر انعطاف‌پذیری و امکان تست راحت‌تر، این معماری توی بلندمدت می‌تونه هزینه‌های توسعه و نگهداری رو کم کنه.

جمع‌بندی

معماری Hexagonal یا همون Ports and Adapters یه روش قوی برای طراحی سیستم‌های نرم‌افزاریه که هم انعطاف‌پذیرن و هم می‌تونن رشد کنن. این معماری با جدا کردن منطق برنامه از تکنولوژی‌های خاص و تعریف پورت‌ها و آداپتورها، به توسعه‌دهنده‌ها اجازه می‌ده که بدون ایجاد اختلال تو بخش‌های دیگه، تغییرات لازم رو اعمال کنن. از طرفی، تست‌پذیری و گسترش سیستم رو هم خیلی بهتر می‌کنه. این معماری برای پروژه‌های بزرگ یه ساختار پایدار و برای پروژه‌های کوچیک یه راهکار خوب برای آینده‌نگریه.

اگه دنبال روشی هستی که هم توسعه، هم نگهداری و هم تغییر نرم‌افزار رو برات آسون‌تر کنه، معماری Hexagonal یکی از بهترین انتخاب‌هاست. قابلیت جایگزینی و تغییر بخش‌ها بدون دست زدن به کل سیستم، باعث شده این معماری توی شرکت‌های بزرگ و کوچیک حسابی طرفدار پیدا کنه.👌

۰ دیدگاه
ما همه سوالات و دیدگاه‌ها رو می‌خونیم و پاسخ میدیم

دوره الفبای برنامه نویسی با هدف انتخاب زبان برنامه نویسی مناسب برای شما و پاسخگویی به سوالات متداول در شروع یادگیری موقتا رایگان شد:

۲۰۰ هزار تومان رایگان
دریافت دوره الفبای برنامه نویسی