میکروسرویس‌ها | ترجمه Learning Domain-Driven Design

میکروسرویس‌ها

میکروسرویس‌ها

عنوان اصلی: Microservices
کتاب: Learning Domain-Driven Design
نویسنده: Vlad Khononov
زبان اصلی: انگلیسی
NewsID: 2361
بازهٔ PDF: 243–258
ترجمه: ترجمه با کمک هوش مصنوعی
تاریخ ترجمه: ۱۴۰۵/۰۵/۱۹ — 2026-08-10

فصل ۱۴ — میکروسرویس‌ها

در میانهٔ دههٔ ۲۰۱۰، میکروسرویس‌ها (Microservices) صنعت مهندسی نرم‌افزار را فرا گرفتند. هدف این بود که به نیاز سیستم‌های مدرن برای تغییر سریع، مقیاس‌پذیری و سازگاری طبیعی با ماهیت توزیع‌شدهٔ Cloud Computing پاسخ داده شود. بسیاری از شرکت‌ها تصمیم راهبردی گرفتند Codebaseهای Monolithic خود را تجزیه کنند تا از انعطاف معماری Microservice بهره ببرند. متأسفانه بسیاری از این تلاش‌ها پایان خوبی نداشت. به‌جای معماری‌های منعطف، بعضی شرکت‌ها با Big Ball of Mud توزیع‌شده روبه‌رو شدند: طراحی‌هایی بسیار شکننده‌تر، به‌هم‌چسبیده‌تر و گران‌تر از Monolithهایی که قصد داشتند آن‌ها را بشکنند.

از نظر تاریخی، Microservice اغلب با DDD و مخصوصاً Bounded Context مرتبط دانسته شده است. حتی بسیاری دو اصطلاح Bounded Context و Microservice را به‌جای یکدیگر به کار می‌برند. اما آیا واقعاً یک چیزند؟ این فصل رابطهٔ میان روش Domain-Driven Design و الگوی معماری Microservice را بررسی می‌کند. تعامل این Patternها و مهم‌تر از آن، نحوهٔ استفاده از DDD برای طراحی سیستم‌های Microservice مؤثر را خواهید آموخت.

از مبانی شروع کنیم: Service و Microservice دقیقاً چه هستند؟

Service چیست؟

طبق تعریف OASIS، Service سازوکاری است که دسترسی به یک یا چند Capability را ممکن می‌کند و این دسترسی از طریق Interface از پیش تعریف‌شده انجام می‌شود.

۱. Reference Model for Service-Oriented Architecture v1.0، OASIS، بازیابی‌شده در ۱۴ ژوئن ۲۰۲۱.

Interface تعریف‌شده می‌تواند هر سازوکاری برای ورود یا خروج داده از Service باشد. این Interface ممکن است همزمان باشد، مانند Request/Response، یا ناهمزمان، مانند مدلی که Event تولید و مصرف می‌کند. این همان Public Interface سرویس است که در شکل ۱۴-۱ نمایش داده شده و وسیلهٔ ارتباط و Integration با سایر مؤلفه‌های سیستم را فراهم می‌کند.

Randy Shoup رابط سرویس را به «درِ ورودی» تشبیه می‌کند. همهٔ داده‌هایی که وارد یا از Service خارج می‌شوند باید از این در عبور کنند. علاوه بر این، Public Interface خود Service را تعریف می‌کند: Functionalityای که Service در معرض دیگران قرار می‌دهد. اگر Interface خوب بیان شده باشد، به‌تنهایی برای توصیف Functionality پیاده‌شده کافی است. شکل ۱۴-۲ نمونه‌ای از Public Interface را نشان می‌دهد که قابلیت سرویس را صریح بیان می‌کند.

این بحث ما را به تعریف Microservice می‌رساند.

Microservice چیست؟

تعریف Microservice به‌طرز شگفت‌آوری ساده است. چون Service توسط Public Interface خود تعریف می‌شود، Microservice سرویسی است با Micro-Public Interface؛ یعنی یک «درِ ورودی کوچک».

کوچک بودن Public Interface فهم Functionality یک Service و Integration آن با سایر مؤلفه‌های سیستم را آسان‌تر می‌کند. محدود کردن Functionality سرویس همچنین دلایل تغییر آن را کم می‌کند و استقلال آن را برای توسعه، مدیریت و Scale افزایش می‌دهد.

همین موضوع توضیح می‌دهد چرا Microserviceها Database خود را Expose نمی‌کنند. اگر Database در معرض دیگران قرار گیرد و بخشی از «درِ ورودی» Service باشد، Public Interface بسیار بزرگ می‌شود. برای مثال، روی یک Relational Database چند Query متفاوت SQL می‌توان اجرا کرد؟ با توجه به انعطاف SQL، برآورد احتمالاً «بی‌نهایت» است. به همین دلیل Microserviceها Database خود را Encapsulate می‌کنند. داده فقط از طریق Public Interface کوچک‌تر و Integration-Oriented قابل دسترسی است.

Method به‌عنوان Service: Microservice کامل؟

این گزاره که Microservice یعنی Micro-Public Interface بیش از حد ساده به نظر می‌رسد و ممکن است این تصور را ایجاد کند که محدود کردن هر Service به تنها یک Method، Microservice «کامل» خواهد ساخت. ببینیم اگر این تجزیهٔ ساده‌لوحانه را در عمل اجرا کنیم چه اتفاقی می‌افتد.

Service مدیریت Backlog شکل ۱۴-۳ را در نظر بگیرید. Public Interface آن از هشت Public Method تشکیل شده است و می‌خواهیم قانون «یک Method برای هر Service» را اعمال کنیم.

چون این Microserviceها قرار است «خوش‌رفتار» باشند، هرکدام Database خود را Encapsulate می‌کند. هیچ Service اجازه ندارد مستقیماً به Database سرویس دیگر دسترسی داشته باشد؛ فقط Public Interface مجاز است. اما Interface فعلی برای همکاری میان آن‌ها کافی نیست. سرویس‌ها باید با هم کار کنند و تغییرهایی را که هر Service اعمال می‌کند Synchronize کنند. در نتیجه، ناچاریم Interface سرویس‌ها را برای نگرانی‌های Integration گسترش دهیم. وقتی Integrationها و جریان دادهٔ میان سرویس‌های حاصل را رسم کنیم، نتیجه شبیه یک Big Ball of Mud توزیع‌شده است؛ شکل ۱۴-۴ آن را نشان می‌دهد.

با استفاده از استعارهٔ Randy Shoup، با تجزیهٔ سیستم به Serviceهای بسیار ریز توانستیم «درهای ورودی» عمومی را کوچک کنیم، اما برای پیاده‌سازی Functionality کل سیستم مجبور شدیم ورودی‌های عظیم «فقط کارکنان» برای هر Service ایجاد کنیم. این مثال چه چیزی به ما می‌آموزد؟

هدف طراحی

قاعدهٔ سادهٔ «هر Service فقط یک Method» به چند دلیل نامناسب است. نخست، عملاً شدنی نیست: چون Serviceها باید با یکدیگر کار کنند، مجبور می‌شویم Public Interface آن‌ها را با Methodهای مرتبط با Integration گسترش دهیم. دوم، در نبرد پیروز می‌شویم اما جنگ را می‌بازیم: هر Service نسبت به طراحی اولیه ساده‌تر می‌شود، اما کل سیستم چند مرتبه پیچیده‌تر می‌گردد.

هدف Microservice Architecture ساخت سیستم منعطف است. تمرکز تلاش طراحی روی یک Component و نادیده گرفتن تعامل آن با بقیهٔ سیستم، برخلاف خود تعریف «System» است:

  • مجموعه‌ای از چیزها یا Deviceهای متصل که با هم کار می‌کنند؛
  • مجموعه‌ای از تجهیزات رایانه‌ای و Programها که برای هدفی خاص با هم استفاده می‌شوند.

بنابراین سیستم را نمی‌توان از مؤلفه‌های کاملاً مستقل ساخت. حتی در Microservice Architecture درست، Serviceها با وجود Decouple بودن هنوز باید Integrate شوند و با یکدیگر ارتباط داشته باشند. حال باید تعامل پیچیدگی هر Microservice و پیچیدگی کل سیستم را بررسی کنیم.

پیچیدگی سیستم

چهل سال پیش Cloud Computing وجود نداشت، Requirementهای مقیاس جهانی مطرح نبود و لازم نبود سیستم هر ۱۱٫۷ ثانیه Deploy شود. با این حال مهندسان همچنان باید پیچیدگی سیستم‌ها را مهار می‌کردند. ابزارهای آن زمان متفاوت بود، اما Challengeها و مهم‌تر از آن، راه‌حل‌ها هنوز برای طراحی Microservice معتبرند.

Glenford J. Myers در کتاب Composite/Structured Design دربارهٔ ساختاردهی Procedural Code برای کاهش پیچیدگی بحث می‌کند. او تأکید می‌کند که پیچیدگی فقط تلاش برای کمینه کردن پیچیدگی محلی هر بخش Program نیست؛ نوع مهم‌تر، Global Complexity یا پیچیدگی ساختار کل Program/System است، یعنی میزان ارتباط یا وابستگی متقابل میان بخش‌های اصلی.

در زمینهٔ این فصل، Local Complexity پیچیدگی هر Microservice منفرد است و Global Complexity پیچیدگی کل سیستم. پیچیدگی محلی به پیاده‌سازی Service وابسته است؛ پیچیدگی جهانی را تعامل‌ها و وابستگی‌های میان Serviceها تعریف می‌کنند. هنگام طراحی Microservice کدام‌یک مهم‌تر است؟ هر دو Extreme را بررسی کنیم.

کاهش Global Complexity تا کمترین مقدار به‌طور شگفت‌آوری آسان است: همهٔ Interactionهای میان Componentها را حذف کنیم و تمام Functionality را در یک Monolithic Service پیاده‌سازی کنیم. همان‌طور که دیدیم، این Strategy در بعضی سناریوها کار می‌کند، اما در سناریوهای دیگر می‌تواند به Big Ball of Mud تبدیل شود؛ یعنی تقریباً بالاترین سطح ممکن Local Complexity.

از طرف دیگر، اگر فقط Local Complexity را بهینه کنیم و Global Complexity را نادیده بگیریم، نتیجه همان Big Ball of Mud توزیع‌شده خواهد بود. شکل ۱۴-۵ رابطهٔ Granularity سرویس و دو نوع Complexity را نشان می‌دهد.

برای طراحی سیستم Microservice درست باید هم Global Complexity و هم Local Complexity را بهینه کنیم. هدف‌گذاری هرکدام به‌تنهایی فقط به Local Optimum می‌رسد؛ Global Optimum زمانی است که هر دو Complexity متعادل شوند. مفهوم Micro-Public Interface می‌تواند به این تعادل کمک کند.

Microservice به‌عنوان Deep Service

Module در یک Software System—و به‌طور کلی در هر System—با Function و Logic آن تعریف می‌شود. Function یعنی Module قرار است چه کاری انجام دهد: Business Functionality. Logic یعنی Business Logic ماژول: چگونه Functionality خود را پیاده می‌کند.

John Ousterhout در کتاب The Philosophy of Software Design مفهوم Modularity را بررسی و یک قاعدهٔ بصری ساده اما قدرتمند برای ارزیابی طراحی Module پیشنهاد می‌کند: Depth.

او پیشنهاد می‌کند Module را به صورت مستطیل در نظر بگیریم، همان‌طور که شکل ۱۴-۶ نشان می‌دهد. لبهٔ بالایی مستطیل Function ماژول یا Complexity Public Interface آن است. مستطیل عریض‌تر نشان‌دهندهٔ Functionality گسترده‌تر و Public Interface پیچیده‌تر است؛ مستطیل باریک‌تر Function محدودتر و Interface ساده‌تر دارد. مساحت مستطیل Logic ماژول یا حجم پیاده‌سازی Functionality را نمایش می‌دهد.

طبق این مدل، Module مؤثر «عمیق» است: Public Interface ساده، Logic پیچیده را Encapsulate می‌کند. Module ناکارآمد «کم‌عمق» است: Public Interface آن نسبت به پیچیدگی Encapsulate‌شده بزرگ است. مثال افراطی:

int AddTwoNumbers(int a, int b)
{
  return a + b;
}

در این مثال Complexity Public Interface—Signature متد—تقریباً برابر Logic داخلی است. چنین Moduleای Moving Part اضافی وارد سیستم می‌کند و به‌جای Encapsulate کردن Complexity، Accidental Complexity کل سیستم را افزایش می‌دهد.

Microservice به‌عنوان Deep Module

غیر از تفاوت اصطلاحات، مفهوم Deep Module با Microservice از این نظر فرق دارد که Module می‌تواند Boundary منطقی یا فیزیکی باشد، در حالی که Microservice الزاماً Boundary فیزیکی است. غیر از این تفاوت، دو مفهوم و اصول طراحی زیربنایی آن‌ها مشابه‌اند.

Serviceهایی که در شکل ۱۴-۳ هرکدام فقط یک Business Method را پیاده می‌کردند، Shallow Module هستند. چون مجبور شدیم Methodهای Integration را اضافه کنیم، Interface حاصل از چیزی که باید باشد عریض‌تر شد.

از دید System Complexity، Deep Module Global Complexity را کاهش می‌دهد، در حالی که Shallow Module با اضافه کردن Componentی که Local Complexity خود را Encapsulate نمی‌کند، Global Complexity را افزایش می‌دهد.

Shallow Serviceها یکی از دلایل شکست بسیاری از پروژه‌های Microservice هستند. تعریف‌های نادرستی مانند «Microservice باید کمتر از X خط کد داشته باشد» یا «بازنویسی Service باید از تغییر دادن آن آسان‌تر باشد» فقط بر Service منفرد تمرکز دارند و مهم‌ترین جنبهٔ Architecture را از دست می‌دهند: کل System.

آستانه‌ای که تا آن می‌توان System را به Microservice تجزیه کرد توسط Use Caseهای System تعیین می‌شود. وقتی Monolith را به Serviceها می‌شکنیم، Cost of Change کاهش می‌یابد و در نقطهٔ مناسب Microservice حداقل می‌شود. اما اگر تجزیه را از آستانهٔ Microservice فراتر ببریم، Deep Serviceها به‌تدریج Shallow می‌شوند. Interfaceهایشان به دلیل نیاز Integration دوباره بزرگ می‌شود، Cost of Change بالا می‌رود و معماری کل System به Big Ball of Mud توزیع‌شده تبدیل می‌شود. شکل ۱۴-۷ رابطهٔ Granularity و Cost of Change را نشان می‌دهد.

اکنون که تعریف Microservice روشن شد، بررسی کنیم DDD چگونه به یافتن Boundaryهای Deep Service کمک می‌کند.

DDD و مرزهای Microservice

مانند Microservice، بسیاری از Patternهای DDD که در فصل‌های قبل دیدیم دربارهٔ Boundary هستند: Bounded Context مرز Model است، Subdomain یک Business Capability را محدود می‌کند و Aggregate و Value Object Boundaryهای تراکنشی‌اند. باید ببینیم کدام Boundary با مفهوم Microservice سازگار است.

Bounded Contextها

Microservice و Bounded Context اشتراک‌های زیادی دارند، تا جایی که اغلب به‌جای یکدیگر استفاده می‌شوند. اما آیا Boundaryهای Bounded Context واقعاً با Boundaryهای Microservice مؤثر هم‌بسته‌اند؟

هر دو Boundary فیزیکی‌اند. Microservice مانند Bounded Context توسط یک تیم مالکیت می‌شود. همان‌طور که Modelهای متعارض نباید در یک Bounded Context قرار گیرند، قرار دادن Modelهای متعارض در یک Microservice نیز Interface پیچیده ایجاد می‌کند.

از این منظر Microservice واقعاً یک Bounded Context است. اما آیا رابطه در جهت معکوس هم برقرار است؟ آیا هر Bounded Context یک Microservice است؟

در فصل ۳ آموختید Bounded Context از سازگاری Ubiquitous Language و Model محافظت می‌کند. Modelهای متعارض نمی‌توانند در یک Context واحد پیاده شوند. فرض کنید روی سیستم مدیریت تبلیغات کار می‌کنید. در دامنهٔ کسب‌وکار، Entityای مثل Lead در Contextهای Promotions و Sales با مدل‌های متفاوت نمایش داده می‌شود. بنابراین Promotions و Sales دو Bounded Context هستند که هرکدام تنها یک مدل معتبر در Boundary خود تعریف می‌کنند؛ شکل ۱۴-۸ این وضعیت را نشان می‌دهد.

برای سادگی فرض کنیم هیچ Model متعارض دیگری غیر از Lead وجود ندارد. این باعث می‌شود Bounded Contextهای حاصل به‌طور طبیعی عریض باشند و هرکدام چند Subdomain را در خود جا دهند. Subdomainها می‌توانند از یک Bounded Context به دیگری منتقل شوند، مادامی که مدل متعارضی ایجاد نشود؛ شکل ۱۴-۹ چند تجزیهٔ معتبر را نشان می‌دهد.

تجزیه‌های مختلف Requirementهایی مانند اندازه و ساختار Team، وابستگی Lifecycle و موارد دیگر را تغییر می‌دهند. اما آیا همهٔ Bounded Contextهای معتبر این مثال لزوماً Microservice هستند؟ خیر؛ مخصوصاً Contextهای نسبتاً عریض یک تجزیه ممکن است بسیار بزرگ‌تر از چیزی باشند که Microservice مؤثر محسوب می‌شود.

پس رابطهٔ Microservice و Bounded Context متقارن نیست. هر Microservice یک Bounded Context است، اما هر Bounded Context لزوماً Microservice نیست. از سوی دیگر، Bounded Context مرز «بزرگ‌ترین Monolith معتبر» را نشان می‌دهد. چنین Monolithی با Big Ball of Mud یکی نیست؛ گزینه‌ای معتبر است که سازگاری Ubiquitous Language یا Model دامنه را حفظ می‌کند. همان‌طور که فصل ۱۵ نشان خواهد داد، در بعضی موارد Boundaryهای عریض‌تر از Microservice مؤثرترند.

شکل ۱۴-۱۰ رابطهٔ Bounded Context و Microservice را به‌صورت بصری خلاصه می‌کند. ناحیهٔ میان این دو Safe است و گزینه‌های طراحی معتبر را تشکیل می‌دهد. اگر System حتی به Bounded Context درست تجزیه نشده باشد، Big Ball of Mud خواهیم داشت؛ اگر از آستانهٔ Microservice ریزتر شویم، Distributed Big Ball of Mud حاصل می‌شود.

Aggregateها

Bounded Context حد «عریض‌ترین Boundary معتبر» را تعیین می‌کند، اما Aggregate تقریباً جهت معکوس دارد: Boundary Aggregate باریک‌ترین Boundary ممکن را مشخص می‌کند. شکستن یک Aggregate به چند Service فیزیکی یا Bounded Context نه‌تنها نامطلوب است، بلکه همان‌طور که Appendix A نشان می‌دهد می‌تواند پیامدهای بسیار بدی داشته باشد.

مرز Aggregate نیز گاهی به‌عنوان Boundary Microservice پیشنهاد می‌شود. Aggregate واحد غیرقابل‌تقسیم Business Functionality است که Business Ruleها، Invariantها و Logic داخلی را Encapsulate می‌کند. با این حال، Microservice دربارهٔ Service منفرد در خلأ نیست. هر Service باید در Context تعامل با سایر Componentهای System بررسی شود:

  • آیا Aggregate با Aggregateهای دیگر Subdomain ارتباط دارد؟
  • آیا Value Objectها را با Aggregateهای دیگر Share می‌کند؟
  • تغییر Business Logic این Aggregate با چه احتمالی سایر Componentهای Subdomain را تحت تأثیر قرار می‌دهد و برعکس؟

هرچه رابطهٔ Aggregate با Business Entityهای دیگر Subdomain قوی‌تر باشد، به‌عنوان Service منفرد Shallowتر خواهد شد. گاهی Aggregate به‌عنوان Service طراحی Modularity مناسبی ایجاد می‌کند؛ اما در بسیاری موارد Serviceهای این‌قدر ریز Global Complexity کل System را افزایش می‌دهند.

Subdomainها

قاعدهٔ متعادل‌تر برای طراحی Microservice این است که Serviceها را با Boundaryهای Business Subdomain هم‌راستا کنیم. همان‌طور که در فصل ۱ دیدید، Subdomainها با Business Capabilityهای ریزدانه هم‌بسته‌اند: Building Blockهایی که شرکت برای رقابت در Business Domain به آن‌ها نیاز دارد.

از دید Business Domain، Subdomain Capability را توصیف می‌کند—Business چه کاری انجام می‌دهد—بدون توضیح این‌که چگونه پیاده می‌شود. از دید فنی، Subdomain مجموعه‌ای از Use Caseهای منسجم است: از یک Model دامنه استفاده می‌کنند، روی داده‌های یکسان یا نزدیک کار می‌کنند و Functionality آن‌ها رابطهٔ قوی دارد. تغییر Requirement یکی از Use Caseها احتمالاً روی Use Caseهای دیگر اثر می‌گذارد؛ شکل ۱۴-۱۱ این موضوع را نشان می‌دهد.

Granularity Subdomain و تمرکز آن بر Function—«چه» به جای «چگونه»—باعث می‌شود Subdomain به‌طور طبیعی Deep Module باشد. Description Subdomain یا Function آن، جزئیات پیچیده‌تر پیاده‌سازی یا Logic را Encapsulate می‌کند. Cohesion Use Caseهای داخل Subdomain نیز عمق Module حاصل را تضمین می‌کند؛ شکستن آن‌ها در بسیاری موارد Public Interface پیچیده‌تر و Module کم‌عمق‌تر ایجاد می‌کند. به همین دلیل Subdomain Boundary امنی برای طراحی Microservice است.

هم‌راستا کردن Microservice با Subdomain یک Heuristic امن است که برای بیشتر Microserviceها Solution مناسب تولید می‌کند. با این حال مواردی وجود دارند که Boundary دیگر کارآمدتر است: ماندن در Boundary زبانی عریض‌تر Bounded Context یا، به دلیل Nonfunctional Requirementها، استفاده از Aggregate به‌عنوان Microservice. پاسخ فقط به Business Domain وابسته نیست، بلکه Structure سازمان، Business Strategy و Nonfunctional Requirementها نیز مهم‌اند. همان‌طور که در فصل ۱۱ دیدیم، Architecture و Design باید پیوسته با تغییرهای محیط سازگار شوند.

فشرده کردن Public Interface میکروسرویس

DDD علاوه بر پیدا کردن Service Boundary می‌تواند Serviceها را «عمیق‌تر» کند. این بخش نشان می‌دهد چگونه Open-Host Service و Anticorruption Layer می‌توانند Public Interface میکروسرویس را ساده کنند.

Open-Host Service

Open-Host Service مدل دامنهٔ داخلی Bounded Context را از Model مورد استفاده برای Integration با Componentهای دیگر جدا می‌کند؛ شکل ۱۴-۱۲ این الگو را نمایش می‌دهد.

معرفی Model Integration-Oriented، یعنی Published Language، Global Complexity را کاهش می‌دهد. نخست اجازه می‌دهد پیاده‌سازی Service را بدون اثر گذاشتن بر Consumerها تکامل دهیم: Implementation Model جدید می‌تواند به Published Language موجود Translate شود. دوم، Published Language Model محدودتری را Expose می‌کند که مخصوص نیاز Integration طراحی شده است و Complexity پیاده‌سازی نامرتبط با Consumer را Encapsulate می‌کند. برای مثال می‌تواند دادهٔ کمتری و در قالبی مناسب‌تر برای Consumer ارائه کند.

Public Interface ساده‌تر روی همان Implementation، Service را عمیق‌تر می‌کند و به طراحی Microservice مؤثرتر کمک می‌کند.

Anticorruption Layer

Anticorruption Layer یا ACL در جهت معکوس عمل می‌کند: Complexity Integration سرویس با Bounded Contextهای دیگر را کاهش می‌دهد. به‌طور سنتی ACL به Contextی تعلق دارد که از آن محافظت می‌کند، اما همان‌طور که در فصل ۹ گفته شد می‌توان یک گام جلوتر رفت و آن را به‌عنوان Service مستقل پیاده کرد.

ACL Service در شکل ۱۴-۱۳ هم Local Complexity Bounded Context مصرف‌کننده و هم Global Complexity System را کاهش می‌دهد. Business Complexity مصرف‌کننده از Integration Complexity جدا می‌شود و دومی به ACL Service منتقل می‌گردد. چون Consumer با Model مناسب‌تر و Integration-Oriented کار می‌کند، Public Interface آن فشرده‌تر است و Complexity Integration سرویس Producer را بازتاب نمی‌دهد.

جمع‌بندی

از نظر تاریخی سبک معماری Microservice پیوند عمیقی با DDD دارد، تا جایی که اصطلاح Microservice و Bounded Context اغلب به‌جای یکدیگر استفاده می‌شوند. در این فصل رابطهٔ آن‌ها را تحلیل کردیم و دیدیم یک مفهوم نیستند.

همهٔ Microserviceها Bounded Context هستند، اما همهٔ Bounded Contextها لزوماً Microservice نیستند. در ماهیت، Microservice کوچک‌ترین Boundary معتبر یک Service را تعریف می‌کند، در حالی که Bounded Context از سازگاری Model داخل خود محافظت می‌کند و عریض‌ترین Boundary معتبر را نشان می‌دهد. Boundary عریض‌تر از Bounded Context به Big Ball of Mud منجر می‌شود؛ Boundary باریک‌تر از آستانهٔ Microservice به Distributed Big Ball of Mud.

با این حال ارتباط Microservice و DDD نزدیک است. دیدیم چگونه ابزارهای DDD می‌توانند برای طراحی Boundaryهای مؤثر Microservice استفاده شوند.

در فصل ۱۵ بحث Architecture سطح بالا را از زاویه‌ای دیگر ادامه خواهیم داد: Integration ناهمزمان از طریق Event-Driven Architecture. خواهیم دید چگونه انواع مختلف Event Message می‌توانند Boundaryهای Microservice را بیشتر بهینه کنند.

تمرین‌ها

  1. رابطهٔ Bounded Context و Microservice چیست؟
    1. همهٔ Microserviceها Bounded Context هستند.
    2. همهٔ Bounded Contextها Microservice هستند.
    3. این دو اصطلاح نام‌های متفاوت یک مفهوم‌اند.
    4. دو مفهوم کاملاً متفاوت و غیرقابل مقایسه‌اند.
  2. کدام بخش Microservice باید «Micro» باشد؟
    1. تعداد Pizza لازم برای سیر کردن Team پیاده‌ساز Microservice؛ Metric باید تفاوت رژیم غذایی و کالری را هم لحاظ کند.
    2. تعداد Lineهای Code لازم برای Functionality سرویس؛ چون عرض Line در Metric حساب نمی‌شود، بهتر است روی Ultra-Wide Monitor پیاده‌سازی شود.
    3. مهم‌ترین موضوع، تهیهٔ Middleware و Infrastructure «Microservice-Friendly» از Vendorهای دارای گواهی Microservice است.
    4. میزان دانش دامنه و پیچیدگی‌هایی که از Boundary سرویس عبور می‌کنند و در Public Interface آن منعکس می‌شوند.
  3. Boundaryهای امن Component کدام‌اند؟
    1. Boundary عریض‌تر از Bounded Context.
    2. Boundary باریک‌تر از Microservice.
    3. Boundaryهای بین Bounded Context (عریض‌ترین) و Microservice (باریک‌ترین).
    4. همهٔ Boundaryها امن‌اند.
  4. آیا هم‌راستا کردن Microservice با Boundary Aggregate همیشه تصمیم خوبی است؟
    1. بله، Aggregate همیشه Microservice خوبی می‌سازد.
    2. خیر، Aggregate هرگز نباید Microservice مستقل باشد.
    3. ساخت Microservice از یک Aggregate ممکن نیست.
    4. تصمیم به Business Domain بستگی دارد.

شکل‌ها و جدول‌های منبع

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

بازنمایی صفحهٔ 244 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-1. Communication between services | Figure 14-2. A service’s public interface
بازنمایی صفحهٔ 245 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-3. Naïve decomposition
بازنمایی صفحهٔ 246 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-4. Integration complexity
بازنمایی صفحهٔ 248 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-5. Service granularity and system complexities
بازنمایی صفحهٔ 249 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-6. Deep modules
بازنمایی صفحهٔ 250 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-7. Granularity and cost of change
بازنمایی صفحهٔ 251 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-8. Bounded contexts
بازنمایی صفحهٔ 252 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-9. Alternative decompositions to bounded contexts
بازنمایی صفحهٔ 253 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-10. Granularity and modularity
بازنمایی صفحهٔ 254 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-11. Subdomains
بازنمایی صفحهٔ 256 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-12. Integrating services through a published language
بازنمایی صفحهٔ 257 منبع برای حفظ دقیق شکل/جدول اصلی. Figure 14-13. Anticorruption layer as a stand-alone service

امتیاز کاربران به این مقاله

☆☆☆☆☆

0 نفر امتیاز داده اند. میانگین: 0.0 از 5

 

0 نظر

نظر محترم شما در مورد مقاله های وب سایت برنامه نویسی و پایگاه داده

نظرات محترم شما در خدمات رسانی بهتر ما را یاری می نمایند. لطفا اگر مایل بودید یک نظر ما را مهمان فرمائید. آدرس ایمیل و وب سایت شما نمایش داده نخواهد شد.

0 / 500