سلام به همه دوستان و همکاران
در حال حاضر چندین موضوع بروز و جدید رو مطالعه کردم و دیدم بد نیست اون هارو به زبان ساده اما کاربردی و فنی بیان کنم. اخیراً درگیر تمرینی در درس معماری نرمافزار بودم که هدفش آشنایی اولیه با چندتا از این مفاهیم داغ بود. گفتم شاید بد نباشه خلاصهای از برداشتهای خودم رو با شما هم به اشتراک بذارم. این توضیحات سعی شده خیلی ساده و روان باشه، جوری که انگار داریم با هم گپ میزنیم. پس اگه شما هم مثل من دنبال یه دید کلی و سریع به این موضوعات هستید، همراهم باشید!
همچنین لینک پست لیندکدین در زیر قابل مشاهده است:
https://www.linkedin.com/posts/hasan-roknabadi-663854303_%DB%B1%DB%B5-%D9%85%D9%81%D9%87%D9%88%D9%85-%D9%85%D9%87%D9%85-%D8%AF%D8%B1-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D9%86%D8%B1%D9%85%D8%A7%D9%81%D8%B2%D8%A7%D8%B1-%D8%A8%D9%87-%D8%B2%D8%A8%D8%A7%D9%86-activity-7327314787665629184-rOTi?utm_source=share&utm_medium=member_desktop&rcm=ACoAAE2Lw6sBPbQg4zjjJqpOgk15lYbqrZpCkxU
۱. زیرساخت به عنوان کد (Infrastructure as Code - IaC)

تا حالا شده بخواهید یک زیرساخت پیچیده رو بارها و بارها با تنظیمات یکسان راهاندازی کنید؟ مثلاً چند سرور، شبکه، دیتابیس و کلی تنظیمات دیگه. انجام دستی این کار هم زمانبره، هم مستعد خطا.
اینجا «زیرساخت به عنوان کد» یا IaC به کمک میاد IaC .یعنی به جای اینکه دستی تو کنسول AWS یا Azure کلیک کنیم و منابع بسازیم، میایم با استفاده از کدهایی (مثلاً با ابزارهایی مثل Terraform یا CloudFormation) تعریف میکنیم که چه زیرساختی با چه مشخصاتی میخوایم. این کدها مثل دستور غذایی یا اسکریپت کارا که در ابزار های زیر ساخت به عنوان کد نام برده شد استفاده میشوند و فقط یک بار مینویسیمشون و بعد هر چند بار که بخوایم، میتونیم همون زیرساخت رو بدون کم و کاست و دقیقاً مث دفعه اول بسازیم. مزیت بزرگش اینه که زیرساختمون هم مثل کدهای برنامهمون قابل ورژنکنترل، بازبینی و اتوماتیکسازی میشه. دیگه خبری از "روی سیستم من کار میکرد!" برای زیرساخت نیست، چون همه چیز مستند و قابل تکراره.
۲. درگاه API و شبکه خدماتی (API Gateway & Service Mesh)
وقتی با معماری میکروسرویس کار میکنیم، تعداد زیادی سرویس کوچیک داریم که با هم حرف میزنن. اینجا دو تا مفهوم مهم مطرح میشه:
فکر کنید یه ساختمون بزرگ با کلی دفتر (میکروسرویس) دارید.
در واقع API Gateway مثل نگهبان یا مسئول پذیرش دم در اون ساختمونه. تمام درخواستهای خارجی (مثلاً از اپ موبایل یا وب) اول به API Gateway میرسه. اون هم کارایی مثل احراز هویت، محدود کردن تعداد درخواستها (Rate Limiting)، مسیریابی درخواست به سرویس مربوطه و حتی گاهی تبدیل فرمت درخواستها رو انجام میده. اینطوری هم کلاینتها راحتترن (یه نقطه ورود دارن) و هم سرویسهای داخلی از خیلی پیچیدگیها خلاص میشن.
حالا اگه بخوایم ارتباطات داخل همون ساختمون، یعنی بین خود دفترها (میکروسرویسها) رو مدیریت کنیم چی؟ Service Mesh مثل یه سیستم مخابراتی پیشرفته داخلی برای اون ساختمونه. این ابزار به ما کمک میکنه تا ترافیک بین سرویسها رو مدیریت کنیم، امنیت ارتباطاتشون رو برقرار کنیم، ببینیم کدوم سرویسها با هم حرف میزنن و اگه مشکلی پیش اومد سریعتر پیداش کنیم. ابزارهایی مثلIstio یاLinkerd این کار رو انجام میدن. حال Service Mesh روی ارتباطات سرویس به سرویس تمرکز داره، در حالی که API Gateway بیشتر روی ارتباط کلاینت-به-سرویس.
به طور کلی فرق بین این دو را میتوان این گونه بیان کرد که در Service Mesh هدف اصلی ارتباط بین خود سرویس ها و در API Gateway ارتباط بین کلاینت و سرویس ها مدنظر و هدف اصلی است.
۳.مفهوم CQRS – (Command Query Responsibility Segregation)

تصور کنید یه سیستم دارید که همزمان هم باید دادههای زیادی رو بخونه (مثلاً نمایش لیست محصولات) و هم دادههای جدیدی رو بنویسه یا ویرایش کنه (مثلاً ثبت سفارش جدید). گاهی اوقات، مدل دادهای که برای نوشتن اطلاعات مناسبه، برای خوندن بهینه نیست (و برعکس) CQRS میگه بیایم این دو تا کار رو از هم جدا کنیم. یعنی یه مدل جدا برای "دستورها" (Commands) که مسئول تغییر دادن دادهها هستن (مثل ایجاد، ویرایش، حذف) و یه مدل جدا برای "پرسوجوها" (Queries) که فقط مسئول خوندن دادهها هستن. اینطوری میتونیم هر بخش رو متناسب با نیازش بهینه کنیم. مثلاً دیتابیسی که برای نوشتن سریع طراحی شده رو برای دستورها استفاده کنیم و دیتابیسی که برای خوندن سریع بهینه شده رو برای پرسوجوها. این کار باعث میشه سیستممون انعطافپذیرتر و مقیاسپذیرتر بشه.
۴. معماری رویداد محور (Event-Driven Architecture - EDA)

در معماری رویداد محور، ارتباط بین اجزای مختلف سیستم (مثلاً میکروسرویسها) بر اساس "رویدادها" (Events) شکل میگیره. رویداد یعنی یه اتفاق مهمی که تو سیستم افتاده، مثلاً "سفارش جدید ثبت شد" یا "کاربر لاگین کرد". وقتی یه سرویس کاری انجام میده که منجر به یه رویداد میشه، اون رویداد رو منتشر میکنه (مثلاً تو یه Message Queue میذاره). بقیه سرویسهایی که به اون نوع رویداد علاقهمند هستن، بهش گوش میدن و کار خودشون رو انجام میدن. مثلاً وقتی رویداد "سفارش جدید ثبت شد" منتشر میشه، سرویس انبارداری میفهمه که باید موجودی رو کم کنه و سرویس ارسال ایمیل هم یه ایمیل تایید برای مشتری میفرسته. مزیت بزرگش اینه که سرویسها از هم مستقل (decoupled) میشن و نیازی نیست مستقیم همدیگه رو صدا بزنن. این باعث میشه سیستم انعطافپذیرتر، مقیاسپذیرتر و مقاومتر در برابر خطا بشه.
۵. معماری بدون سرور (Serverless Architecture)
اسم "بدون سرور" شاید یکم گمراهکننده باشه، چون بالاخره یه جایی سروری هست که کد ما رو اجرا میکنه! اما نکته اینجاست که مادیگه درگیر مدیریت اون سرورها (نصب سیستمعامل، پچهای امنیتی، مقیاسپذیری و ...) نیستیم. در معماری Serverless، ما کدهامون رو به صورت "توابع" (Functions) مینویسیم و اونها رو روی پلتفرمهای ابری مثل AWS Lambda یا Azure Functions بارگذاری میکنیم. این توابع فقط وقتی اجرا میشن که یه اتفاقی (event) بیفته، مثلاً یه درخواست HTTP بیاد یا یه فایل تو فضای ذخیرهسازی آپلود بشه. ما هم فقط به اندازه زمانی که کدمون اجرا شده و منابعی که مصرف کرده پول میدیم. این یعنی صرفهجویی خیلی خوب در هزینهها، مخصوصاً برای اپلیکیشنهایی که همیشه ترافیک بالایی ندارن. مقیاسپذیری هم به صورت خودکار توسط پلتفرم انجام میشه.
۶. روش API (API-first Approach)
در این رویکرد، قبل از اینکه حتی یه خط کد برای رابط کاربری (UI) وب یا موبایل بنویسیم، اول میریم سراغ طراحی و ساخت APIها. API مثل یه قرارداد یا رابط استاندارد بین بخشهای مختلف نرمافزار یا حتی بین نرمافزار ما و دنیای بیرون عمل میکنه. وقتی اول API رو طراحی میکنیم، تیمهای مختلف (مثلاً تیم بکاند، تیم فرانتاند، تیم موبایل) میتونن به صورت موازی و مستقل از هم کار کنن، چون میدونن قراره با چه API هایی صحبت کنن. این کار باعث میشه توسعه سریعتر بشه، مستندسازیAPIها جدیتر گرفته بشه و در نهایت، تجربه کاربری یکپارچهتری روی پلتفرمهای مختلف داشته باشیم. انگار اول نقشه راه و اتصالات اصلی رو مشخص میکنیم، بعد میریم سراغ ساخت ساختمونها.
۷.مفهوم (Domain Driven Design) DDD
طراحی دامنه محور یا DDD یه رویکرد برای ساخت نرمافزارهای پیچیدهست که تمرکزش روی درک عمیق "دامنه کسبوکار" (Business Domain) و مدلسازی اون در نرمافزاره. ایده اصلی اینه که نرمافزار باید بازتابی از واقعیتهای کسبوکار باشه. برای همین، خیلی مهمه که توسعهدهندهها و کارشناسهای اون کسبوکار(Domain Experts) یه زبان مشترک (Ubiquitous Language) داشته باشن و از همون اصطلاحات در کد و مستندات استفاده کنن. DDD مفاهیمی مثل (Bounded Context) مرزبندی بخشهای مختلف دامنه (Aggregate) مجموعهای از اشیاء که با هم یک واحد رو تشکیل میدن Entity و Value Object رو معرفی میکنه تا به ما کمک کنه مدلهای دقیقتر و قابل فهمتری از کسبوکار بسازیم. این کار در نهایت به تولید نرمافزاری منجر میشه که نگهداریش راحتتره و بهتر با نیازهای واقعی کسبوکار هماهنگه.
۸. معماری شش ضلعی (Hexagonal Architecture / Ports and Adapters)

معماری شش ضلعی (که بهش "پورتها و آداپتورها" هم میگن) یه الگو برای طراحی نرمافزاره که هدفش جداسازی کامل منطق اصلی برنامه هسته یا Domain Logic از نگرانیهای بیرونی مثل رابط کاربری، دیتابیس، یا سرویسهای جانبیه. تصور کنید هسته برنامه شما در مرکز قرار داره. این هسته از طریق "پورتها" (که معمولاً اینترفیسهایی در کد هستن) با دنیای بیرون ارتباط برقرار میکنه. برای هر تکنولوژی یا ابزار خارجی (مثل یه دیتابیس خاص یا یه فریمورک وب) یه "آداپتور" نوشته میشه که اون پورت رو پیادهسازی میکنه. مثلاً یه آداپتور برای دیتابیس MySQL و یه آداپتور دیگه برای PostgreSQL اینطوری اگه بخوایم دیتابیس رو عوض کنیم، فقط کافیه آداپتورش رو عوض کنیم و هسته برنامه دست نخورده باقی میمونه. این معماری تستپذیری و انعطافپذیری سیستم رو خیلی بالا میبره.
۹. منبعیابی رویداد (Event Sourcing)

در روش سنتی، ما معمولاً "وضعیت فعلی" دادهها رو تو دیتابیس ذخیره میکنیم. مثلاً اگه موجودی حساب کاربری تغییر کنه، فقط مقدار جدید موجودی رو آپدیت میکنیم. اما در Event Sourcing، ما تمام "تغییرات" رو به صورت دنبالهای از "رویدادها" ذخیره میکنیم. یعنی به جای اینکه بگیم "موجودی فعلی ۱۰۰۰ تومان است"، میگیم "ابتدا ۵۰۰ تومان واریز شد، سپس ۲۰۰ تومان برداشت شد، سپس ۷۰۰ تومان واریز شد". وضعیت فعلی سیستم با اجرای دوباره این رویدادها از ابتدا به دست میاد. این کار مزایای زیادی داره: هیچ دادهای از بین نمیره و همیشه میتونیم تاریخچه کامل تغییرات رو ببینیم (عالی برای Audit) ، میتونیم وضعیت سیستم رو در هر نقطهای از زمان بازسازی کنیم، و حتی میتونیم مدلهای مختلفی برای خوندن دادهها(Read Models) بر اساس همین رویدادها بسازیم که به CQRS خیلی کمک میکنه. مثل دفتر کل حسابداری میمونه که همه تراکنشها رو ثبت میکنه.
۱۰.پلتفرم های (Low-code/No-code Platforms)
این پلتفرمها به افراد این امکان رو میدن که اپلیکیشنهای نرمافزاری رو با حداقل کدنویسی (Low-code) یا حتی بدون هیچ کدنویسی(No-code) بسازن. معمولاً این کار از طریق رابطهای کاربری گرافیکی، ابزارهای کشیدن و رها کردن(Drag-and-drop) و قالبهای از پیش آماده انجام میشه. هدف اصلی اینه که توسعه نرمافزار سریعتر بشه و حتی افرادی که تخصص برنامهنویسی ندارن (مثل تحلیلگران کسبوکار یا مدیران محصول) هم بتونن ایدههاشون رو به سرعت پیادهسازی کنن. این پلتفرمها برای ساخت پروتوتایپها، اپلیکیشنهای داخلی ساده، یا اتوماسیون فرآیندهای کسبوکار خیلی مفید هستن. البته برای سیستمهای خیلی پیچیده و با نیازمندیهای خاص، ممکنه محدودیتهایی داشته باشن، اما سرعت و سادگیشون واقعاً جذابه.
۱۱. سیستمهای مدیریت فرآیندهای کسبوکار (BPMS - Business Process Management Systems)
هر سازمانی برای انجام کارهاش یه سری فرآیند داره، مثل فرآیند استخدام، فرآیند تایید مرخصی، یا فرآیند پردازش سفارش مشتریBPMS .نرمافزاریه که به سازمانها کمک میکنه این فرآیندها رو به صورت دیجیتالی مدلسازی، اجرا، پایش و بهینهسازی کنن. با BPMS میتونیم نمودار جریان کار(Workflow) هر فرآیند رو بکشیم، مشخص کنیم هر مرحله توسط چه کسی و با چه شرایطی انجام بشه، فرمهای لازم رو طراحی کنیم و کل فرآیند رو اتوماتیک کنیم. این کار باعث میشه فرآیندها شفافتر، کارآمدتر و با خطای کمتری انجام بشن. همچنین BPMS امکان مانیتورینگ و گزارشگیری از عملکرد فرآیندها رو میده تا نقاط قابل بهبود رو شناسایی کنیم. در واقع BPMS به مدیریت منظم و هوشمندانه فعالیتهای سازمان کمک شایانی میکنه.
۱۲. صف پیام (Message Queue) - مثل Kafka و RabbitMQ

صف پیام یه جورایی مثل صندوق پست برای نرمافزارها عمل میکنه. وقتی یه بخش از سیستم (Producer) میخواد یه پیامی (دادهای) رو برای بخش دیگهای (Consumer) بفرسته، به جای اینکه مستقیم صداش بزنه، پیام رو تو یه "صف" میذاره. اون بخش دیگه هم هر وقت آماده بود، میره و پیامها رو از صف برمیداره و پردازش میکنه. این کار باعث میشه فرستنده و گیرنده از هم مستقل بشن (Decoupling). اگه گیرنده موقتاً در دسترس نباشه، پیام تو صف منتظر میمونه و از بین نمیره. این روش برای توزیع بار بین چند پردازشگر، افزایش مقاومت سیستم در برابر خطا، و پیادهسازی ارتباطات غیرهمزمان (Asynchronous) خیلی مفیده. Kafka بیشتر برای حجم بالای داده و پردازش جریانی (Streaming) استفاده میشه و خیلی مقیاسپذیره، در حالی که RabbitMQ یه کارگزار پیام سنتیتر با امکانات مسیریابی پیچیدهتره.
13. ارکستراسیون کانتینرها (Container Orchestration)

امروزه خیلی از اپلیکیشنها رو به صورت "کانتینر" مثلاً با Docker بستهبندی میکنیم. کانتینرها سبک، قابل حمل و ایزوله هستن. اما وقتی تعداد این کانتینرها زیاد میشه و روی چندین ماشین مختلف پخش میشن، مدیریتشون خیلی سخت میشه. اینجا "ارکستراسیون کانتینرها" مثل Kubernetes یا به اختصار K8s وارد میدون میشه Kubernetes مثل یه رهبر ارکستر برای کانتینرهای ما عمل میکنه. وظایفی مثل اینکه هر کانتینر روی کدوم ماشین اجرا بشه(Scheduling)، چطور بینشون بار توزیع بشه (Load Balancing)، اگه یه کانتینر خراب شد چطور جایگزین بشه(Self-healing)، و چطور نسخههای جدید اپلیکیشن بدون قطعی سرویس آپدیت بشن(Rolling Updates) رو به صورت خودکار انجام میده. این باعث میشه بتونیم اپلیکیشنهای بزرگ و پیچیده رو با اطمینان و کارایی بالا روی زیرساختهای مختلف اجرا و مدیریت کنیم.
۱۴. معماری چند مستأجری (Multi-Tenancy Architecture)

در معماری چند مستأجری، یک نمونه (Instance) از نرمافزار به چندین مشتری یا "مستأجر" (Tenant) به طور همزمان سرویس میده، در حالی که دادهها و تنظیمات هر مستأجر از بقیه جدا و ایزوله نگه داشته میشه. فکر کنید یه آپارتمان دارید که چندین واحد داره. هر واحد مستأجر خودشو داره (دادهها و تنظیمات شخصی)، اما همه از زیرساخت مشترک ساختمون (مثل لولهکشی، برق، آسانسور) استفاده میکنن. این معماری برای ارائهدهندگان نرمافزار به عنوان سرویس (SaaS) خیلی رایجه، چون هزینههای زیرساخت و نگهداری رو کاهش میده (یک نرمافزار برای همه آپدیت میشه). چالش اصلی در این معماری، اطمینان از امنیت و ایزولهسازی کامل دادههای هر مستأجر و همچنین مدیریت منابع به شکلیه که فعالیت یه مستأجر روی بقیه تأثیر منفی نذاره(Noisy Neighbor Problem)
۱۵. الگوهای یکپارچهسازی سازمانی (Enterprise Integration Patterns - EIP)
وقتی تو سازمانهای بزرگ با چندین سیستم نرمافزاری مختلف (مثل CRM، ERP سیستم مالی و ... ) سروکار داریم، برقراری ارتباط و تبادل داده بین این سیستمها یه چالش بزرگه. EIP مجموعهای از راهحلهای اثباتشده و بهترین تجارب برای حل مشکلات رایج در زمینه یکپارچهسازی سیستمهاست. این الگوها که توسط Gregor Hohpe و Bobby Woolf در کتاب معروفی به همین نام جمعآوری شدن، مثل یه زبان مشترک و جعبه ابزار برای معماران و توسعهدهندگانیه که میخوان سیستمهای ناهمگون رو به هم متصل کنن. الگوهایی مثل Message Router چطور پیامها رو به مقصد درست هدایت کنیم Content Enricher (چطور اطلاعات پیام رو قبل از ارسال غنیتر کنیم)، یاSplitter وAggregator (چطور پیامهای بزرگ رو بشکنیم و بعداً دوباره جمع کنیم) مثالهایی از این الگوها هستن. استفاده از EIP به ساخت راهحلهای یکپارچهسازی قویتر، قابل فهمتر و با قابلیت نگهداری بهتر کمک میکنه.
خب، این هم از برداشتهای اولیه من از این ۱۵ مفهوم جذاب. امیدوارم این توضیحات ساده و در عین حال فنی و کاربردی براتون مفید بوده باشه و یه دید کلی بهتون داده باشه. قطعاً هر کدوم از این موضوعات دنیایی از جزئیات دارن که میشه ساعتها در موردشون صحبت کرد. خوشحال میشم اگه شما هم تجربه یا نکتهای در مورد این مفاهیم دارید، در کامنتها به اشتراک بذارید تا همگی بیشتر یاد بگیریم.
مراجع مورد استفاده (و همچنین برای مطالعه بیشتر):
موفق و پیروز باشید!