S.Amin nayeri
S.Amin nayeri
خواندن ۱۵ دقیقه·۳ سال پیش

تعریف DDD، MVVM و Event Sourcing :


Domain-Driven Design یا DDD به معنی، طراحی دامنه محور:

طراحی دامنه محور (Domain-Driven Design یا DDD):

یک رویکرد طراحی نرم‌افزاری است که بر نرم‌افزار مدل‌سازی تمرکز می‌کند تا دامنه را مطابق با ورودی کارشناسان آن دامنه مطابقت دهد.

برای تعریف طراحی مبتنی بر دامنه، ابتدا باید منظور خود از دامنه را در این زمینه (و به طور کلی توسعه) مشخص کنیم. تعریف رایج فرهنگ لغت از دامنه این است: "حوزه ای از دانش یا فعالیت". کمی از این موضوع، دامنه در قلمرو مهندسی نرم افزار معمولاً به حوزه موضوعی اشاره دارد که برنامه در نظر گرفته شده در آن اعمال شود. به عبارت دیگر، در طول توسعه برنامه، دامنه «حوزه دانش و فعالیتی است که منطق برنامه حول آن می چرخد».

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

طراحی دامنه محور (DDD) بر سه اصل اصلی تمرکز دارد:

- تمرکز کردن روی دامنه اصلی و منطق دامنه

- قرار دادن طرح­های پیچیده بر اساس مدل­های دامنه

- همکاری مداوم با کارشناسان دامنه، به منظور بهبود مدل برنامه و حل مشکلات مرتبط با دامنه

طراحی دامنه محور ایوانز چند اصطلاح رایج را تعریف می­کند که هنگام توصیف و بحث در مورد اقدامات DDD مفید هستند:

زمینه یا context: تنظیماتی که در آن یک کلمه یا عبارت ظاهر می­شود که معنای آن را تعیین می­کند. اظهارات مربوط به یک مدل را فقط می­توان در یک زمینه درک کرد.

مدل: سیستمی از انتزاعات که جنبه­های انتخابی یک دامنه را توصیف می­کند و می­تواند برای حل مسائل مربوط به آن حوزه استفاده شود.

زبان فراگیر یا Ubiquitous Language: زبانی است که حول مدل دامنه ساختار یافته و توسط همه اعضای تیم برای اتصال تمامی فعالیت­های تیم با نرم افزار استفاده می­شود.

زمینه محدود یا Bounded Context: توصیفی از یک مرز (معمولاً یک سیستم فرعی یا کار یک تیم خاص) که در آن یک مدل خاص تعریف شده و قابل اجرا است.

طراحی دامنه محور نیز تعدادی از مفاهیم سطح بالا را تعریف می کند که می­توانند در ارتباط با یکدیگر برای ایجاد و اصلاح مدل­های دامنه استفاده شوند که عبارتند از:

موجودیت: شیئی که با رشته پیوستگی خود مشخص می­شود، در مقابل اشیاء سنتی که با ویژگی هایشان تعریف می­شوند.

شئ ارزشی یا Value Object: یک شیء تغییرناپذیر (غیر قابل تغییر) که دارای صفات است، اما هویت متمایز ندارد.

دامنه رخداد یا Domain Event: شیئی که برای ثبت یک رویداد گسسته مربوط به فعالیت مدل در سیستم استفاده می شود. در حالی که همه رویدادهای داخل سیستم قابل ردیابی هستند، یک رویداد دامنه فقط برای انواع رویدادهایی ایجاد می­شود که کارشناسان دامنه به آن اهمیت می­دهند.

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

خدمات یا Service : اساساً یک سرویس یک عملیات یا شکلی از منطق تجاری است که به طور طبیعی در قلمرو اشیاء نمی­گنجد. به عبارت دیگر، اگر برخی از عملکردها باید وجود داشته باشد، اما نمی تواند به یک موجودیت یا شی ارزش مرتبط باشد، احتمالاً یک سرویس هستند.

مخازن یا Repositories: نباید با مخازن رایج کنترل نسخه اشتباه گرفته شود، معنی DDD مخزن سرویسی است که از یک رابط جهانی برای دسترسی به تمام موجودیت ها و اشیاء ارزشی که در یک مجموعه انبوه خاص هستند استفاده می­کند. روش‌هایی باید تعریف شوند تا امکان ایجاد، اصلاح و حذف اشیاء در مجموعه را فراهم کنند. با این حال، با استفاده از این سرویس مخزن برای ایجاد پرس و جوهای داده، هدف حذف چنین قابلیت­های پرس و جوی داده از درون منطق تجاری مدل­های شی است.

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

طراحی دامنه محور نیز به شدت بر رویه محبوب تر یکپارچه سازی مداوم تأکید می­کند، که از کل تیم توسعه می خواهد که از یک مخزن کد مشترک استفاده کنند و روزانه (اگر نه چندین بار در روز) به آن تعهد بدهند. یک فرآیند خودکار در پایان روز کاری اجرا می‌شود که یکپارچگی کل پایه کد، اجرای تست‌های واحد خودکار، تست‌های رگرسیون و موارد مشابه را بررسی می‌کند تا به سرعت هرگونه مشکل احتمالی که ممکن است در آخرین commit‌ها معرفی شده باشد را شناسایی کند.

  • مزایای طراحی دامنه محور:

- ارتباطات را آسان می کند: با تأکید اولیه بر ایجاد یک زبان مشترک و همه جا حاضر مرتبط با مدل دامنه پروژه، تیم ها اغلب ارتباط در کل چرخه عمر توسعه را بسیار آسان­تر می­بینند. به طور معمول، DDD هنگام بحث در مورد جنبه­های برنامه به اصطلاحات فنی کمتری نیاز دارد، زیرا زبان فراگیر که در اوایل ایجاد شد، احتمالاً اصطلاحات ساده تری را برای اشاره به جنبه های فنی تر تعریف می­کند.

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

- بر روی اینترفیس دامنه تاکید می کند: از آنجایی که DDD تمرین ایجاد مفاهیم دامنه و آنچه متخصصان دامنه در پروژه توصیه می کنند، DDD اغلب برنامه­هایی را تولید می­کند که دقیقاً برای دامنه مورد نظر مناسب و نماینده آن هستند، برخلاف آن برنامه­ها. که در درجه اول بر UI/UX تاکید دارند. در حالی که یک تعادل آشکار مورد نیاز است، تمرکز بر دامنه به این معنی است که یک رویکرد DDD می­تواند محصولی تولید کند که به خوبی با مخاطبان مرتبط با آن دامنه طنین انداز شود.

  • معایب طراحی دامنه محور:

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

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

- برای پروژه های بسیار فنی مناسب نیست: در حالی که DDD برای برنامه­هایی که پیچیدگی دامنه زیادی دارند (که منطق کسب و کار نسبتاً پیچیده و پیچیده است) عالی است، DDD برای برنامه هایی که پیچیدگی دامنه حاشیه ای دارند چندان مناسب نیست، اما برعکس پیچیدگی فنی زیادی دارند. از آنجایی که DDD به شدت بر نیاز (و اهمیت) متخصصان دامنه برای تولید زبان مناسب همه جا حاضر و سپس مدل دامنه ای که پروژه بر اساس آن استوار است تأکید می کند، پروژه ای که از نظر فنی فوق العاده پیچیده است ممکن است برای کارشناسان دامنه چالش برانگیز باشد و مشکلاتی را ایجاد کند. شاید زمانی که الزامات یا محدودیت های فنی به طور کامل توسط همه اعضای تیم درک نشده بود.

الگوی Model-View-ViewModel (MVVM):

یک الگوی طراحی نرم افزاری است که برای جداسازی منطق برنامه و کنترل های رابط کاربری ساخته شده است. MVVM همچنین به عنوان model-view-binder شناخته می شود و توسط معماران مایکروسافت کن کوپر و جان گاسمن ساخته شده است.

مانند بسیاری از الگوهای طراحی دیگر، MVVM به سازماندهی کد و تبدیل برنامه ها به ماژول ها کمک می کند تا توسعه، به روز رسانی و استفاده مجدد از کد را ساده تر و سریع تر کند. این الگو اغلب در ویندوز و نرم افزارهای ارائه گرافیک وب استفاده می شود.

الگوی MVVM در Windows Presentation Foundation (WPF) استفاده می شود که بر روی دات نت مایکروسافت اجرا می شود. Silverlight، پلاگین چند رسانه ای معادل اینترنت مایکروسافت WPF، همچنین از MVVMاستفاده می کند.

شکل ۱: نمایی از MVVM، توجه: پیوند بین Model و View Model، دستکاری داده ها و بین ViewModel و View، اتصال دو طرفه داده است.
شکل ۱: نمایی از MVVM، توجه: پیوند بین Model و View Model، دستکاری داده ها و بین ViewModel و View، اتصال دو طرفه داده است.


شکل ۱: نمایی از MVVM، توجه: پیوند بین Model و View Model، دستکاری داده ها و بین ViewModel و View، اتصال دو طرفه داده است.

  • توضیحات مدل:

مدل: ( کد قابل استفاده مجدد – داده ها) اشیاء تجاری که داده ها و رفتار دامنه برنامه را محصور می کنند، به سادگی داده ها را نگه می دارند.

نما: ( کد ویژه پلتفرم – رابط کاربری ) آنچه کاربر می بیند، داده های قالب بندی شده.

ویو مدل یا VIEWMODEL: (کد قابل استفاده مجدد - LOGIC) پیوند بین Model و View یا داده ها را از Model بازیابی می کند و در معرض View قرار می دهد. این مدلی است که به طور خاص برای Viewطراحی شده است.

  • امکانات:

- وضعیت چرخه عمر برنامه حفظ خواهد شد.

- برنامه در همان موقعیتی قرار می گیرد که کاربر آن را ترک کرده است.

- اجزای UI از منطق تجاری دور نگه داشته می شوند.

- منطق تجاری از عملیات پایگاه داده دور نگه داشته می شود.

آسان برای درک و خواندن. مدل، نشان دهنده داده ها و/یا اطلاعات واقعی است که ما با آن سروکار داریم. نمونه‌ای از یک مدل ممکن است یک مخاطب (شامل نام، شماره تلفن، آدرس و غیره) یا ویژگی‌های یک نقطه انتشار پخش مستقیم باشد.

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

اغلب تمیز نگه داشتن یک مدل یک چالش است. منظور من از این بازنمایی واقعی از «دنیای واقعی» است. به عنوان مثال، یک سابقه تماس ممکن است حاوی آخرین تاریخ اصلاح و هویت کاربر اصلاح کننده (اطلاعات حسابرسی) و یک شناسه منحصر به فرد (پایگاه داده یا اطلاعات پایدار) باشد. تاریخ اصلاح شده هیچ معنای واقعی برای یک تماس در دنیای واقعی ندارد، بلکه تابعی از نحوه استفاده، ردیابی و تداوم مدل در سیستم است.

  • مزایا:

قابلیت نگهداری: می تواند چابک باقی بماند و نسخه های متوالی را به سرعت منتشر کند.

توسعه پذیری: قابلیت جایگزینی یا اضافه کردن کدهای جدید را داشته باشید.

تست پذیری: نوشتن تست های واحد در برابر منطق اصلی آسان تر است.

ارتباط شفاف: مدل view یک رابط شفاف برای کنترلر Viewارائه می دهد که از آن برای پر کردن لایه viewو تعامل با لایه مدل استفاده می کند که منجر به یک ارتباط شفاف بین لایه های برنامه شما می شود.

  • معایب:

- برای رابط­های کاربری ساده، MVVM می­تواند بیش از حد باشد.

- در موارد بزرگتر، طراحی ViewModelممکن است سخت باشد.

- هنگامی که پیوندهای پیچیده داده ای داریم، اشکال زدایی کمی دشوار خواهد بود.

الگوی منبع یابی رویداد

منبع یابی رویداد یا Event Sourcing:

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

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

  • معماری منبع رویداد:

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

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

شکل ۲: جایگاه معماری  Event Sourcing  در بین سایر الگوها
شکل ۲: جایگاه معماری Event Sourcing در بین سایر الگوها


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

توجه: CQRSتوسعه یافته CQS است که یک الگوی معماری است و مخفف عبارت Command Query Separation است. CQSمفهوم اصلی است که دو نوع عملیات انجام شده در یک سیستم را تعریف می کند: فرمانی که یک وظیفه را اجرا می کند، پرس و جوی که اطلاعات را برمی گرداند، و هرگز نباید یک تابع برای انجام هر دوی این کارها وجود داشته باشد. با استفاده از CQRS، باید بین مدل نوشتن و مدل خواندن، جداسازی دقیقی داشته باشید. این دو مدل باید توسط اشیاء جداگانه پردازش شوند و از نظر مفهومی با هم مرتبط نباشند. این اشیاء ساختارهای ذخیره سازی فیزیکی نیستند، اما به عنوان مثال کنترل کننده فرمان و کنترل کننده پرس و جو هستند. آنها به مکان و نحوه ذخیره داده ها مرتبط نیستند. آنها به رفتار پردازش مرتبط هستند. کنترل کننده های فرمان مسئول کنترل دستورات، تغییر وضعیت یا انجام سایر عوارض جانبی هستند. کنترل کننده پرس و جو مسئول بازگرداندن نتیجه پرس و جو درخواست شده است.

  • مزایا:

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

سفر در زمان: همه تغییرات حالت حفظ می شوند، بنابراین می توان سیستم ها را در زمان به عقب و جلو برد که برای اشکال زدایی و تجزیه و تحلیل "چه می شود" بسیار ارزشمند است.

تحلیل علل ریشه­ای: رویدادهای تجاری را می توان به رویدادهای اصلی خود گره زد که قابلیت ردیابی و دید کل گردش کار را از ابتدا تا انتها فراهم می کند.

تحمل خطا: جریان های رویداد اساساً فقط گزارش هایی با ویژگی های پشتیبان و بازیابی قوی هستند. فقط نوشتن داده های اصلی "منبع رکورد" در جریان رویداد، بازسازی پیش بینی های پایین دست را امکان پذیر می کند. EventStoreDB یک فناوری پایگاه داده توزیع شده با failoverدر صورت شکست رهبر است.

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

ابتدا ناهمزمان: سیستم های منبع رویداد برای حداقل میزان تعامل همزمان تلاش می کنند. مرزهای سازگاری آگاهانه انتخاب می شوند تا الزامات کسب و کار برآورده شوند و هر چیز دیگری در نهایت سازگار باشد. این منجر به سیستم های پاسخگو، با کارایی بالا و مقیاس پذیر می شود.

استقلال سرویس: اگر سرویسی از کار بیفتد، سرویس‌های وابسته می‌توانند زمانی که منبع برگشت داده می‌شود، «تقویت کنند». از آنجایی که رویدادها در یک توالی در جریان ذخیره می شوند، زمانی که هر سرویس دوباره آنلاین شود، می توان همگام سازی را به دست آورد.

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

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

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

جریان داده یک طرفه: داده ها در یک سیستم CQRS/منبع رویداد از طریق مدل های مستقل برای به روز رسانی یا خواندن اطلاعات یک طرفه جریان می یابند. این یک توانایی بهبود یافته برای استدلال در مورد داده ها و اشکال زدایی را به ارمغان می آورد زیرا هر جزء در جریان داده یک مسئولیت واحد دارد.

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

منابع:

[1] https://airbrake.io/blog/software-design/domain-driven-design

[2] https://docs.microsoft.com/en-us/azure/architecture/patterns/event-sourcing

[3] https://www.eventstore.com/event-sourcing

[4] https://whatis.techtarget.com/definition/Model-View-ViewModel

[5] https://www.wintellect.com/model-view-viewmodel-mvvm-explained/

[6] https://www.geeksforgeeks.org/introduction-to-model-view-view-model-mvvm/


«این مطلب، بخشی از تمرینهای درس معماری نرم‌افزار در دانشگاه شهیدبهشتی است»

dddmvvmevent sourcingcqrsمعماری_نرم_افزار_بهشتی
شاید از این پست‌ها خوشتان بیاید