سبک‌های معماری نرم‌افزار

در این دوره، به‌طور جامع با مفهوم «سبک» در معماری نرم‌افزار آشنا می‌شوید و تأثیر آن بر طراحی سیستم‌ها را به‌خوبی می‌آموزید. همچنین، با سبک‌های رایج معماری نرم‌افزار آشنا خواهید شد و نقاط قوت، ضعف، و Trade-off های هر یک را بررسی می‌کنید تا بتوانید انتخاب مناسب‌تری برای پروژه‌های خود داشته باشید.
سبک‌های معماری نرم‌افزار
5,300,000 تومان
ثبت نام ثبت نام
  • مدرس هادی احمدی
  • مدت زمان 63 ساعت
  • جلسات آموزشی 15 جلسه 3 ساعته
  • جلسات Case Study 6 جلسه 3 ساعته
  • روز دوشنبه ها 18 تا 21
  • تاریخ شروع 16 مهر 1403
  • نوع برگزاری آنلاین
  • هزینه 5,300,000 تومان

توضیحات

عبارت «سبک معماری» یا Architectural Style اولین بار در مقاله‌ای با عنوان «مبانی مطالعه معماری نرم‌افزار» که در سال 1992 توسط Dewayne Perry و Alexander Wolf نوشته شد، معرفی و توضیح داده شد. Wolf و Perry سبک معماری را «شیوه سازماندهی ساختاری» سیستم‌های نرم‌افزاری تعریف کردند و بیان کردند که یک سبک معماری اجزا، روابط بین آن‌ها، و همچنین محدودیت‌ها و اصول طراحی و ساخت و ترکیب آن‌ها را مشخص می‌کند. در نگاه Wolf و Perry، هر سبک معماری، تصمیمات مهمی را درباره اجزای معماری در بر می‌گیرد و بر محدودیت‌های مهمی که بر اجزا و روابط بین آن‌ها تأثیر می‌گذارند، تأکید دارد. مفهوم سبک‌ معماری به سرعت به بحث‌های طراحی و معماری نرم‌افزار راه یافت و در سال‌های بعد، این تعریف بارها توسط دیگران بازبینی، بازتعریف یا تکمیل شد. برای مثال در سال 1996، Marry Shaw و David Garlan، دو چهره برجسته حوزه معماری نرم‌افزار، بخش زیادی از کتاب خود را به بررسی سبک‌های معماری اختصاص دادند.

آشنایی با سبک‌های معماری در دنیای امروز برای معماران نرم‌افزار اهمیت بسیار زیادی دارد. درک عمیق از سبک‌ها و آشنایی با مزایا و معایب هر سبک و Trade-off های آن‌، به طراحان این امکان را می‌دهد که انتخاب‌های مناسب‌تری برای نیازهای پروژه‌های خود داشته باشند و تصمیمات طراحی بهتری بگیرند. این دوره آموزشی تلاش دارد تا دانش لازم را برای درک و استفاده از از سبک‌های معماری ارائه می‌دهد و شما را قادر می‌سازد تا با درک عمیق‌تری به طراحی و پیاده‌سازی نرم‌افزارهای موفق بپردازید.

این دوره به شما کمک خواهد کرد تا:

  • مفهوم سبک‌ها (Styles) را درک کنید
  • سبک‌ها را در Abstraction Level های مختلف مطالعه کنید
  • درک کنید که سبک‌ها چه تاثیراتی در ابعاد مختلف دارند (کیفیت محصول، نحوه تعامل تیم‌های توسعه، نحوه تغییرات آینده محصول و ...)
  • سبک‌های رایج در توسعه نرم‌افزارهای امروز را به همراه Trade-off های آن‌ها بشناسید

چه Style هایی در این دوره پوشش داده شده اند:

  • Layered Architecture Style
  • Pipeline Architecture Style (AKA Pipes and Filters)
  • Microkernel Architecture Style
  • Modular Monolith Architecture Style
  • Microservices Architecture Style
  • Event-Driven Architecture Style

اگر فکر می‌کنید که لیست بالا کامل نیست و نیاز به اضافه کردن مواردی دارد، باید در نظر داشته باشید که هدف اصلی این دوره آموزش مفهوم «سبک معماری» در سطح کلان، شناخت و مطالعه آن‌ها و یادگیری نحوه تحلیل و ارزیابی Trade-off های مربوط به آن‌ها است. به همین دلیل، انتظار می‌رود که شرکت‌کنندگان پس از پایان دوره بتوانند خودشان سبک‌های دیگری را که مد نظر دارند مطالعه کنند.

مخاطبین دوره

دوره «سبک‌های معماری نرم‌افزار» برای افرادی طراحی شده است که در زمینه معماری نرم‌افزار پیش‌زمینه داشته و مطالعات و تجربیات عملی در این حوزه داشته‌اند. از مخاطبان انتظار می‌رود که دو ویژگی زیر را داشته باشند:

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

این دوره، دوره‌ای برای «آشنایی» با سبک‌های معماری نیست. هرچند که سبک‌های مطرح شده در آن تعریف می‌شوند، اما انتظار می‌رود که مخاطب با مفاهیم کلی آشنایی داشته و تجربه حداقلی از آن‌ها کسب کرده باشد، چراکه تمرکز مباحث کلاس بر تحلیل و بررسی عمیق‌تر ابعاد مختلف این سبک‌ها خواهد بود.

سرفصل دوره

0. مروری بر مفاهیم «دوره مبانی معماری نرم‌افزار»

مروری بر مفاهیم اساسی مانند Context، Objective، Driver، Constraint، و Force و ... که برای تحلیل و شناخت فضای مسئله در معماری نرم‌افزار ضروری هستند.

این بخش به مرور مفاهیم ساختاری مانند Structure، Element، Relation، و Interaction می‌پردازد که برای طراحی و سازمان‌دهی اجزای مختلف یک سیستم نرم‌افزاری اهمیت دارند.

Heuristic ها و راه‌حل‌های طبقه‌بندی شده مانند Tactics, Patterns, Principles و ...

در این بخش، مشخصه‌های کیفی مانند Maintainability، Scalability، Evolvability و ... از دوره قبل مرور شده و تاثیرات و روابط آن‌ها با یکدیگر بررسی می‌شود.

به نقل از کتاب Fundamentals of Software Architecture، یکی از وظایف طراح یا معمار، رسیدن به "least-worst combination of trade-offs" است. در این قسمت، به مرور مفهوم Trade-off و چگونگی توازن Quality Attribute یا Characteristics های مختلف خواهیم پرداخت.

1. سبک یا Style در معماری نرم‌افزار

بخش اول این دوره به تعریف Architectural Style اختصاص دارد. در این بخش، ابتدا مفهوم Architectural Styles را تعریف می‌کنیم و نگاهی به تاریخچه و تعاریف مختلف این سبک‌ها در طول زمان خواهیم داشت. سپس به تفاوت‌ها و یا ارتباط بین مفهوم Style و مفاهیم دیگر در معماری نرم‌افزار، مانند الگوهای معماری (Architectural Patterns) و معماری مرجع (Reference Architecture) خواهیم پرداخت. سپس به بررسی ابعاد مختلف سبک‌های معماری، از جمله انواع اجزاء و المان‌ها و روابط بین آن‌ها، مجموعه Heuristic ها و Pattern های مرتبط، مدل‌های مورد استفاده، و Constraint ها، Guideline ها و محدودیت‌های اعمالی در سبک‌ها خواهیم پرداخت.

در این بخش، به موضوعات کلیدی در مورد سبک‌های معماری خواهیم پرداخت:

  • تعریف سبک معماری یا Architectural Style چیست؟
  • تفاوت‌های کلیدی بین Architectural Style و Architectural Pattern
  • تفاوت بین Architectural Style و Reference Architecture (معماری مرجع)
  • روش‌های مختلف طبقه‌بندی سبک‌ها
  • ارزیابی سبک‌ها، Trade-off Analysis و معیارهای انتخاب سبک‌ها

این بخش به بررسی ویژگی‌ها و تفاوت‌های این مفاهیم پرداخته و توضیح می‌دهد که چگونه می‌توان از هر کدام در طراحی سیستم‌های نرم‌افزاری استفاده کرد.

در این بخش، به بررسی اجزاء مختلفی که یک سبک معماری را تشکیل می‌دهند و یا ممکن است در آن وجود داشته باشند خواهیم پرداخت:

  • انواع اجزاء (Parts) و المان‌ها (Elements) و روابط بین آن‌ها
  • مجموعه‌ از Constraint ها، Guideline ها و محدودیت‌های اعمالی سبک
  • مجموعه Heuristic ها و Pattern های تشکیل‌دهنده سبک و یا مرتبط با آن
  • مجموعه‌ Model های استفاده شده در سبک و یا مرتبط با آن

2. Layered Architecture Style

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

در این بخش، ابتدا به مرور تاریخچه و تغییرات معماری لایه‌ای در طول سه دهه گذشته خواهیم پرداخت. سپس به تعریف دقیق این سبک معماری، نقاط قوت و ضعف آن، و بررسی Quality Attribute های مختلف در آن می‌پردازیم.

  • مروری بر تاریخچه و تحولات معماری لایه‌ای
  • تعریف معماری لایه‌ای
  • نقاط قوت و ضعف معماری لایه‌ای
  • بررسی Quality Attribute های مختلف در این معماری

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

برخی از مباحثی که در مورد آن‌ها صحبت خواهیم کرد عبارتند از:

  • مساله Abstraction Level یا سطح انتزاع
  • Commonality Variability Analysis (CVA)
  • تفکیک Responsibility ها
  • موضوع Cross-Cutting Concerns
  • بررسی برخی اصول و الگوهای طراحی لایه‌ها مثل Separating Policy from Mechanism، Separation of Concerns و ...

در این بخش به موضوعات مرتبط با ارتباط و تعامل بین لایه‌ها، مانند طراحی رابط‌ها (Interfaces)، طراحی جریان داده‌ها (Data Flows)، و موارد مشابه می‌پردازیم. برخی از این مباحث شامل موارد زیر می‌باشند:

  • مفهوم Interface و اصول و الگوهای طراحی آن‌ها
  • روش‌ها و الگوهای Messaging Passing و ارتباط
  • مدیریت خطا در انتقال اطلاعات بین لایه‌ها
  • ترجمه بین لایه‌ها

یکی از مهم‌ترین موضوعات، مسئله وابستگی‌ها و Dependency های بین لایه‌ها است. این بخش بر اصول و الگوهای طراحی متمرکز است تا به مدیریت بهتر این وابستگی‌ها کمک کند.

  • Coupling & Cohesion در طراحی لایه‌ها
  • اصول و Heuristic های مدیریت وابستگی‌ها مثل Stable-Abstraction Principle و ...
  • مفاهیم Inversion of Control و Dependency Injection
  • مفهوم Vertical Layer یا Shared Layer

در این بخش، معماری لایه‌ای (و به طور کل مساله طراحی لایه‌ها) را در چندین مورد مختلف بررسی خواهیم کرد. ابتدا به مثال‌هایی خارج از حوزه نرم‌افزار، مانند لایه‌های موجود در پروتکل‌های ارتباطی نظیر TCP/IP یا مدل OSI می‌پردازیم. سپس به بررسی معماری لایه‌ای در چند نوع مختلف از نرم‌افزارها خواهیم پرداخت: به عنوان مثال، لایه‌ها در یک ابزار متن‌باز (Open Source)، معماری لایه‌ای در یک پروژه سازمانی (Enterprise)، و لایه‌ها در یک نرم‌افزار سیستمی مانند سیستم‌عامل.

3. Pipeline (Pipes and Filters) Architecture

سبک Pipeline (یا Pipes and Filters) یکی از قدیمی‌ترین سبک‌های معماری است که داده‌ها را در مسیری متشکل از Filter های مختلف حرکت می‌دهد و در این مسیر هر Filter یک وظیفه پردازشی مشخص را بر عهده دارد. در این بخش از دوره به بررسی این سبک خواهیم پرداخت و نقاط قوت و ضعف آن را مطالعه خواهیم کرد. سپس با استفاده از Case Study های مختلف، تجربه استفاده از این سبک در طراحی سیستم‌های متنوعی مانند سیستم‌های Messaging، سیستم‌های Stream Processing، سیستم‌های Signal Processing، ابزارها و فریم‌ورک‌های وب و ... را بررسی خواهیم کرد.

در این بخش به تعریف Pipeline (یا Pipes and Filters) پرداخته و Trade-off های مربوط به آن را بررسی خواهیم کرد. همچنین کاربردها، نقاط قوت و ضعف این سبک را مورد مطالعه قرار خواهیم داد.

در این بخش به بررسی شکل‌های مختلف طراحی Pipeline خواهیم پرداخت و مواردی مانند Linear Pipe، Bounded Pipe، Typed Pipe و ... را به همراه کاربردشان بررسی خواهیم کرد.

در این قسمت، به بررسی مفاهیم، اصول و الگوهای مرتبط با Modifiability و Extensibility در معماری Pipeline می‌پردازیم. موضوعاتی مانند OCP (Open/Closed Principle) و روش‌های طراحی برای تسهیل قابلیت توسعه (Extensibility) را مورد بحث قرار می‌دهیم و مفاهیمی نظیر Hook، Interception و دیگر الگوهای مشابه را بررسی خواهیم کرد.

در این بخش، به این می‌پردازیم که چگونه می‌توان Filter ها را طوری طراحی کرد که Reusable باشند و در موقعیت‌های مختلف به کار بروند. همچنین، به این مساله خواهیم پرداخت که چگونه می‌توانیم طراحی Composable داشته باشیم و از ترکیب فیلترهای موجود به رفتارهای جدید برسیم. در این بخش، موضوعاتی مانند میزان وابستگی Filter به ExecutionContext، نحوه طراحی Interface ها، استقلال Filter و ... مورد بحث قرار خواهند گرفت.

در این بخش از دوره، به بررسی چند سوال کلیدی در طراحی Pipeline می‌پردازیم:

  • Context کلی اجرا (اصطلاحا Execution Context) چگونه نگهداری و مدیریت می‌شود؟
  • داده‌ها چگونه در Pipeline حرکت می‌کنند؟ آیا همیشه از یک فیلتر به فیلتر دیگر منتقل می‌شوند یا گاهی نیاز به یک Orchestrator برای مدیریت جریان داده‌ها داریم؟
  • تغییر مسیر در اجرای Pipeline (اصطلاحا Branch زدن) به چه صورت و توسط چه کسی کنترل و مدیریت می‌شود؟
  • در چه شرایطی به فیلترهای Stateful نیاز داریم و در این مواقع چه مواردی باید در نظر گرفته شود؟

اگرچه بسیاری از پروژه‌ها به طراحی Pipeline های توزیع شده نیازی ندارند، اما مطالعه این موضوع می‌تواند نکات زیادی برای یادگیری داشته باشد. این نوع Pipeline‌ ها می‌توانند برای کاربردهایی مانند Stream Processing یا Event Processing در مقیاس برزگ مفید باشند. در این حالت، ویژگی‌هایی مانند Scalability و Elasticity اهمیت زیادی دارند و Pipeline باید بتواند به خوبی مقیاس‌پذیر باشد، چه به صورت کلی و برای کل Pipeline و چه به طور خاص برای یک یا چند فیلتر.

در این بخش، به بررسی چندین Case Study می‌پردازیم که به نوعی از این سبک استفاده کرده‌اند یا بر اساس این Topology طراحی شده‌اند. این Case Study‌ها شامل حوزه‌های مختلفی از فریم‌ورک‌ها و ابزارهایی مانند WCF و ASP.NET Core گرفته تا سیستم‌های Messaging و کاربردهای این سبک در Complex Event Processing (CEPStream Processing و برخی محصولات در حوزه Signal Processing می‌شوند.

4. Microkernel Style

سبک Microkernel که یکی از سبک‌های کلاسیک معماری نرم‌افزار است، سیستم را به دو بخش کلی تقسیم می‌کند: هسته اصلی (Core یا Kernel) که قابلیت‌های پایه‌ای سیستم را فراهم می‌کند و Plug-in هایی که با اتصال به این هسته اصلی، قابلیت‌ها و عملکردهای تکمیلی را به آن اضافه می‌کنند. این سبک که شاید بتوان بزرگترین نقطه قوت آن Extensibility نام برد، تاکنون در طراحی سیستم‌های متنوعی از جمله سیستم‌عامل‌ها، IDE ها، CMS ها و ... مورد استفاده قرار گرفته است. (برای مثال Windows NT و یا Eclipse IDE).

در این بخش به تعریف سبک Microkernel پرداخته و نقاط قوت، ضعف و Trade-offهای آن را بررسی می‌کنیم. همچنین، مشخصه‌های کیفی و کاربردهای این سبک در معماری نرم‌افزار مورد مطالعه قرار می‌گیرد.

در این بخش به مسایل مرتبط با طراحی Kernel و Plugin‌ ها می‌پردازیم. لازم است توجه کنیم که طراحی Kernel ممکن است بسته به مساله، با چالش‌های Domain-Specific متعددی همراه باشد و پیچیدگی‌های خاص خود را داشته باشد (مثلا در طراحی Kernel یک سیستم‌عامل). با این حال، در این بخش تلاش می‌کنیم بدون ورود به مسایل وابسته به یک Domain خاص، به مباحث طراحی Kernel و Plugin‌ ها بپردازیم. برخی از این موضوعات عبارتند از:

  • برخی دغدغه‌های طراحی Kernel (Performance، مدیریت بهینه‌ی سرویس‌ها، منابع، Plugin Isolation و ...)
  • سطح انتزاع در طراحی Core یا Kernel (میزان Generic یا Domain-Specific بودن)
  • طبقه‌بندی‌های مختلف اجزاء در معماری Microkernel
    • دو سطحی (Core, Plugins)
    • پنج سطحی (Kernel, Clients, Adapters, Services, Views)
  • Heuristic های طراحی در معماری Microkernel
  • موضوع تغییر و Backward Compatibility
  • مکانیزم‌های نصب و حذف Plugin ها
  • طراحی Plugin Registry

یک دسته از مسائل مهم در طراحی Microkernel ها، مباحث حوزه Connectivity، Communication، و Integration میان اجزا است. در این بخش، انواع روش‌های ارتباطی معرفی شده و اصول، الگوها، و روش‌های ارتباط و Integration مورد بحث قرار می‌گیرند. برخی از این مباحث عبارتند از:

  • انواع ارتباطات (Plugin-to-Kernel, Plugin-to-Plugin, Kernel-to-Plugin)
  • اصول و الگوهای ارتباط بین اجزاء
  • Heuristic های طراحی Interface ها

در این بخش به مفاهیم مرتبط با Extensibility در معماری Microkernel می‌پردازیم و بررسی می‌کنیم که چگونه یک Microkernel می‌تواند با ایجاد بستری مناسب، امکان توسعه و اضافه کردن Plugin‌های متنوع را در طول زمان فراهم کند. همچنین، تکنیک‌هایی مانند طراحی Extensibility Points، استفاده از Hook‌ها و Interceptor‌ها و موارد مشابه را مورد بررسی قرار خواهیم داد.

چگونه می‌توان اطمینان حاصل کرد که بروز Failure در یکی از پلاگین‌ها باعث خرابی کل سیستم نشود؟ در این بخش به موضوع Fault Tolerance پرداخته و الگوهای مدیریت این مساله، از جمله Fault Isolation، را بررسی خواهیم کرد.

معماری Microkernel به‌طور معمول به صورت Monolithic پیاده‌سازی می‌شود، اما در برخی موارد به شکل معماری توزیع‌شده نیز استفاده می‌شود. در این بخش به کاربردهای (هر چند محدود) این سبک در حالت توزیع‌شده و چالش‌های مرتبط با آن پرداخته می‌شود.

در این بخش، به بررسی انواع برخی سیستم‌های مبتنی بر سبک Microkernel می‌پردازیم. این موارد شامل سیستم‌های مدیریت محتوا (CMS)، برخی سیستم‌عامل‌ها (مانند Windows NT) و برخی IDE ها (مثل Eclipse) است. با نگاهی به این نمونه‌ها، چگونگی پیاده‌سازی و مزایای و معایب معماری Microkernel در این سیستم‌ها را بررسی خواهیم کرد.

5. Modular Monolith

سبک Modular Monolith سبکی در راستای طراحی یک سیستم یکپارچه و Monolithic است که به‌طور منطقی به ماژول‌های مستقل و قابل مدیریت تقسیم می‌شود. این سبک به دلیل ساختار Monolithic، هزینه و پیچیدگی کمتری نسبت به سیستم‌های توزیع‌شده دارد و با تمرکز بر طراحی ماژولار، وابستگی‌های بین اجزا را به طور مؤثری مدیریت می‌کند. بدیهی است که این سادگی و راحتی با Trade-off هایی همراه است و به دلیل ماهیت Monolithic، این سبک در مقایسه با سبک‌های توزیع‌شده، از مقیاس‌پذیری کمتری برخوردار است.

در این بخش از دوره به سبک Modular Monolith خواهیم پرداخت و در مورد نحوه طراحی Moduleها و مدیریت وابستگی‌ بین آن‌ها صحبت خواهیم کرد. سپس به بررسی Pattern ها و Anti-Pattern ها در این سبک خواهیم پرداخت و راهکارهای مدیریت وابستگی‌ها و استقلال ماژول‌ها را مطالعه خواهیم کرد.

در این بخش به تعریف سبک Modular Monolith پرداخته و نقاط قوت، ضعف و Trade-offهای آن را بررسی می‌کنیم.

در این بخش، به نحوه طراحی ماژول‌ها، Decompose کردن آن‌ها و مشخص کردن Boundary ها خواهیم پرداخت و اصول طراحی ماژولار را بررسی می‌کنیم. همچنین، به بررسی رویکردهای رایج در طراحی ماژول‌ها خواهیم پرداخت.

  • Abstraction, Decomposition و Granularity ماژول‌ها
  • نگاهی بر رویکردهای متفاوت در طراحی Module-ها
    • حول محور Sub-domain ها
    • حول محور Business Capability ها
    • Narrow Vertical Slicing

در این بخش به مسائل طراحی لایه Presentation و چگونگی پیاده‌سازی Modularity در این لایه خواهیم پرداخت. برخی از موارد این بخش:

  • بررسی روش‌های مختلف طراحی Presentation در سبک Modular Monolithic
  • اصول طراحی Composite UI و رعایت Modularity در آن
  • الگوهای ارتباط بین Moduleها در Composite UI
  • استفاده از Microkernel برای طراحی Composite UI

در این بخش در مورد طراحی Database در Modular Monolith ها صحبت می‌کنیم و در مورد دغدغه‌هایی در حوزه‌های زیر صحبت می‌کنیم:

  • Modularity در Database
  • مساله Transaction ها و وابستگی تراکنشی Module ها
  • مساله Query های مشترک بین Module ها
  • موضوعات عملیاتی (مثل Backup, Disaster Recovery و ...) در Modular Monolith

در این بخش به موضوعات Integration و Consistency بین ماژول‌ها پرداخته می‌شود. برخی موارد عبارتند از:

  • Transactional vs Eventual Consistency
  • استفاده از Event ها (Domain Event, Integration Event)
  • Orchestration و بررسی الگوهایی مانند Facade و ...
  • Query ها و Materialized View ها

وابستگی بین Module ها، یکی از مهم ترین مساله در طراحی Modular Monolith ها است. در این بخش به مدیریت وابستگی‌ها بین ماژول‌ها و چگونگی دستیابی به Loose Coupling خواهیم پرداخت.

  • وابستگی و Dependency در سطوح مختلف (Database، مدل، Query ها و ...)
  • Anti-Corruption Layer و ترجمه بین ماژول‌ها
  • Shared Kernel، کاربردها، مزایا و معایب

Event-Driven Architecture (EDA)

Event-Driven Architecture یا EDA یک سبک معماری است که عمدتا به صورت ترکیبی و در کنار سبک‌های دیگر (مخصوصا سبک‌های توزیع‌شده مثل Microservices) مورد استفاده قرار می‌گیرد. EDA کشش زیادی به Decouple کردن سرویس‌ها از طریق Event ها دارد که مبتنی بر یک مکانیزم قدیمی و کلاسیک با نام Implicit Invocation (Implicit Receiver, Selective Broadcasting) هستند. EDA با تمرکز بر روی Asynchrony، مشخصه‌های کیفی زیادی از جمله Scalability، Elasticity، Autonomy، Fault Tolerance، Extensibility و ... را تحت تاثیر قرار می‌دهد. البته مانند تمام سبک‌‎های معماری دیگر، نقاط ضعف‌ها و همچنین هزینه‌های خاص خود را به همراه دارد.

مباحث این بخش از کلاس به تفصیل در دوره «مفاهیم و مقدمات Event-Driven Architecture» ارائه شده است.

در این بخش به تعریف سبک Event-Driven Architecture (EDA) پرداخته و نقاط قوت، ضعف و Trade-offهای آن را بررسی می‌کنیم. همچنین EDA به عنوان مکملی در کنار سبک‌های توزیع‌شده مثل Event-Driven Microservices مورد بحث قرار می‌گیرد.

  • نقاط ضعف، قوت و Trade-off های EDA
  • EDA به عنوان سبک ترکیبی با دیگر سبک‌ها (مانند Event-Driven Microservices)
  • Topology های مختلف در EDA
  • Implicit Invocation، Reactive Integration، Selective Broadcast
  • Consumer, Producer, Flow
  • Command, Event, Message
  • Sync vs Async Communication
  • Channel, Endpoint, Delivery
  • Queue, Stream
  • Broker, Mediator, Bus
  • Consumer-Driven vs Producer-Driven Subscription
  • بررسی قاعده CAP و Trade-off های حوزه Consistency
    • تعریف Best-Effort Availability و Best-Effort Consistency
    • بررسی رویکرد Strong Consistency – Best-Effort Availability
    • بررسی رویکرد Availability Guarantee – Best-Effort Consistency
  • شناخت مساله Consistency
    • تعریف مفهوم و شناخت Consistency Models
    • زوایای مختلف Consistency (Data-Centric vs Client-Centric View)
    • ابعاد مختلف Consistency (Staleness, Ordering)
    • Guarantee های مختلف مانند (MRC, MWC, RYWC, WFRC)
  • رویکردهای مواجهه با Eventual Consistency
    • رویکردهای Preventive (مانند Lock, Reservation Pattern و ...)
    • رویکردهای Responsive - راه حل‌های مبتنی بر عکس‌العمل
  • طراحی سیستم‌های Messaging در EDA مبتنی بر Pipes and Filters
  • مفاهیم پایه‌ای Messaging مانند (Message, Channel, Delivery, Endpoint و ...)
  • شناخت Delivery Guarantee ها (At-least-once, At-most-once و ...)
  • الگوهای Routing (مانند Aggregator, Splitter, Content-Based Router و ...)
  • الگوهای Transformation و تغییر پیام‌ها (مانند Content Enricher, Envelope Wrapper و ...)
  • الگوهای طراحی Endpoint ها (مانند Idempotent Receiver, Gateway و ...)

در این بخش درباره Transaction ها در EDA صحبت می‌کنیم. ابتدا مدل‌های مختلف Coordination (از جمله Choreography و Orchestration) را بررسی خواهیم کرد سپس وارد مبحث Saga خواهیم شد. در این بخش در مورد مسائل طراحی در Saga ها مانند الگوهای طراحی آن‌ها، مدیریت State در آن‌ها و ... صحبت خواهیم کرد.

وجود تکنیک Implicit Receiver و ترکیب آن با مکانیزم‌های Async به معماری EDA این امکان را می‌دهد که قابلیت‌های گسترده‌ای در زمینه Scalability و Elasticity ارائه دهد. به عنوان مثال، کنترل بیشتر بر روی Load و توزیع آن و یا ایجاد رفتارهای Elastic در زمان اجرا با توجه به وضعیت Channel‌ ها و ... بخشی از این قابلیت‌ها هستند. در این بخش، به بررسی این قابلیت‌ها و نحوه پیاده‌سازی آن‌ها خواهیم پرداخت.

یکی از ویژگی‌های برجسته EDA، قابلیت‌های آن در زمینه Resiliency و مقابله با Failure است. در این بخش از کلاس، به بررسی این قابلیت‌ها خواهیم پرداخت و به تحلیل الگوها و روش‌های مختلف برای مدیریت شکست‌ها خواهیم پرداخت. راه‌حل‌ها را در قالب دو دسته کلی ارائه خواهیم کرد:

  • روش‌های Protective (مانند Queue-Based Load Leveling و Queue-Based Rate Limiting و ...)
  • روش‌های Responsive (مانند Adaptive LIFO و Controlled Delay و ...)

یکی از جنبه‌های مهم در معماری EDA موضوعات Observability و Traceability است. در این بخش از کلاس، به بررسی چالش‌ها و راهکارهای مربوط به این دو مفهوم می‌پردازیم. Observability به معنای توانایی نظارت و مشاهده وضعیت سیستم به طور جامع و دقیق است، در حالی که Traceability به قابلیت دنبال کردن و ردیابی جریان رویدادها و داده‌ها در سیستم اشاره دارد. ما به تحلیل مشکلاتی که ممکن است در این حوزه‌ها به وجود آید و روش‌های مختلف برای مدیریت و بهبود Observability و Traceability در سیستم‌های رویدادمحور خواهیم پرداخت.

  • شناخت نیازمندی‌های Observability (محتوای پیام‌ها، وضعیت Channel ها و ...)
  • شناخت نیازمندی‌های Traceability (مسیر پیام‌ها، ترتیب اتفاقات و ...)
  • طراحی برای Observability و Traceability
  • بررسی تکنولوژی‌ها و ابزارهای مفید در این حوزه

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

در این بخش قصد داریم با برخی حوزه‌های مرتبط با پردازش Event ها آشنا شویم. برای مثال حوزه Stream Processing و یا Complex Event Processing (CEP) . البته تمرکز ما بیشتر بر روی مفاهیم ابتدایی و معرفی کلی خواهد بود و وارد عمق این مباحث نخواهیم شد.

در این بخش، به بررسی تجربیات واقعی شرکت‌های بزرگ که از معماری EDA و سیستم‌های Messaging استفاده کرده‌اند، خواهیم پرداخت. این بررسی شامل تحلیل روش‌های پیاده‌سازی و چالش‌های مواجه شده در مقیاس‌های بزرگ خواهد بود. یکی از این Case Study‌ها، تجربه Facebook در زمینه Resiliency سیستم‌ها است که در مقاله Fail at Scale منتشر شده است.

5. Microservices Style

نیاز به طراحی سیستم‌های ابری بزرگ مقیاس در شرکت‌هایی مثل Amazon و Netflix، زمینه‌ساز به وجود آمدن سبک Microservices شد. این سبک، سبکی توزیع شده و مبتنی بر توسعه سرویس‌های Granular، مستقل و جدا است. این سبک، به دلیل توزیع‌شده بودن، با پیچیدگی‌های زیادی همراه است. اما از طرفی از لحاظ مشخصه‌هایی مانند Scalability، Resiliency، Elasticity و ... مزایای زیادی ارائه می‌دهد.

از زمان ظهور Microservices تا به امروز، تغییرات زیادی در نگرش‌ به این سبک ایجاد شده است. برای مثال در سال 2020، Uber که یکی از پیشگامان استفاده از این سبک بود، در وبلاگ فنی خود نوشت که در مورد میزان ریزدانگی سرویس‌ها دچار اشتباه شده و به سمت Domain-Oriented Microservice Architecture تغییر مسیر داده است. همچنین، برخی از تیم‌هایی که تنها مزایای این سبک را مد نظر داشتند، با هزینه‌های عملیاتی آن روبرو شده و به استفاده از سبک‌های دیگر روی آوردند. به عنوان مثال، در سال 2023، سرویس Amazon Prime Video تصمیم به بازگشت به ساختار Monolithic گرفت.

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

در این بخش به تعریف و شناخت سبک Microservices، و بررسی مزایا، معایب، و Trade-off‌ های آن خواهیم پرداخت. البته لازم است در این جریان، نگاهی بر سیر تحول Service-Orientation در حوزه معماری نرم‌افزار داشته باشیم.

طراحی سرویس‌ها یکی از اصلی‌ترین و پایه‌ای‌ترین مباحث در Microservices است. در این بخش، به تفصیل به نحوه تفکیک و طراحی سرویس‌ها خواهیم پرداخت و مباحث کلیدی طراحی آن‌ها را بررسی خواهیم کرد. برخی از این مباحث شامل:

  • مساله Decomposition و تفکیک سرویس‌ها
    • Domain-Oriented Microservice Architecture
  • مساله سایز و Granularity سرویس‌ها
    • بررسی Integrator و Disintegrator ها
  • مساله Abstraction و سطح انتزاع سرویس‌ها
  • طراحی Boundary و مرز سرویس‌ها

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

  • تعریف Autonomy و انواع آن (Runtime Autonomy و Design-Time Autonomy)
  • بررسی سطوح مختلف Autonomy
  • ارتباط Autonomy با مشخصه‌های کیفی دیگر

یکی از ویژگی‌های بارز Microservices، قابلیت Resiliency و نحوه برخورد با Failure است. در این بخش، به بررسی این موضوع خواهیم پرداخت:

  • فعالیت‌های مختلف در حوزه Resiliency (مانند Recognition, Isolation, Protection و ...)
  • تکنیک‌ها و ابزارهای حوزه Recognition و شناسایی Failure مانند (Healthchecks, Metrics و ...)
  • الگوها و تکنیک‌های حوزه Isolation و جلوگیری از انتشار Failure (مانند Bulkhead و ...)
  • الگوهای حوزه Protection و محافظت از گستردگی ابعاد Failure (مانند Circuit Breaker، Back Pressure، Load Shedding و ...)
  • مباحث حوزه Mitigate و رفع مشکلات ناشی از Failure (مانند Compensation، Rollback و ...)

به دلیل ماهیت توزیع‌شده‌ی سبک Microservices، مساله Integration و یکپارچگی به یکی از مسائل مهم تبدیل می‌شود. در این بخش، ابتدا به بررسی Communication خواهیم پرداخت و سپس به مسائل مربوط به Integration خواهیم پرداخت.

  • بررسی Communication Pattern های مختلف
  • بهره‌گیری از EDA و توسعه Event-Driven Microservices
  • موضوعات حول محور طراحی API
  • بررسی Saga و انواع روش‌های پیاده‌سازی (در بخش EDA) به طور کامل تشریح می‌شود
  • مفاهیم Eventual Consistency (در بخش EDA به طور کامل پوشش داده شده است)

هر چند هم در دوره مبانی و هم در بخش EDA همین دوره، به موضوع Scalability و Elasticity پرداختیم، اما در این قسمت این دو مشخصه را بیشتر در فضای سبک Microservices بررسی میکنیم. برخی از مباحث عبارتند از:

  • Horizontal vs Vertical Scalability
  • مفهوم Auto-Scaling
  • مساله Distribution در ابعاد مختلف (در سطح سرویس‌ها، سطح داده‌ها، Cache ها و ...)
  • الگوها، روش‌ها و Heuristic های طراحی سرویس‌های Scalable و Elastic
  • بررسی Communication و Integration Pattern ها در راستای مقیاس‌پذیری
  • Distribution در داده‌ها در راستای جهت مقیاس‌پذیری (Replication, Partitioning و ...)

در این بخش از کلاس، به بررسی مسائل طراحی مرتبط با API‌ ها و Client ها در معماری Microservices می‌پردازیم.

  • بررسی برخی الگوهای رایج در سطح API ها (مانند API Gateway, BFF و ...)
  • بررسی سبک Micro Frontend جهت طراحی Frontend

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

  • نقش Container ها و Orchestrator ها در جریان Deploy سرویس‌ها
  • نقش Practice های DevOps در توسعه و Deploy سرویس‌ها
  • بررسی Service Mesh ها

در این بخش، به برخی از دغدغه‌ها و مسائل طراحی مرتبط با Production خواهیم پرداخت. موضوعاتی مانند Observability، Monitoring، Logging و سایر مسائل مشابه مورد بررسی قرار می‌گیرند. همانند بخش Deployment، تمرکز این بخش نیز بیشتر بر روی ابعاد طراحی است و کمتر به جنبه‌های ابزاری و تکنولوژیک خواهیم پرداخت.

در بسیاری از منابع، از جمله کتاب‌های Neal Ford و Mark Richards، سبک Microservices به عنوان یکی از معماری‌هایی معرفی شده که از نظر Evolutionary بودن و تطابق با رویکردهای طراحی Evolutionary رتبه بسیار بالایی دارد. اما دلیل این امر چیست و چگونه می‌توان به این قابلیت دست یافت؟ در این بخش از دوره، به بررسی این موضوع و روش‌های سرویس‌های Adaptive و Evolvable خواهیم پرداخت:

  • تکامل‌پذیری و Evolvability در معماری Microservices
  • Adaptability و طراحی سرویس‌های Adaptive
  • Extensibility در طراحی سرویس‌ها
  • Case Study: بررسی مسیر تکاملی پیشگامان استفاده از معماری Microservices مثل Uber و Amazon و ...

ورود به توسعه سیستم‌های توزیع‌شده با طرز فکر Monolithic، اغلب منجر به اشتباهاتی در تصمیم‌گیری می‌شود که نهایتاً به ایجاد یک Distributed Monolith می‌انجامد؛ معماری که تقریباً تمام محدودیت‌های سبک Monolithic را با خود دارد، در حالی که هزینه‌های Microservices را نیز به همراه می‌آورد. در این بخش از کلاس، به بررسی مجموعه‌ای از اشتباهات رایج در زمینه‌های مختلف (مانند طراحی سرویس‌ها، ارتباط بین سرویس‌ها و ...) می‌پردازیم و تلاش می‌کنیم تا با ارائه رویکردهای صحیح، ذهنیت بهتری را برای توسعه سیستم‌های توزیع‌شده در مخاطب ایجاد کنیم.

در این بخش به بررسی چند Case Study از تجربه‌های موفق و ناموفق در استفاده از Microservices می‌پردازیم. با توجه به اینکه این معماری اغلب در مقیاس‌های بسیار بزرگ به کار می‌رود، بیشتر این Case Studyها مربوط به شرکت‌های بزرگی مانند Uber، Amazon و ... خواهند بود. برای مثال:

  • سیر تکاملی Uber در طراحی سرویس‌ها و حرکت به سمت Domain-Oriented Microservices
  • تجربه بازگشت به ساختار Monolithic در سرویس Amazon Prime Videos
  • مسیر مهاجرت Netflix به Cloud و معماری Microservices

8. Architectural Governance

هر سبک معماری با مجموعه‌ای از اصول، راهنمایی (Guideline)، و Heuristicsهای طراحی همراه است که باید در طراحی سیستم توسط تیم رعایت شوند و یا مدنظر قرار بگیرند. برای مثال، در یک سبک توزیع‌شده، ممکن است Asynchronous Messaging نسبت به Sync API Call ترجیح داده شود، یا استفاده از دیتابیس مشترک ممکن است با اهداف سبک مورد نظر تناقض داشته باشد. . اما چگونه می‌توان در فرآیند طراحی یک سیستم، اطمینان حاصل کرد که این موارد به درستی رعایت می‌شوند؟

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

  • مروری بر تکنیک‌های بهبود جریان تصمیم‌گیری در تیم‌های توسعه از دوره قبل
  • نحوه مستندسازی جهت انتقال دقیق و جامع Guideline های سبک معماری
  • نحوه ساخت درک مشترک از Guideline ها و اصول موردنظر در سبک
  • نحوه برگزاری جلسات Design Review
  • به‌کارگیری Architecture Tests برای شناسایی و کنترل نقض قوانین (ابزارهایی مانند ArchUnit و ...)

9. سبک‌ها و پویایی‌های انسانی

از سال 1968 و با مطرح شدن قانون Conway، ثابت شد که همه سیستم‌های نرم‌افزاری شامل این قانون‌ می‌شوند: «سازمان‌هایی که سیستم‌ طراحی می‌کنند، ناگزیر طراحی‌هایی انجام می‌دهند که بازتابی از ساختارهای ارتباطی این سازمان‌هاست.» Eric Raymond با لحنی طنزآمیز بیان می‌کند: «اگر چهار تیم روی یک کامپایلر کار کنند، شما یک کامپایلر چهار مرحله‌ای خواهید داشت. »

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

در این بخش از دوره، قصد داریم به بررسی عمیق‌تری از موضوعات مرتبط با تأثیر ساختار تیم‌ها و سبک‌های معماری بپردازیم:

  • مروری بر قانون Conway: بررسی چگونگی تأثیر ساختار سازمانی بر طراحی سیستم‌ها
  • The Reverse Conway Maneuver: نحوه ایجاد بهبود در طراحی سیستم‌ها از طریق تغییرات در ساختار سازمانی و تیمی.
  • مروری بر مفاهیم Team Topologies: آشنایی با انواع تیم‌ها و تعاملات بین تیمی.
  • Cognitive Load – بار شناختی: تاثیر سبک‌های معماری مختلف بر «بار شناختی» افراد و تیم‌ها
  • سبک‌ها و ساختار تیم‌ها و تعاملات تیمی: بررسی تأثیر سبک‌های مختلف معماری بر ساختار تیم‌ها و نحوه تعامل آن‌ها و بالعکس.

نحوه برگزاری جلسات آموزشی

(مجموعا 23 جلسه)

15 جلسه آموزشی 3 ساعته

6 جلسه 3 ساعته Case Study

30 دقیقه پرسش و پاسخ بعد هر جلسه

ارسال ویدیوها به دانشجویان بعد جلسه

اطلاع از آخرین دوره‌ها و کارگاه‌های آموزشی

جهت دریافت آخرین اخبار مربوط به دوره‌ها و کارگاه‌های آموزشی، کانال تلگرام ما را دنبال کنید: