1. Infrastructure as Code (IaC)
بجای اینکه ما بخواهیم دستی زیرساخت پروژه مون رو به هر دلیلی تغییر دهیم و یا حتی پیاده سازی کنیم در تیم خودمان یا تیم های مختلف (منظور از زیرساخت اجزایی مثل دیتابیس یا سرورها هستش) دلیل تغییر هم میتونه برای انجام تست یا بروزرسانی باشه (مثلا ظرفیت سرور رو افزایش بدیم) از IaC استفاده میکنیم. IaC همونجور که از اسمش معلومه زیرساخت به عنوان کد، ما دستورالعمل ها و ترتیب انجام ستاپ زیرساخت های مدنظر برای اون تغییر رو به صورت یک کد (با فرمت معمولا Json یا xml) مینویسیم و ابزار IaC ای هم که روی اون دستگاهی که می خواهیم اجرا کنیم باید نصب باشه و اون ران میکنه و ستاپ رو انجام میده برامون.
همین باعث میشه مثلا برای تست کردن دیگه نریم تغییرات رو دستی انجام بدیم و فقط اون فایل رو تغییر بدیم کافیه و خیلی سرعت رو بالا میبره و همچنین خطای انسانی رو هم حذف میکنه، مگر اینکه تو اون فایله خطا کنیم :).
2. API Gateway & Service Mesh
میشد گفت API ها نقاط دسترسی ما به سرویس یا میکروسرویس ها هستند و ما با دانستند آنها میتونیم به آن سرویس ها دسترسی پیدا کنیم.
همانطور که از اسمش معلومه API Gateway یه دروازه است که با دسترسی به اون به عنوان کلاینت میتونیم به سرویسهای مختلفی دسترسی پیدا کنیم بدون اینکه بدونیم API اونها چیه و کارش کنترل کردن دسترسی های خارجی است و مثلا احراز هویت هم میتونه انجام بده.
از طرفی Service Mesh یک لایه ی زیرساخت هست که وظیفه ی هندل کردن تعاملات سرویس ها (میکرو سرویس ها) با همدیگه رو داره. دوقسمت تشکیل شده Data Plane و Control Plane، هر سرویس یک دیتا پلین داره که بهش پروکسی هم میگند.
یکدونه کنترل پلین داریم به عنوان هوش مرکزی قوانین رو مشخص میکنه روی کل لایه ی Service Mesh ولی هر کدوم از دیتا پلین ها باید اون قوانین رو خودشون اجرا کنند برای برقراری ارتباط.
دیتا پلین ها مدام نیاز ندارند با کنترل پلین در ارتباط باشند و بعد از گرفتن قوانین ازش خودشون لود بلنسینگ و ارتباطات رو انجام میدهند برای همین درسته که سیستم ممکنه با وجود کنترل پلین حالت کنترلی و متمرکز بگیره اما اصل کاری ها توسط دیتا پلین ها انجام میشه که توزیع شده هستند.
خلاصه API Gateway کار کاربر های بیرونی رو راحت میکنه و امنیت و چک هایی رو انجام میده که برامون مهمه و باعث میشه کاربر ها نیازی نداشته باشند api های هر سرویسی رو بدونند و یا سیستمی هارد کد کرده باشد شون.
و از اون طرف سرویس مش میاد و کل ارتباطات سرویس ها با همدیگه رو میبره توی لایه ی زیرساخت بجای اپلیکیشن و تعامل و بلنس کردن سرویس ها با همدیگه رو انجام میده و قوانین ارتباطشون رو وضع میکنه.
3. CQRS (Command Query Responsibility Segregation)
وقتی ما به مقدار زیادی عملیات های خواندن و نوشتن داریم و لود هاشون به اصطلاح بالاست، میتونیم با جدا کردن کل سیستیم به بخش های مخصوص نوشتن و مخصوص خواندن و هندل کردن هر بخش به صورت متفاوت سرعت و امنیت و مقیاس پذیری رو ایجاد کنیم.
به طور معمول تعداد درخواست های خواندن معمولا خیلی بیشتر از نوشته از طرفی ممکنه عملیات نوشتن پیچیدگی بالایی داشته باشه و اگر مثلا از یک دیتابیس استفاده کنیم اونوقت هرکی بخواد بنویسه دیگه اجازه ی خوندن نداره از اون محفظه دیتابیس که خیلی باعث دردسره!
در این پترن معماری ما 2 تا مدل ایجاد میکنیم، یکی برای خوندن که فقط query میگیره و read-only هستش.
یک مدل برای command ها که عملیات های مخصوص ایجاد، تغییر و حذف داده رو باهاش انجام میدیم.
معمولا هم برای هر کدوم از این مدل ها, ساختار و زیربنای جداگانه ای در نظر گرفته شده که مخصوص خود اون مدل بهینه سازی شدند. مثلا جدا شدن دیتابیس مخصوص خواندن و مخصوص نوشتن.
هماهنگ شدن این مدل ها با همدیگر به صورت آسنکرون (ناهمگام) خواهد بود، بعد از این که ما داده ای رو با command درخواست دادیم، نتیجه اش چه موفقیت آمیز بود و چه نبود به صورت یک event برای مدل خواندن ما ارسال میشه برای ذخیره.
4. Event-Driven Architecture (EDA)
در این روش سرویس ها به جای اینکه برای هم مسیج بفرستند، از ایونت برای برقراری ارتباط با همدیگر استفاده می کنند. توی این معماری ما 3 نقش اصلی داریم Event Producer، Event Consumers و Event Bus/Broker.
یک ایونت یه حالت اتفاق افتاده ای توی سیستم هستش و ایونت ها هم immutable هستند یعنی غیرقابل تغییرکه سازنده ی ایونت بعد از ایجاد یک ایونت میاد اونو روی Event Bus قرار میده.
مسئولیت Event Bus اینه که دیتا را به هرکی برایش اون ایونت مهمه و میخواد دریافت کند و سابسکرایب کرده به اون ارسال کند.
مصرف کننده ها هم بعد از دریافت ایونت حالت خودشونو باهاش بروزرسانی یا فعالیت هایی رو اجرا میکنند، ایونت ها میتونند تعداد مختلفی مصرف کننده داشته باشند سر همین اگر بخواهیم به ترتیب خاصی این فعالیت ها اتفاق بیفتند میشه از روش هایی مثل Orchestration استفاده کرد و یا صرفا ایونت های مختلف پشت سر هم درست کرد یا ترکیبشون کرد.
این روش به ما ساختاری از هم گسسته ارائه میکنه که در اون سرویس ها لازم نیست از هم خبر داشته باشند و صرفا تعاملات شون واکنش به ایونت ها باشه.
5. Serverless Architecture
پایه ی Serverless Architecture کلاد یا فضای ابری برای زیرساخت مون هست. با بردن سرویس و میکرو سرویس هامون به کلاد دغدغه ی گرداندن اون سرور از محیط کار برداشته میشه و تمرکز اصلی تیم میتونه روی قوانین بیزینس و ایجاد فانکشنالیتی جدید باشه. توی این روش که ما آدرس دقیقی از API های سرور هامون نداریم (چون روی کلاد هستند) از پترن های معماری قبلی ای که اشاره کردیم مثل API Gateway برای دسترسی خارجی به سرویس ها و استفاده از Event ها برای کارایی داخلی و ارتباط سرور ها با همدیگه توی کلاد حائز اهمیت و تشویق میشه.
6. API-first Approach
یه استراتژی هستش که طراحی API رو اولویت قرار می دهیم، API ها سورس های ارتباطاتی اجزای داخلی و خارجی با سیستم ما هستند در این روش قبل از زدن یک خط کد میریم سراغ طراحی API و با اولویت قرار دادن اون می توانیم قبل از زدن کدی مطمئن شویم خروجی سرویسمون چه خواهد بود.
مزایای دونست اول این موضوع می توانند به اطمینان از درستی ارتباط با اینترنت و دیگر سرویس هامون در انتهای کار باشد. و همینطور داشتن دیدی از خروجی باعث میشه تیم های دیگر بتوانند همزمان با این سرویس های درحال تولید پیش برند همچنین در داخل یک تیم هم این کار باعث میشه بک اند و فرانت اند مستقل از هم و همزمان کار هاشون رو بکنند.
7. Domain Driven Design
در این روش ما سعی بر مدل کردن مشکل دنیای واقعی (core business logic) توی برنامه ای که میسازیم هستیم. کل سیستم باید معادل ساختار در واقعیت باشه، مثلا اسم های stakeholder ها با اسم های توی برنامه (customer, manager …) و دیگر اسم های دیگه مثل کانسپت ها برابر باشه و طرز کارو رو هم همونجوری مدل میشه که توی دنیای واقعی انجام میشه، اینطوری یه دید آشنا و راحت به همه استک هولدر ها میده و یادگیری کارکرد و تست کردن سیستم هم چون براساس دنیای واقعیه راحت تر میشه.
یک مفهوم Aggregates هم داریم که به مجموعه ای از آبجکت های دومین میگویند که به هم ربط دارند و به عنوان یک واحد همشونو در نظر میگیریم. یکی از اون آبجکت های اجماع شده نقش ریشه را میگره و اون آبجکت تنها نقطه ی دسترسی از بیرون هستش و تمام ارتباطات از ریشه میگذره.
8. Hexagonal architecture
در معماری Hexagonal هدف ما ساختن کامپوننت های خیلی از هم گسسته که وابستگی ندارند به همدیگر هست که توسط پورت ها و آداپتورها به بیزینس لاجیک مون که به صورت یک شش ضلعی نمایش داده میشه وصلشون کنیم.
تا جایی که من فهمیدم پورت و آداپتور ها مانند اینترفیس ها داخل معماری لایه بندی هستند. که ازشون برای dependency injection (تزریق وابستگی) و وصل کردن لایه ها به هم به طوری که وابسته نباشند استفاده میکنیم. در اینجا هم پورت ها نحوه ی وصل شدن به core اصلی (شش ضلعی) هستند و آداپتورها نحوه ی پیاده سازی اون پورت توی کامپوننت هستش و هر کامپوننت میتونه نحوه ی متفاوتی پیاده سازی کنه.
9. Event Sourcing
در این روش به جای نگه داشتن استیت خالی ما تمام ایونت هایی که باعث شده به این استیت برسه رو به صورت یک دنباله و تاریخچه نگه میداریم.
محفظه ی نگهداری مون اسمش event store هستش و خود ایونت ها رو هم توی EDA توضیح دادم که یه حالت اتفاق افتاده ای توی سیستم هستش و غیر قابل تغییره که برای دیباگ کردن خیلی کارو راحت میکنه.
10. Low-code/No-code platforms
پلتفرم هایی که به کاربران اجازه میدهند با کامپونت های از پیش ساخته شده برنامه هایی را بسازند. میشه حالت درگ و دراپ باشه و یا وصل کردن نود های بصری و دارای منطق به همدیگر، توی low code ما میتونیم برای قسمت های پیچیده یا شخصی کردن سازی بیشتر از کد استفاده کنیم و وایت باکس تره (قابل مشاهده ی منطق/کد نود های بصری هستیم) ولی توی no code کاملا وابسته به کامپوننت های ارائه شده ایم.
11. Business Process Management Systems (BPMS)
نرم افزارهایی هستند که برای بهبود و اتوماتیک کردن فرایند های وقت گیر و رایج داخل بیزینس طراحی شدند. کارشان مرتب کردن، خودکار سازی، تمیز کردن فرایند کارها هستش. دارای امکانات نظارتی برای پیشروی فرایند هم دارند.
12. Message Queue (such as Kafka and RabbitMQ)
یک روش ارتباط ناهنگام هستش که به سرویس ها میکروسرویس ها اجازه میده با هم ارتباط داشته باشند بدون اینکه به هم مستقیم متصل باشند. به این صورت که فرستنده پیام مدنظر شو (هر نوع مختلفی از پیام مثل ایونت یا دستور یا …) رو میفرسته به یک بافر مرکزی و اونجا نگه داشته میشوند تا گیرنده پروسس کنه پیام رو.
یکی از مزایای این روش نداشتن وابستگی و جدا بودن هستش چون اصلا خبر ندارند سرویس های دیگه چه کسایی اند و سر و کارشون با یک بافر هست صرفا سر همین خیلی مقیاس پذیریش بالا میره و از طرفی ناهمگام بودن هم باعث میشه صبر نکنند برای جواب برگشت و به کارشان برسند که همین باعث افزایش کارایی میشود.
13. Container orchestration (such as Kubernetes)
محفظه ها زیربنا هایی هستند که برنامه ی ما روشون اجرا میشه و تمام چیزهایی که برنامه برای اجرا شدن نیاز داره مثلا کتابخانه ها رو شامل میشوند. برای مدیریت کردن تعداد زیادی از محفظه ها با همدیگه ما از ابزار های Container orchestration استفاده می کنیم، مدیریت این محفظه ها شامل لود بالانس کردن، دیپلوی کردن، تغییر مقیاس، مدیریت منابع و … هستش که با این ابزار میتونیم این مدیریت رو در مقیاس بالا، همزمان و به صورت انتخابی داشته باشیم.
14. Multi-Tenancy Architecture
معماری ای هستش که در آن هر واحد (instance) از اون نرم افزار به چندین کاربر خدمات میده انگار که نرم افزار یه آپارتمان چند طبقه هست و کاربران مختلف اجاره نشین داخل اون آپارتمان هستند. اطلاعات هر کاربر داخل اون آپارتمان (instance) جدا هستش و غیرقابل دیدن برای باقی کاربران این آپارتمان هست.
این آپارتمان زیرساخت مشترکی داره مثل سرور، دیتابیس و .. و صرفا جدا شده برای هر کاربر که کار خودش رو بکنه. این معماری داخل سازمان هایی که سرویس های ابری ارائه میدهند رایجه (طبیعتا).
15. Enterprise Integration Patterns
همانند دیزاین پترن ها که برای core اصلی یک مشکل به صورت تکراری پیش میومد یه راه حل ارائه می دهند که قابلیت استفاده ی مجدد دارند و تعمیم اش میدیم برای سیستم و مشکل خودمون، EIP ها هم کاتالوگ های راه حل های قابل استفاده مجدد برای مشکلات رایجی هستند که هنگام ادغام برنامه ها و سیستم های مختلف سازمانی با آن مواجه ممکنه بشیم و صرف نظر از تکنولوژی ای که داریم ارائه شدند و قابل استفاده هستند که بتونیم راه حل رو تعمیم بدیم برای مشکل خودمون.