<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های gamenikocraft</title><link>https://virgool.ir/feed/@gamenikocraft</link><description></description><language>fa</language><pubDate>2026-11-11 13:49:03</pubDate><image><url>https://virgool.ir/images/default-avatar.jpg</url><title>gamenikocraft</title><link>https://virgool.ir/@gamenikocraft</link></image><item><title>از شیء تا داده: بررسی جامع معماری های نرم افزاری در یونیتی و گذار به طراحی داده محور</title><link>https://virgool.ir/@gamenikocraft/از-شیء-تا-داده-بررسی-جامع-معماری-های-نرم-افزاری-در-یونیتی-و-گذار-به-طراحی-داده-محور-w0pwdpjtfdml</link><description>۱) مقدمه: چرا کد تمیز در مقیاس بالا کافی نیستکمابیش هر مهندسی که با سیستم های تعاملی سنگین کار کرده، آن لحظه را به یاد دارد: سیستمی می نویسی که از هر نظر تمیز است، کلاس ها سر جای خودشان اند، سلسله مراتب وراثت منطقی است، مسئولیت ها به درستی تفکیک شده اند، و روی چند صد موجودیت مثل ساعت کار می کند. اما همین که مقیاس را چند برابر می کنی ،از صدها به ده ها هزار موجودیت ،نرخ فریم فرومی ریزد. نکته ی گیج کننده این است که پردازنده بیکار به نظر می رسد، اما خروجی کند است. این مقاله دقیقا به همین معما می پردازد و نشان می دهد که ریشه ی مشکل نه در بد بودن شیءگرایی، بلکه در ناسازگاری ذاتی چیدمان حافظه ی آن با معماری پردازنده های مدرن است.من در این مقاله پنج معماری رایج در موتور یونیتی را کنار هم گذاشتم: شیءگرایی (OOP)، معماری موجودیت مولفه سیستم (ECS)، پشته ی فناوری داده محور یونیتی (DOTS)، طراحی داده محور مبتنی بر (SODD) ScriptableObject  و معماری مولفه محور (Component-Based). محور روایت، گذار از پارادایم شیءگرایی به طراحی داده محور (Data-Oriented Design) است، گذاری که به تعبیر منابع، پیامدهای واقعی عظیمی بر کارایی دارد، چون محور طراحی را از شیء به چیدمان داده در حافظه جابه جا می کند. تمام تحلیل، ارزیابی و اعداد این نوشته بر پایه ی شواهد مستند منابع بنا شده اند و با الهام از مفاهیم پایه ای در چارچوب ارزیابی معماری ATAM سازمان یافته اند.۲) شیءگرایی و بن بست های آن در مقیاس بالا۲.۱ کپسوله سازی و بهای پنهان آنشیءگرایی بر اصولی مانند کپسوله سازی، وراثت، چندریختی و رابط ها استوار است و سطح انتزاع بالایی به توسعه دهنده می دهد. در یونیتی کلاسیک، هر موجودیت به صورت یک MonoBehaviour مدل می شود که داده و رفتار را با هم درون خود baked می کند، برای مثال یک کلاس LandTile با فیلدهای x، y، isOccupied و isActive و متدهایی که منطق را در همان شیء نگه می دارند. این مدل برای فهم انسان بسیار طبیعی است و ماژولاریتی شهودی می دهد، اما همین هم مکانی داده و رفتار در مقیاس بالا به یک بدهی کارایی تبدیل می شود.۲.۲ ریشه ی مشکل: Cache Miss، حافظه ی پراکنده و تقابل Stack/Heapدر شیءگرایی، هر شیء به صورت مستقل روی Heap تخصیص داده می شود، حافظه به دو ناحیه تقسیم می شود: Stack (ترتیبی، LIFO، برای متغیرهای موقت و آرگومان ها) و Heap (تخصیص پویا و غیرترتیبی در زمان اجرا). آبجکت هایی که پشت سرهم ساخته می شوند می توانند در آدرس های کاملا متفاوت حافظه بیفتند. در یونیتی این وضعیت حادتر است: هر GameObject در واقع یک آبجکت سنگین ++C است که یک پوسته ی #C به آن اشاره می کند و هر دو می توانند هرجای حافظه باشند.وقتی پردازنده فقط یک عدد می خواهد اما کل شیء را از حافظه می کشد.پیامد مهندسی این پراکندگی روشن است : وقتی پردازنده فقط به یک عدد از یک شیء نیاز دارد، کل آن شیء از حافظه واکشی می شود، این کار کش را آلوده می کند (Cache Pollution)، نرخ خطای کش (Cache Miss) را بالا می برد و مانع بهره گیری از دستورات برداری SIMD می شود. منابع این وضعیت را با عبارت گویای Cache misses galore ،یعنی سیل خطاهای کش ،توصیف می کنند. بدتر آنکه دسترسی تصادفی به حافظه باعث می شود نرخ این خطاها با تعداد موجودیت ها به صورت خطی رشد کند و در نهایت به یک فروپاشی کاملا محسوس منجر شود.۲.۳ فروپاشی غیرخطی: یک امضای معماری، نه یک تصادفیکی از یافته های کلیدی این است که افت کارایی OOP خطی نیست، بلکه شتاب دار است. در یکی از منابع، هزینه ی هر گام از افزایش تعداد موجودیت ها به روشنی ثبت شده است: در بازه ی ۱۵۰۰ به ۲۰۰۰ موجودیت تنها حدود ۱۰ میلی ثانیه به زمان اضافه می شود، اما در بازه ی ۲۵۰۰ به ۳۰۰۰ این افزایش به حدود ۳۲ میلی ثانیه می رسد. این رفتار غیرخطی نشان می دهد که محدودیت های OOP معماری اند، نه اتفاقی، یعنی با بهینه سازی های خرد قابل رفع نیستند و رفعشان نیازمند تغییر خود معماری است.افت کارایی OOP خطی نیست، شتاب دار است.۲.۴ هم روندی در شیءگرایی: دشواری ذاتیموازی سازی در OOP دشوار است: دو نخ نمی توانند بدون سربار روی یک آبجکت کار کنند، چون خطر Race Condition و تغییر غیرهمگام داده وجود دارد و هر نخ باید بداند نخ دیگری روی همان آبجکت کار می کند یا نه. در یونیتی کلاسیک، ساخت یا حذف Component نیازمند mutex lock روی فهرست سراسری id→pointer است. منابع تاکید می کنند که موتور اصلی یونیتی روی main thread اجرا می شود و اغلب توابع API آن thread-safe نیستند ، بنابراین Coroutine ها هم روندی ارائه می دهند نه موازی سازی و صرفا شبیه نخ هایی با قابلیت توقف / انتظارند. راهکار عملی OOP این است که الگوریتم های سنگین (مانند یافتن دشمنان در فاصله ی مشخص) به sub-thread ها منتقل شوند تا نرخ فریم افت نکند، در حالی که فراخوانی های API یونیتی روی main thread باقی می مانند، برای Singletonها نیز از قفل و double-checked locking استفاده می شود.۲.۵ الگوهای ترمیمی کارایی در OOPجامعه ی شیءگرا برای مقابله با این محدودیت ها الگوهای مشخصی ساخته است: الگوی Object Pool برای کنترل تخصیص حافظه و جلوگیری از بار Garbage Collector (که استخر را روی یک ساختمان داده ی Stack پیاده می کند و نسخه ی LinkedPool فقط به اشیای ذخیره شده حافظه تخصیص می دهد)، الگوی Dirty Flag برای پرهیز از محاسبه ی مجدد، و Spatial Partition برای دسترسی فضایی. حتی خود Data Locality در این ادبیات به عنوان یک الگوی بهینه سازی معرفی می شود ،یعنی جامعه ی OOP هم به اهمیت چیدمان حافظه واقف است، اما آن را به جای یک اصل معماری، به صورت یک وصله ی موضعی به کار می گیرد.۳) معماری ECS و DOTS : طراحی حول داده۳.۱ سه گانه ی Entity، Component، SystemECS یک الگوی معماری مبتنی بر ترکیب به جای وراثت (Composition over Inheritance) است که شیء را به سه بخش می شکند. موجودیت (Entity) دیگر یک شیء سنگین نیست، صرفا یک شناسه ی سبک 64 بیتی (شامل یک ایندکس و یک ورژن) است که هیچ داده یا رفتاری در خود ذخیره نمی کند. مولفه (Component) داده ی خالص است، یک struct ساده مانند TilePosition{int2}، TileOccupied{bool} یا NeedsUpdating که فقط حالت را نگه می دارد. سیستم (System) منطق است، کدی که روی مجموعه ای از موجودیت های Query شده اجرا می شود. یک EntityManager موجودیت ها را دنبال می کند و کوئری ها اغلب با توابع lambda نوشته می شوند. این تفکیک، درخت وراثت صلب را حذف می کند و انعطاف ترکیبی می دهد.ترکیب به جای وراثت: موجودیت فقط یک شناسه است.۳.۲ قلب کارایی: Archetype، Chunk و تقابل AoS با SoAکلید برتری کارایی ECS در چیدمان حافظه است. موتور، همه ی موجودیت هایی را که مجموعه ی دقیقا یکسانی از مولفه ها دارند در یک Archetype گروه بندی می کند. حافظه در بلوک های پیوسته ای به نام Chunk (هرکدام حدود ۱۶ کیلوبایت) تخصیص می یابد و هر Chunk فقط داده ی یک Archetype را در خود دارد. حالا پیمایش سیستم به یک حلقه ی خطی روی حافظه ی فشرده تبدیل می شود، یک بار خواندن cache-line تقریبا ۸ تا ۱۶ موجودیت هم نوع را با هم بارگذاری می کند و Cache Miss به حداقل می رسد.اما یک لایه ی معماری ظریف تر هم وجود دارد که اغلب زیر برچسب کلی ECS پنهان می ماند: تفاوت مدل AoS (آرایه ای از struct ها) با SoA (structی از آرایه ها). منابع تاکید می کنند که صرف جداسازی داده از منطق کافی نیست، این چیدمان داده ی زیرین است که عامل واقعی کارایی است. SoA داده های هم نوع را پیوسته می چیند، امکان دستورات SIMD و خواندن موازی آرایه ها را فراهم می کند و پایداری فریم بهتری می دهد، به طوری که در یک اندازه گیری، SoA در برابر AoS به ۶۵.۸۱ در برابر ۶۱.۵۱ فریم بر ثانیه رسید. archetype ها به صورت جدول ستونی (columnar) با دسترسی O(1) به مولفه پیاده می شوند.قلب کارایی ECS: داده ها در Chunk های پیوسته کنار هم می نشینند.۳.۳ Burst و SIMD : از داده ی مرتب تا کد ماشین بهینهچون داده در ECS مرتب و پیوسته است، کامپایلر Burst می تواند کد #C را به دستورات بومی SIMD ترجمه کند و کد ماشین را دقیقا برای پردازنده ی دستگاه هدف تولید کند. این همان چیزی است که DOTS را به پیاده سازی صنعتی ECS تبدیل می کند. البته Burst قیودی دارد: فقط با انواع blittable کار می کند و برخی safety check ها را حذف می کند. تاثیر آن اما چشمگیر است و در بخش بنچمارک ها با عدد نشان داده خواهد شد.داده ی مرتب، پیش شرط کد ماشین برداری است.۳.۴ موازی سازی: Job System، Command Buffer و Sync PointDOTS دو سطح موازی سازی ارائه می دهد: Data Parallelism (تقسیم موجودیت های یک سیستم میان چند نخ) و Task Parallelism (اجرای هم زمان چند سیستم مستقل). Job System کد چندنخی #C را ممکن می کند و از worker thread ها (هر هسته ی منطقی یک worker) برای پرهیز از Context Switching استفاده می کند، برای پرهیز از Race Condition به جای ارجاع ، کپی داده را به هر Job می دهد. با اعلان ایستای ReadOnly / ReadWrite روی داده، زمان بندی Job ها بهینه تر می شود (Job هایی که فقط می خوانند منتظر هم نمی مانند).تغییرات ساختاری (ساخت / حذف موجودیت یا مولفه) نمی توانند وسط پیمایش موازی رخ دهند، این تغییرات به صورت معوق (deferred) در یک Command Buffer انباشته و در Sync Point ها روی نخ اصلی اعمال می شوند. توصیه ی معماری این است که تعداد Sync Point ها کمینه بماند. در عمل، پیمایش ها بسته به تعداد هسته های پردازنده ی دستگاه هدف (مثلا بین ۶ تا ۷ نخ در یک پردازنده ی ۸ هسته ای) تقسیم می شوند و کارهایی که فقط روی نخ اصلی ممکن اند (مانند تغییر Texture) در Sync Point سفارشی انجام می گیرند.موازی سازی امن : تغییرات ساختاری در صف می مانند تا نقطه ی همگام سازی.۳.۵ واقعیت مدل هیبریدی و فرآیند bakingنکته ی مهم استقرار این است که ECS خالص همیشه ممکن نیست. برخی اجزا مانند دوربین ها، منابع نور و بعضی اسکریپت ها قابل تبدیل به entity نیستند و باید با GameObject / MonoBehaviour پیاده شوند، به همین دلیل اکثر پروژه های Unity ECS در عمل ماهیت شیءگرا هم دارند (رویکرد Hybrid / Companion GameObject). این هم زیستی اجباری، خود منبع پیچیدگی و کاپلینگ معماری است. از سوی دیگر، مدل هیبریدی یک مزیت استراتژیک دارد: نگه داشتن لایه ی UI GameObject و انتقال منطق پرتکرار به ECS ، مهاجرت کامل را لازم نمی کند و مانع پذیرش را پایین می آورد. الزامات ساختاری DOTS شامل نصب پکیج های Entities/Burst/Jobs و Hybrid Renderer + URP، پیاده سازی سیستم ها با SystemBase و مولفه ها با IComponentData، و فرآیند baking برای تبدیل GameObject به Entity است. (البته باید توجه داشت که در نسخه های جدید و ۱.۰ به بعد یونیتی، ساختار ISystem جایگزین SystemBase شده است تا کارایی بهتری ارائه دهد، اما اصول معماری ثابت مانده است).۴) معماری SODD : داده به مثابه ی شهروند درجه یکاگر ECS پاسخ مسئله ی کارایی است، SODD (طراحی داده محور مبتنی بر ScriptableObject) پاسخ مسئله ای متفاوت است: کاپلینگ و مدیریت حالت. بسیاری از دردهای واقعی تیم ها ربطی به سرعت خام ندارند، مشکل این است که یک تغییر کوچک در یک صحنه، ده جای دیگر را می شکند. SODD این گره را هدف می گیرد.۴.۱ فلسفه : جداسازی چرخه ی حیات داده از صحنهایده ی محوری SODD این است که داده را به یک شهروند درجه یک ارتقا دهد: روند ScriptableObject چرخه ی حیات داده را از چرخه ی حیات شیء و صحنه جدا می کند و داده را به یک asset مستقل، سریالایزپذیر و قابل تزریق تبدیل می کند. نمونه های ساخته شده در Editor سریالایز و به صورت asset ذخیره می شوند و در زمان اجرا دی سریالایز و در RAM بارگذاری می گردند. از منظر نظری، این همان ایده ی Flyweight/حالت مشترک است که در سطح asset پیاده می شود: داده ی مشترک، مستقل از هر instance.۴.۲ بلوک های سازنده: Variable، Event، RuntimeSet و ManagerSODD بر چند بلوک پایه استوار است. Scriptable Variable ها ظرف های ماژولار برای یک مقدار (مثل int/float/string) هستند که بین سیستم ها به اشتراک گذاشته می شوند تا سیستم ها برای خواندن/نوشتن state به هم وابسته نباشند. Scriptable Event ها کانال های رویداد مبتنی بر ScriptableObject با API به سبک Observer هستند: AddListener، RemoveListener و Invoke ،هم نام با UnityEvent و delegate های #C. سیستم ها به این رویدادها گوش می دهند و کاملا از یکدیگر Decouple می شوند، برای نمونه، Control Scheme Handler ها تغییر طرح کنترل را پایش و Scriptable Event متناظر را Trigger می کنند. در کنار اینها، RuntimeSet (معادل Collection) و GameEvent و Manager هایی به صورت ScriptableObject (مانند GameManager با SetTimeScale/LoadScene/Quit و ScoreManager با ارجاع به Variable&lt;int&gt; score) قرار دارند و سیستم های UI با Subscribe به تغییر Variable به روزرسانی می شوند.داده به عنوان شهروند درجه یک: ScriptableObject به جای Singleton.۴.۳ جایگزینی Singleton و مدیریت حالتSODD به طور مشخص الگوی Singleton را نقد می کند : اتصال سخت (tight coupling) ، مدیریت حالت سراسری با عوارض جانبی بین صحنه ها، دشواری دیباگ و تست، و ناسازگاری با Editor. Singleton یکی از بحث برانگیزترین الگوها / گاه ضدالگو توصیف می شود که مزایایی مانند دسترسی آسان و پایداری بین صحنه ها دارد اما وابستگی های پنهان و حالت سراسری تغییرپذیر می سازد. راه حل SODD جایگزینی آن با ScriptableObject Manager هاست تا حالت مشترک به شکل قابل کنترل و مستقل از صحنه مدیریت شود.۴.۴ مرزها و محدودیت ها: بهایی که SODD می گیردمهندس خوب مرزها را می شناسد. سریالایزر پیش فرض یونیتی قادر به سریالایز رابط ها و کلاس های abstract نیست و SODD را به افزونه ی Odin وابسته می کند، پایداری داده در حالت Build آن طور که انتظار می رود کار نمی کند، callback های ScriptableObject غیرقابل اتکا توصیف شده اند، و یک شکاف واقعی در مستندسازی و اتکاپذیری وجود دارد. مسائل عملی دیگری هم هست: ترتیب callback های MonoBehaviour قطعی است اما ترتیب بین MonoBehaviour ها نیست و باید با Script Execution Order یک مقداردهی مرکزی تنظیم شود، برای پایداری بین صحنه ها از DontDestroyOnLoad استفاده می شود و تفاوت رفتار Build mode و Play mode باید مدیریت گردد. به گفته ی منبع، این معماری در حدود یک ماه ساخته شد و به آموزش و راهنمایی نیاز دارد. پس SODD ابزار انعطاف و مدیریت حالت است، نه لزوما ابزار کارایی خام.۵) معماری مولفه محور (Component-Based) : ترکیب به جای وراثتمعماری مولفه محور در یونیتی دو چهره دارد. چهره ی اول همان مدل GameObject-Component است: افزودن Component ها به یک GameObject طبیعی و ماندگار است، اما چون پیاده سازی آن شیءگراست، به همان پراکندگی داده در حافظه و Cache Miss منجر می شود، در رویکرد سنتی، آبجکت مالک داده های خودش است (مثلا player مالک velocity/position). الگوی افزودن Component، Composition over Inheritance را تشویق می کند و سلسله مراتب را مسطح تر می کند، اما عیبی هم دارد: گاهی لازم است همان قابلیت چندبار نوشته شود.چهره ی دوم، معماری مولفه محور اصیل تری است که در منابعی مثل RCSA / RAGE توصیف شده و تمرکزش بر بازاستفاده پذیری و انتقال پذیری است. در این مدل، مولفه ها به صورت جعبه ی سیاه (black box) با رابط ها و لایه بندی مشخص تعریف می شوند و از طریق Publish/Subscribe (پیام رسانی یک به چند و یک طرفه با Topic/Channel) با هم حرف می زنند. برخلاف Observer که در آن باید در خود منبع مشترک شوی، Publish/Subscribe منشا اعلان را Decouple می کند و مانند یک message router عمل می کند (پیاده سازی Broadcast Messaging نمونه ی همین ایده است). تمرکز صریح این معماری بر Portability است : مانع اصلی بازاستفاده، تنوع زبان ها/موتورها/سیستم عامل ها/پلتفرم های هدف است و این معماری برای انتقال پذیری مولفه ها بین محیط های فنی مختلف طراحی شده. جالب آنکه Data Locality هم در همین ادبیات به عنوان یک الگوی بهینه سازی برای بیشینه کردن استفاده از کش CPU فهرست شده است.دو چهره ی معماری مولفه محور در یونیتی.۶) مقایسه ی فنی معماری ها: حافظه، هم روندی و رویدادجدول زیر تفاوت های بنیادین چهار محور معماری را در مدیریت حافظه، هم روندی و مدیریت رویداد جمع بندی می کند. این تفاوت ها مبنای همه ی ترید آف هایی هستند که در بخش های بعد تحلیل می شوند.جدول ۱ ،مدیریت و چیدمان داده در حافظه (Stack/Heap و Data Locality)جدول ۲ ،مدیریت هم روندی (Concurrency)جدول ۳ ،ارتباطات و مدیریت رویداد (Sync در برابر Async)۷) سناریوهای کارایی و بنچمارک هادر این بخش، اعداد مستند منابع را با ذکر شرایط محیطی مرور می کنیم. تاکید می کنیم که این اعداد در شرایط آزمونی مشخص به دست آمده اند و باید در همان بستر تفسیر شوند، همین دقت، تفاوت یک تحلیل مهندسی با یک ادعای تبلیغاتی است.۷.۱ آزمون بنیادین: Conway&#39;s Game of Life روی یک میلیون سلولشفاف ترین نمایش قدرت داده محوری در آزمون MY.GAMES دیده می شود. یک گام از الگوریتم Conway روی میدان ۱۰۰۰×۱۰۰۰ (یعنی ۱٬۰۰۰٬۰۰۰ سلول) روی پردازنده ی Intel Core i9-10900 (۱۰ هسته/۲۰ نخ) اجرا شد:• پیاده سازی سنتی تک نخی (متد SimulateStep) : حدود ۳۸۰ میلی ثانیه (دقیقا ۳۸۱.۳۲ms در Profiler).• با C# Job System (توزیع کار میان ۱۷ worker): حدود ۴۲ میلی ثانیه - تقریبا ۹ برابر سریع تر از حالت تک نخی.• با Job System + Burst : کمتر یا مساوی ۲ میلی ثانیه - تقریبا ۱۹۰ برابر نسبت به نتیجه ی اولیه.این توالی نشان می دهد که موازی سازی و کامپایل بومی، وقتی روی داده ی درست چیده شده اعمال شوند، بهبود را از مرتبه ی چند برابر به مرتبه ی صدها برابر می رسانند.از ۳۸۰ میلی ثانیه تا رسیدن به مرز ۲ میلی ثانیه.۷.۲ به روزرسانی وضعیت تایل ها: ۰٫۳۷ در برابر ۱٫۶۸ میلی ثانیهدر سناریوی به روزرسانی وضعیت اشغال ۲۵۰٬۰۰۰ تایل در هر فریم روی گرید ۵۰۰×۵۰۰ (اجرا داخل Unity Editor روی PC ویندوز، هر تست ۱۰ بار و میانگین گیری، فریم اول کنار گذاشته شد)، آرتیفکت مقایسه TileOccupationSystem (ECS/SystemBase) در برابر کلاس TileOccupation (MonoBehaviour) بود. ECS پیمایش را بین ۶ تا ۷ worker thread تقسیم می کند و Main Thread فقط Command Buffer را می سازد و اجرا می کند. نتیجه: نسخه ی MonoBehaviour به طور میانگین ۱.۶۸ میلی ثانیه (کمینه ۱.۴۹، بیشینه ۲.۷۴) و نسخه ی ECS تنها ۰.۳۷ میلی ثانیه (نخ اصلی ۰.۱۳، Jobها ۰.۲۴) طول کشید ،یعنی حدود ۴.۵ برابر سریع تر.۷.۳ درس صادقانه: وقتی ECS کندتر می شود (تعامل با Texture)در سناریوی رندر / به روزرسانی نقشه، ECS مجبور بود علاوه بر Command Buffer، داده ی رنگ را از یک Texture2D بگیرد، کپی و اعمال کند ،یعنی از دنیای داده محور بیرون بزند و با یک Unity Object تعامل کند. اینجا نتیجه معکوس شد: ECS ۱.۷۱ میلی ثانیه (نخ اصلی ۱.۶۸، Jobها ۰٫۰۳۳) در برابر MonoBehaviour ۱.۰۶ میلی ثانیه. حذف تغییر Texture، زمان نخ اصلی ECS را به طور مداوم ۱.۳۰ میلی ثانیه کوتاه کرد. در مجموع (رندر + منطق) ECS ۲.۰۸ در برابر OOP ۲.۷۴ میلی ثانیه بود. درس معماری روشن است: سربار تعامل با آبجکت های سنگین سنتی روی نخ اصلی برمی گردد و باید در طراحی لحاظ شود.۷.۴ زمان های per-frame سیستم ها و بهره وری Chunkدر یک پروژه ی Unity ECS زمان های هر سیستم در هر فریم از پنل Debugger ثبت شد: aircraftSystem = ۰.۵۳، RenderMeshSystemV2 = ۱.۰۰، EndFrameTRSToLocalToWorldSystem = ۰٫۰۹، ExportPhysicsWorld =۰.۰۷، RenderBoundsUpdateSystem = ۰.۰۷ و چند سیستم سبک تر (میلی ثانیه در هر فریم). همچنین بهره وری Chunk گزارش شده ۹۵ و ۵۰ بود و موجودیت پیش فرض WorldTime مقادیر ElapsedTime و DeltaTime را نگه می داشت. این داده ها نشان می دهند که در ECS، رندر (RenderMeshSystemV2) اغلب سنگین ترین سیستم است، نه منطق شبیه سازی.۷.۵ مقیاس پذیری: ۱۳×، ۹×، ۳× ،و یک استثناء مهمپژوهش های مرجع، تصویری قدرتمند اما نه یک طرفه از مقیاس پذیری داده محوری می دهند: Männistö گزارش می کند DOTS تا ۳ برابر بهتر است، Näykki نشان می دهد ECS موازی ۱۳ برابر واحد بیشتر روی صفحه نگه می دارد و کد Burst به طور میانگین بیش از ۲ برابر کارایی می دهد، اما در بخش Animation رویکرد OOP ۳٫۵ برابر سریع تر از DOTS است، Borufka گزارش می کند ترکیب ECS + Job System + Burst ۹ برابر بهتر از MonoBehaviour کار می کند. برتری موازی سازی مشروط به تعداد بالای موجودیت است، در نمونه ی شبیه ساز پرواز با تنها یک موجودیت، مزیت بهره وری سخت افزار اصلا محقق نشد.شتاب واقعی، اما نه یک طرفه.۷.۶ آزمون میدانی: شبیه سازی Life Below در Late-Gameیک نمونه ی واقعی از پایداری در بار سنگین، شبیه سازی اکوسیستم بازی Life Below است: یک سیو ۱۴ساعته با ۱۵.۰۰۰ موجودیت و بیش از ۴۵۰ سیستم فعال، در حالتی که Time Acceleration باعث می شود fixed update چندبار در هر فریم اجرا شود. با وجود این بار، شبیه سازی روان اجرا می شد: ۶۰ فریم بر ثانیه و تقریبا ۰.۵ میلی ثانیه زمان CPU در هر فریم برای شبیه سازی. نکته ی تعیین کننده: غیرفعال کردن Burst باعث شد شبیه سازی بیش از ۳ برابر طولانی تر شود ،شاهدی مستقیم بر نقش Burst در پایداری سیستم های بزرگ.۷.۷ جابه جایی گلوگاه و مسئله ی رویدادها (Garbage)دو یافته ی ظریف اما مهم را هم باید افزود. نخست، بهبود معماری CPU لزوما کل سیستم را سریع نمی کند، در ECS چندنخی، گلوگاه اغلب به GPU منتقل می شود (Gfx.WaitForPresent بین ۸ تا ۲۰ برابر زمان رندر). درس معماری: بهینه سازی یک بعد، بعد محدودکننده ی بعدی را آشکار می کند. دوم، در مقایسه ی UnityEvent با C# event (الگوی Observer)، رویدادهای UnityEvent دست کم 2 برابر کندتر هستند. رویدادهای #C هنگام فراخوانی (Invoke) هیچ زباله ای تولید نمی کنند، اما عمل ثبت نام و لغو ثبت نام (Subscribe/Unsubscribe) به خصوص هنگام استفاده از توابع بی نام (Lambda)، باعث تخصیص حافظه و تولید نمایی زباله می شود.۸) ارزیابی معماری و ترید آف ها در چارچوب ATAMبرای ارزیابی روشمند، از واژگان کتاب Bass و مفاهیم کلیدی روش ATAM استفاده می کنیم (هرچند به دلیل محدودیت فضا، تمام فازهای رسمی مانند درخت مطلوبیت پیاده سازی نشده اند). نقطه ی حساسیت (Sensitivity Point) تصمیمی معماری است که اثری مشخص بر پاسخ یک ویژگی کیفی دارد، ترید آف (Trade-off) تصمیمی است که چند ویژگی کیفی به آن حساس اند و بهبود یکی به تضعیف دیگری می انجامد، و ریسک (Risk) تصمیمی مخاطره آمیز است.۸.۱ نقاط حساس و ریسک ها• چیدمان حافظه (Chunk پیوسته در برابر Heap پراکنده) یک نقطه ی حساس بحرانی است: کارایی مستقیما به data locality و اندازه ی کش CPU وابسته است و در OOP نرخ Cache Miss با تعداد موجودیت خطی رشد می کند و فروپاشی غیرخطی می سازد.• انتخاب مدل چیدمان ECS (AoS در برابر SoA) نقطه ی حساس است: AoS هنگام iteration الگوی دسترسی تکه تکه دارد، SoA امکان SIMD و پایداری فریم بهتر می دهد (۶۵.۸۱ در برابر ۶۱.۵۱ FPS).• رویداد immediate در سیستم موازی یک ریسک Race Condition است: مثلا در CollisionSystem نابودی فوری گلوله لازم است، اما اجرای موازی آن به دلیل تغییر هم زمان جدول archetype ناامن است.• عدم اعمال به موقع رویداد staged یک ریسک Residual Conflict است: اگر رندر پیش از اعمال رویداد Destroy اجرا شود، موجودیت نابودشده رندر می شود، راهکار، sync barrier است.• چندنخی CPU در ECS یک نقطه ی حساس است که گلوگاه را به GPU منتقل می کند (Gfx.WaitForPresent بین ۸ تا ۲۰ برابر رندر).۸.۲ منحنی یادگیری و هزینه ی پیاده سازیپذیرش معماری داده محور رایگان نیست. الزامات ساختاری DOTS (نصب پکیج های Entities/Burst/Jobs و Hybrid Renderer + URP، پیاده سازی با SystemBase و IComponentData، و فرآیند baking) به همراه boilerplate و تغییر ذهنیت، مانعی جدی است که در منابع حل نشده توصیف شده. محدودیت های زمان بندی نخ نیز وجود دارد: تغییرات ساختاری فقط روی نخ اصلی (WithoutBurst.Run) و زمان بندی پویا باید هر بار از نظر ایمنی بازبینی شود. در سمت SODD، معماری در حدود یک ماه ساخته شد و به دانش سریالایزیشن و ScriptableObject و افزونه ی Odin نیاز دارد. در مقابل، رویکردهایی مانند HECATE با نگاشت مفاهیم به ECS، منحنی یادگیری را از Steep به Moderate کاهش می دهند، حتی توسعه دهنده ی ناآشنا با ECS توانست با مطالعه ی فهرست System ها منطق را دنبال کند، هرچند معکوس شدن کنترل (inversion of control) در ECS پیچیدگی می افزاید.۸.۳ ترید آف ها: چه چیزی فدای چه چیزی شد؟جدول زیر جان کلام ارزیابی معماری است، اینکه هر تصمیم چه چیزی به دست آورد و چه چیزی را فدا کرد.هر تصمیم معماری، چیزی را فدای چیز دیگری می کند.نکته ی مهم Bass این است که تاکتیک روی یک ویژگی کیفی واحد تمرکز دارد و درون تاکتیک ترید آف دیده نمی شود، اما در الگوهای معماری، ترید آف ها در خود الگو تعبیه شده اند. همچنین یافته ی Phalanx یادآوری می کند که مزیت ECS اغلب در Modifiability/Maintainability است نه لزوما سرعت خام، در Phalanx سرعت شبیه سازی تقریبا هم سطح سایر شبیه سازها ماند و اصول ECS حتی پیاده سازی پرمحاسبه ای را تحمیل کردند.۹) همگرایی با مهندسی سیستم های توزیع شده: درس HECATEیکی از جالب ترین یافته های این پژوهش این است که ECS/DOD صرفا یک ترفند کارایی بازی نیست، بلکه چارچوبی برای واردکردن مفاهیم مهندسی سیستم های توزیع شده به دامنه ای است که پیش تر تک پارچه بود. معماری HECATE نمونه ی شاخص این همگرایی است.۹.۱ ساختار لایه ای و نقش FacadeHECATE یک معماری لایه ای سه گانه دارد: Agent Abstraction Layer → ECS Core Layer → Infrastructure Layer، با اجتناب عمدی از کاپلینگ محکم بین لایه ها. عناصر آن همان سه گانه ی ECS است ،Entity (شناسه ی سبک)، Component (ظرف داده ی خالص) و System (پردازشگر منطق) ،به همراه مجموعه ای از Manager ها (Entity/Component/System/Event Manager) و یک Engine برای ارکستراسیون. مهم آنکه HECATE به عنوان یک Facade عمل می کند و پیچیدگی ECS را پنهان می کند، همچنین جداول نگاشت رسمی TAO→ECS ارائه می دهد تا انتزاعات مفهومی عامل ها به عناصر ECS نگاشته شوند و معنا حفظ گردد.۹.۲ چرا این همگرایی مهم است؟ارتباط رویداد-محور ECS ستون فقرات تعامل بدون کاپلینگ محکم است و از دو گونه رویداد پشتیبانی می کند: Immediate Events (بلافاصله) و Queued Events (به صف افزوده و در چرخه ی بعدی پردازش می شوند)، Event Manager رجیستری شنونده ها را نگه می دارد و رخدادها را dispatch می کند. همین ساختار است که پلی به مفاهیم توزیع شده می زند: بروکر پیام، مدل سرور/کلاینت و مقیاس پذیری افقی. به بیان دیگر، وقتی داده از رفتار جدا و ارتباط رویداد-محور شد، وارد کردن الگوهای سیستم های توزیع شده به موتور بازی طبیعی تر می شود. این هم راستا با کاربردهای فراتر از بازی ECS است: استفاده در co-simulation توزیع شده (Vico) و شبیه سازی GPU-محور یادگیری تقویتی (Madrona با رویکرد megakernel) نشان می دهد ECS یک الگوی عام معماری داده محور است، نه صرفا یک موتور بازی.۹.۳ چالش های بازاین همگرایی هنوز کامل نیست. در HECATE، عملیات توزیع شده ی چندگره ای هنوز حل نشده است، تایید صوری (formal verification) وجود ندارد، انطباق با استاندارد FIPA-ACL برقرار نیست، و استدلال هنجاری پیچیده غایب است. در سطح کلان تر نیز منابع به فقدان معماری های عام و بازاستفاده پذیر فراپروژه ای اشاره می کنند: راه حل ها اغلب game-/genre-/technology-specific می مانند و طراحی داده محور هنوز فقط سطحی مطالعه شده است. همچنین نبود صورت بندی رسمی برای معنای archetype در فریم ورک ها، استدلال درباره ی تعیین پذیری و جهش ساختاری را دشوار می کند.۱۰) نتیجه گیریاین بررسی تطبیقی چند درس معماری روشن به دست می دهد. نخست، در مقیاس بالا دشمن کارایی الگوریتم نیست، چیدمان حافظه است، باید داده را برای پردازنده چید نه برای ذهن انسان، و همین است که چیدمان حافظه را از یک جزئیات پیاده سازی به یک نگرانی درجه یک معماری ارتقا می دهد. دوم، ECS و DOTS با محلی سازی داده، Burst و موازی سازی، دیوار کارایی شیءگرایی را می شکنند و اعداد ،از ۳۸۱ میلی ثانیه تا ۲ میلی ثانیه در آزمون Conway، و ۱،۶۸ در برابر ۰،۳۷ میلی ثانیه در به روزرسانی تایل ها ،این را تایید می کنند. سوم، SODD مسئله ی متفاوتی را حل می کند: انعطاف، جداسازی و مدیریت داده ی مستقل از صحنه، ابزار کاهش کاپلینگ، نه موتور کارایی خام. چهارم، معماری مولفه محور میان طبیعی بودن برای انسان و بازاستفاده پذیری Portability تعادل برقرار می کند.اما مهم ترین درس، پیام مرکزی ATAM است: هیچ معماری ای مطلقا برنده نیست. هر تصمیم یک ترید آف است ،ECS سریع در تعامل با Texture کند می شود، بهبود CPU گلوگاه را به GPU می برد، و رویکرد شیءگرا در انیمیشن ۳.۵ برابر جلو می زند. کار ما به عنوان معمار، نه تعصب به یک پارادایم، بلکه شناخت این تعادل ها و انتخاب آگاهانه ی معماری متناسب با ویژگی های کیفی واقعی هر پروژه است. گذار از OOP به DOD نه یک جایگزینی کامل، بلکه یک همگرایی پراگماتیک (Hybrid) است: نگه داشتن آنچه OOP خوب انجام می دهد و سپردن بار سنگین داده به معماری داده محور.هیچ معماری ای مطلقا بهتر نیست، انتخاب، تابع بافت مسئله است.این مطلب، بخشی از تمرین های درس معماری نرم افزار در دانشگاه شهیدبهشتی استمنابع کلیدی بررسی شده• Ylikoski ،پژوهش بنچمارک ECS در برابر MonoBehaviour در یونیتی، منبع اعداد به روزرسانی تایل/رندر و زمان های per-frame• MY.GAMES / Ocean Hero ،گزارش صنعتی ECS روی موبایل، بنچمارک Conway (Conway/Job/Burst) و محرک های سخت افزاری معماری داده محور.• The Essence of ECS ،مبانی مدل حافظه، Archetype/Chunk، AoS در برابر SoA، ایمنی هم روندی و مسائل باز.• Benchmarking Unity DOTS ،سربار حافظه ی اولیه، جابه جایی گلوگاه به GPU و الزامات ساختاری DOTS.• Pham (2020) ،Game Architectures in Unity Projects، مرجع اصلی معماری (SODD) ScriptableObject و نقد Singleton.• Casals &amp; Brandão (2025) ،HECATE: An ECS-based Framework، معماری لایه ای و همگرایی با سیستم های توزیع شده.• Muratet &amp; Garbarini (2020) ،Accessibility and serious games: ECS software architecture، سناریوی Modifiability.• Mizutani و همکاران (2021) ،مرور نظام مند Software Architecture for Digital Game Mechanics، چالش های باز و MVC.• Hansen &amp; AL Halbouni (2020) ،A Scenario-Based Evaluation of Game Architecture.• Ferrone ،مرجع مقایسه ی کارایی و Garbage میان C# events و UnityEvents، Object Pool، Dirty Flag و Data Locality.• Baron ،الگوهای طراحی، ScriptableObject، Thread-safety و Coroutine.• مطالعه ی کاپلینگ موتورها (Moose/Pharo، مدل Runtime Engine Architecture با ۱۶ زیرسیستم) و ارجاع به Cities Skylines 2 و Phalanx.• Bass و همکاران ،Software Architecture in Practice، چارچوب ارزیابی ATAM و مفاهیم Trade-off/Sensitivity Point/Risk.</description><category>gamenikocraft</category><author>gamenikocraft</author><pubDate>Sun, 09 Aug 2026 19:05:53 +0330</pubDate></item><item><title>از ۱۴ هزار به ۱۴ میلیون پیام در روز، داستان واقعی یک شوک داده ای</title><link>https://virgool.ir/@gamenikocraft/از-۱۴-هزار-به-۱۴-میلیون-پیام-در-روز-داستان-واقعی-یک-شوک-داده-ای-huqfjnqbgwbl</link><description>مرور سخنرانیStreaming: Real-Time Architecture for Connected Products in Automotive :سخنرانان: گروه مهندسی Thoughtworksلینک یوتیوب: https://www.youtube.com/watch?v=DQoroUTI8vcهمیشه شنیدن تئوری ها در کلاس درس یا کنفرانس ها جذاب است، اما هیچ چیز جای یک  Case Studyواقعی از وسط میدان جنگ را نمی گیرد! تیم شرکت Thoughtworks در این ارائه داستان پروژه ای را تعریف می کنند که برای قانون جدید داده های اروپا (EU Data Act) در صنعت خودرو سازی پیاده سازی کردند. قانونی که شرکت ها را مجبور می کند داده های خام سنسور های ماشین را به صورت بلادرنگ به مشتریان تحویل دهند.همه چیز در محیط تست امن و ارام پیش می رفت. سیستم روزانه ۱۴ هزار پیام دریافت می کرد و پایدار بود. اما فاجعه زمانی رخ داد که سیستم به محیط واقعی متصل شد. ناگهان حجم ورود داده ها به ۱۴ میلیون پیام در روز رسید! این یعنی پلتفرم باید در کسری از ثانیه هزار برابر بار بیشتری را مدیریت می کرد.دیدن اینکه تیم چگونه معماری خود را برای زنده ماندن در این شوک داده ای تغییر داد، بسیار آموزنده بود. آن ها از Apache Kafka برای هضم اولیه و صف بندی این حجم عظیم استفاده کردند و سپس با RabbitMQ داده ها را به دست کلاینت ها رساندند. اما درسی که ارزشمندتر بود، چالش مانیتورینگ بود. آن ها توضیح دادند که در مقیاس میلیون ها پیام، ابزار هایی مثل DataDog می توانند صورت حساب های نجومی و ترسناکی روی دست شرکت بگذارند. به همین دلیل مجبور شدند سیستم لاگ گیری را به شدت محدود و فیلتر کنند.خلاصه برداشت من: این ارائه ثابت کرد که تئوری روی کاغذ با محیط عملیاتی چقدر تفاوت دارد. مهم ترین برداشت من این بود که در سیستم های مقیاس پذیر، مدیریت داده ها فقط حل چالش های پردازشی نیست، بلکه اگر حواسمان به هزینه های پنهان ابزار های جانبی (مثل مانیتورینگ فضای ابری) نباشد، موفق ترین معماری ها هم می توانند از نظر مالی به شکست منتهی شوند. این مطلب، بخشی از تمرین های درس معماری نرم افزار در دانشگاه شهید بهشتی است.</description><category>gamenikocraft</category><author>gamenikocraft</author><pubDate>Sat, 11 Jul 2026 17:45:03 +0330</pubDate></item><item><title>میکروسرویس ها، تله ای شیک برای تیم های نرم افزاری</title><link>https://virgool.ir/@gamenikocraft/میکروسرویس-ها-تله-ای-شیک-برای-تیم-های-نرم-افزاری-bpy6dlb03gra</link><description>مرور سخنرانیSoftware Architecture for Tomorrow: Expert Talk : سخنرانان Sam Newman : و Julian Woodلینک یوتیوب:  https://www.youtube.com/watch?v=8KntBPOdfWAآیا میکروسرویس ها به یک مد روز کورکورانه در شرکت های نرم افزاری تبدیل شده اند؟ سام نیومن، کسی که خودش کتاب مرجع میکروسرویس ها را نوشته، در این گفتگوی دونفره با جولیان وود صراحتا می گوید: بله! این مصاحبه بیشتر شبیه درد دل دو مهندس با تجربه است که از دیدن اشتباهات تکراری در صنعت خسته شده اند.نیومن به نکته ظریفی اشاره می کند: خیلی از سازمان ها بدون داشتن مشکل مقیاس پذیری یا تیم های بزرگ، فقط برای اینکه شبیه شرکت های سیلیکون ولی به نظر برسند، سیستم یکپارچه (Monolith) خود را تکه تکه می کنند. نتیجه چیست؟ آن ها فراموش می کنند که در سیستم های توزیع شده، ما با یک مانع بزرگ به نام شبکه طرف هستیم. شبکه ای که تاخیر دارد، قطع می شود و پیام ها را در هوا گم می کند.یکی از بخش های آموزنده این گفتگو، بازگشت به اصول اولیه مهندسی بود، اصل مخفی سازی اطلاعات. نیومن توضیح داد که در یک معماری درست، یک میکروسرویس سبد خرید نباید تمام ساختار دیتابیس خود را از طریق  APIدر اختیار سرویس پرداخت بگذارد. بلکه باید فقط دیتای ضروری را با یک قرارداد محکم منتقل کند. اگر این اصل رعایت نشود، تغییر در یک سرویس باعث شکسته شدن زنجیره ای کل سیستم می شود.خلاصه برداشت من: میکروسرویس ها راه حل همه مشکلات نیستند و هزینه های پنهان زیادی مخصوصا در بخش شبکه و پیچیدگی زیرساخت دارند. همچنین در طراحی سیستم های توزیع شده، مخفی سازی اطلاعات و تعریف مرز های دقیق، از خود تکنولوژی هایی که استفاده می کنیم بسیار مهم تر است.این مطلب، بخشی از تمرین های درس معماری نرم افزار در دانشگاه شهید بهشتی است.</description><category>gamenikocraft</category><author>gamenikocraft</author><pubDate>Sat, 11 Jul 2026 17:38:28 +0330</pubDate></item><item><title>اعترافات یک معمار نرم افزار، چرا نباید از روز اول رویای اسکیل شدن داشته باشیم؟</title><link>https://virgool.ir/@gamenikocraft/اعترافات-یک-معمار-نرم-افزار-چرا-نباید-از-روز-اول-رویای-اسکیل-شدن-داشته-باشیم-attcjemyyxyl</link><description>مرور سخنرانی : Master Software Architecture: From Simplicity to Complexity سخنران : Maciej &#34;MJ&#34; Jedrzejewskiلینک یوتیوب:  https://www.youtube.com/watch?v=ZCrCqbblXjkسخنران در ابتدای ارائه، یکی از اشتباهات رایج خودش را تعریف می کند: یک بار برای سایتی که روزانه فقط صد بازدیدکننده داشت، یک کلاستر کوبرنتیز راه اندازی کرده بود. نتیجه؟ بیشتر وقتش صرف دیباگ کردن پادها می شد تا توسعه ویژگی های جدید. او در این ویدیو دقیقا دست روی همان نقطه ضعف بزرگ مهندسان نرم افزار می گذارد: تله ی بیش مهندسی یا  Over-engineeringحرف حساب او این است که بهترین معماری، معماری ای است که مشکلات امروز شما را حل کند. او یک مسیر چهار مرحله ای را پیشنهاد می دهد: سادگی، قابلیت نگهداری، رشد، و پیچیدگی. در فاز اول (سادگی)، شما فقط باید محصول را به دست مشتری برسانید. هیچ نیازی به کافکا یا ردیس کلاستر نیست. وقتی ترافیک بالا رفت و کدها شروع به درهم تنیدگی کردند، تازه وارد فاز قابلیت نگهداری می شوید.قسمتی از این ارائه که به شدت کاربردی است، تأکید بر کشف دامنه (Domain Discovery) بود. خیلی وقت ها ما بدون اینکه فرایند کسب وکار را بفهمیم، شروع به کشیدن دیاگرام پایگاه داده می کنیم. سخنران پیشنهاد می کند با تکنیک هایی مثل  Event Storming، متخصصان فنی و غیرفنی را دور هم جمع کنیم تا رویدادهای واقعی کسب وکار را روی تخته ترسیم کنند. این کار به صورت جادویی مرزهای سیستم را برای ما روشن می کند.خلاصه برداشت من:بزرگترین درس این ارائه ، غلبه بر ترس از جا ماندن در تکنولوژی بود. یاد گرفتم که معماری باید قدم به قدم با نیازهای واقعی کسب وکار رشد کند. تحمیل کردن میکروسرویس به سیستمی که هنوز ترافیک بالایی ندارد، هنر نیست، بلکه یک اشتباه مهندسی و تحمیل بدهی فنی است.این مطلب، بخشی از تمرین های درس معماری نرم افزار در دانشگاه شهید بهشتی است.</description><category>gamenikocraft</category><author>gamenikocraft</author><pubDate>Sat, 11 Jul 2026 17:35:24 +0330</pubDate></item><item><title>اگر گودزیلا به دیتاسنتر ما حمله کند چه کنیم؟ نگاهی به نظریه پسماند ها</title><link>https://virgool.ir/@gamenikocraft/اگر-گودزیلا-به-دیتاسنتر-ما-حمله-کند-چه-کنیم-نگاهی-به-نظریه-پسماند-ها-haxsnb73iw6a</link><description>مرور سخنرانی :  Residues: Time, Change &amp; Uncertainty in Software Architecture سخنران  Barry O&#39;Reilly :لینک یوتیوب:  https://www.youtube.com/watch?v=D8qQUHrksrEمعماری شما در برابر حمله هیولای آتش افشان از دریای شمال چقدر مقاوم است؟ وقتی بری اوریلی این سوال را در سخنرانی اش مطرح کرد، به نظر میرسید در حال شوخی با حضار است. اما چند دقیقه بعد، متوجه میشویم با یکی از عمیق ترین مفاهیم معماری نرم افزار روبرو هستم: نظریه پسماند (Residuality Theory).ما در دانشگاه یاد گرفته ایم که معماری را بر اساس نیازمندی های مشخص (Requirements) بسازیم. اما اوریلی با وام گرفتن از مفاهیم علوم پیچیدگی، نشان می دهد که دنیای واقعی کسب و کار به هیچ وجه قابل پیش بینی نیست. او می گوید به جای تمرکز روی مسیر های ایده آل، باید سیستم را با سناریو های کاملا تصادفی و غیر منطقی تست کنیم.مثال او درباره سیستم شارژ خودرو های برقی بی نظیر بود. تصور کنید سیستم را برای شارژ عادی ساخته اید. ناگهان یک سناریوی عجیب مطرح می شود: اگر یک راننده ماشین بنزینی از روی لجبازی جلوی شارژر پارک کند چه؟ معمار سیستم برای حل این تنش، تصمیم می گیرد دوربین ثبت پلاک اضافه کند. این دوربین، به صورت تصادفی مشکل دیگری را هم حل می کند: جلوگیری از دزدی کابل های شارژر! این یعنی وقتی ما معماری را با تنش های پیش بینی نشده درگیر می کنیم، چیزی که از سیستم باقی می ماند (همان پسماند)، به شدت تاب آورتر از طرح اولیه است.خلاصه برداشت من: برداشت اصلی من این است که ما باید دست از طراحی برای یک دنیای ایده آل و قابل پیش بینی برداریم. معمار نرم افزار نباید فقط به فکر مسیر های خوش بینانه باشد، بلکه باید سیستم را برای زنده ماندن در برابر اتفاقات کاملا بی ربط و ناشناخته آماده کند. این مطلب، بخشی از تمرین های درس معماری نرم افزار در دانشگاه شهید بهشتی است.</description><category>gamenikocraft</category><author>gamenikocraft</author><pubDate>Sat, 11 Jul 2026 17:33:11 +0330</pubDate></item><item><title>کد زدن همیشه بهترین راه نیست، چرا باید با جریان کار ها آشتی کنیم؟</title><link>https://virgool.ir/@gamenikocraft/کد-زدن-همیشه-بهترین-راه-نیست-چرا-باید-با-جریان-کار-ها-آشتی-کنیم-folusvmvcgrr</link><description>مرور سخنرانی: Building Better Software: Why Workflows Beat Code Every Time سخنرانان:  Ben Smith و James Beswickلینک یوتیوب: https://www.youtube.com/watch?v=SKYbOk2S-xoچند بار پیش آمده که برای پیاده سازی یک منطق تلاش مجدد (Retry) ساده، سه روز تمام درگیر دیباگ کردن کد ها باشید؟ راستش را بخواهید، ما برنامه نویس ها یک غرور پنهان داریم: فکر می کنیم هر مشکلی را حتما باید با باز کردن ادیتور و نوشتن صد ها خط کد حل کنیم. اما تماشای ویدیوی بن اسمیت و جیمز بزویک در کنفرانس GOTO 2025 یک تلنگر جدی به این طرز فکر بودبحث اصلی آن ها این است که برای مفاهیم پیچیده ای مثل قطع کننده مدار (Circuit Breaker) در سیستم های توزیع شده، نوشتن کد دستی یعنی خودکشی. وقتی یک سرویس قطع می شود، مدیریت تایم اوت ها و صف بندی دوباره درخواست ها با کد، کلافی سردرگم می سازد. اما در یک ابزار گردش کار (Workflow)، شما این منطق را به صورت یک فلوچارت بصری می بینید و مدیریت می کنید.مورد جذاب تر در این ارائه، باز کردن مفهوم هزینه ها بود. در مدل های سنتی، شما یک سرور می خرید و چه ترافیک داشته باشید چه نه، هزینه اش را پرداخت می کنید. اما ابزار های گردش کار ابری معمولا Serverless هستند، یعنی دقیقا فقط زمانی که یک درخواست واقعی پردازش شود کنتور می اندازند. برای تیم های استارتاپی که بودجه محدودی دارند، این پرداخت به ازای مصرف (Pay-per-use) یعنی مدیریت هوشمندانه و بسیار بهتر هزینه ها.خلاصه برداشت من: این ویدیو به ما یاد می دهد که تعصب روی کد نویسی دستی همیشه خوب نیست. گاهی استفاده از ابزار های آماده مثل سیستم های گردش کار، نه تنها کسر شان یک برنامه نویس نیست، بلکه نشان دهنده بلوغ مهندسی او در مدیریت زمان، هزینه و جلوگیری از اختراع دوباره چرخ است.این مطلب، بخشی از تمرین های درس معماری نرم افزار در دانشگاه شهید بهشتی است.</description><category>gamenikocraft</category><author>gamenikocraft</author><pubDate>Sat, 11 Jul 2026 17:28:39 +0330</pubDate></item><item><title>تمرین ۱ معماری نرم افزار : مروری بر ۲۰ مفهوم کلیدی</title><link>https://virgool.ir/@gamenikocraft/تمرین-۱-معماری-نرم-افزار-مروری-بر-۲۰-مفهوم-کلیدی-v2f1nbrywsnu</link><description>Chaos Engineering:مهندسی آشوب راهکاری است که میتوانیم از طریق آن در سیستم نرم افزاری خود به هم ریختگی و عیوبی ایجاد کنیم تا شکست های احتمالی و پنهان را قبل از اینکه واقعا سیستم عیب کند نمایان کنیم .این ابداع شرکت نتفلیکس بود ، نتفلیکس در سال 2008 از یک دیتابیس استفاده میکرد که اگر مشکلی در ان بوجود می امد کل سیستم مختل میشد و این اتفاق یکبار برای انها افتاد و 3 روز استریم ویدیو با مشکل جدی روبرو شد به این صورت که هیچکسی نمیتوانست ویدیویی از سایت ببیند . پس از این اتفاق به این نتیجه رسیدند که از وجود یک نقطه شکست جلوگیری کنند و معماری خود را به میکروسرویس تغییر دهند . اما با این حال به علت وجود وابستگی ها همچنان ممکن بود که با خرابی سرویس هایی کل سیستم مختل شود ، همچنین نمیتوانستند در محیط توسعه انرا تست کنند زیرا در دنیای واقعی خرابی های پیش بینی نشده و بی قائده ای همچون داغ کردن و سوختن سرور ، پر شدن دیسک ، قطعی شبکه و ... وجود دارند ، سر انجام مهندسان نتفلیکس ابزاری به نام Chaos Monkey ساختند که مانند میمونی بازیگوش به صورت تصادفی برخی از سرویس ها را غیرفعال میکرد، عملکرد سیستم پس از آشوب های ابتدایی تعریفی نداشت اما به مرور بهبود یافت و باعث مقاوت بیشتر سیستم شد .  Backend for Frontend:در سال 2010 اکثر شرکت های بزرگ، محصولات نرم افزاری خود را برای کلاینت های دسکتاپ طراحی میکردند اما به مرور که بازار تلفن های همراه هوشمند رشد چشمگیری داشتند ، نیاز به توسعه کلاینت های موبایلی بسیار گسترده شد.با توجه به اینکه کلاینت های موبایلی و دسکتاپ تفاوت هایی از جمله صفحه نمایش ، توان پردازشی ، اتصال شبکه متفاوت و ... داشند نیاز بود که اپلیکیشن های موبایلی و نرم افزار های دسکتاپ کمی تفاوت داشته باشند اما در ابتدا اپلیکیشن هایی که ساخته میشد از همان سرویس هایی استفاده میکرد که در نسخه دسکتاپ ارسال میشد که برای موبایل بهینه نبود و مشکلاتی مانند کندی را به همراه داشت.از آن پس تکنیکی به نام Backend for Frontend یا BFF ابداع شد که در آن از سرویس هایی به نام BFF استفاده میکنیم که درخواست های سمت کلاینت یا سرور را مناسب با نوع آن کلاینت تنظیم و بهینه میکند (این با API Gateway متفاوت است ،API Gateway صرفا یک دروازه ای است که API ها را از خود عبور میدهد و مدیریت میکند ولی از منطق کلاینت ها آگاه نیست و نمیتواند آنها را تفکیک کند)، به این صورت دیگر نیاز نبود که بار اضافه وارد کلاینت های خاص شود و به بهبود سرعت آنها و هچنین استقلال توسعه کمک کرد.  AI4SEدر سال های نه چندان دور ، توسعه سیستم نرم افزاری به مهارت های فردی متکی بود برای مثال یک توسعه دهنده باید خودش کدنویسی ، تست ، مستند سازی و کشف باگ را انجام میداد که بسیار کند بود و احتمال خطای انسان بالاتر بود. با گذشت زمان و ظهور ابزار های هوش مصنوعی کار آنها بسیار ساده تر شده به طوریکه در تمام مراحل توسعه نرم افزار میتوانیم از ابزار های هوض مصنوعی استفاده کنیم مثلا در مرحله نیازمندی ها میتوان از جلسات ضبط شده استفاده کرد تا ابزار های هوش مصنوعی به صورت خودکار نیازمندی ها را لیست کنند و حتی به وسیله همین نیازمندی ها کمک شایانی به معماری و در نهایت کدنویسی و تست نرم افزار کنند. SE4AIهمانگونه که فرایند های مهندسی نرم افزار نیازمند هوش مصنوعی هستند ، هوش مصنوعی نیز نیازمند مهندسی نرم افزار است . مثلا راه اندازی موثر عوامل و مدل های هوش مصنوعی در قالب یک اپلیکیشن عمومی نیازمند به کار گرفتن تجربه ای چند ساله در حوزه ساخت نرم افزار است . به کارگیری این تجارب برای توسعه انواع مختلف سامانه های هوش مصنوعی مانند چت بات ها ، سیستم های تشخیص تصویر و ... حوزه ای جدید به نام SE4AI  را پدید آورده .در SE4AI روش های مهندسی نرم افزار به داد هوش مصنوعی رسیده اند و میتوان گفت مکمل AI4SE است . MLOpsاین مفهوم ترکیب ماشین لرنینگ و DevOps است.فرض کنید یک سامانه برای فروش بازی های ویدیویی داریم و مدلی برای این سامانه طراحی شده است که بر اساس سوابق خرید ها و جستجوی مشتریان به انها پیشنهاد خرید میدهد . ابتدا نیاز است که مدل ما train شود و باید داده های اولیه به ان بدهیم و نهایتا مدل یادگیری را انجام داده و به خوبی در ان سامانه کار میکند . حال فرض میکنیم که پس از گذشت مدتی بازی ها به سمت یک دسته بندی نوظهور و ترند متمایل شده اند و مشتریان بیشتر تقاضای خرید از ان دسته را دارند یا به هر نحو دیگری الگوی خرید انها دچار تغییر شده اما مدل طبق همان داده های قبلی پیشنهاد میدهد و نیاز است که مدل دوباره با داده های جدید آموزش ببیند، به روزرسانی شود و دوباره روی سامانه مستقر گردد. انجام دستی این کار به شدت کند است. اینجا جایی است که MLOps  وارد می شود: ترکیب یادگیری ماشین و DevOps ، تا این چرخه را خودکار کند از گرفتن خودکار داده های جدید، تا آموزش مجدد مدل، تست خودکار و در نهایت استقرار سریع نسخه جدید بدون توقف سامانه و کوتاه شدن مدت استقرار ها یعنی میتوان گفت مدل دائما در حال یادگیری است Infrastructure as Code (IaC)در گذشته تمامی سامانه های نرم افزاری نیازمند این بودند که سرور هایشان را به صورت دستی نصب و راه اندازی میکردند به این صورت که ابتدا سرور های فیزیکی خریداری و سپس سیستم عامل ، نیازمندی ها و پیکربندی ها را به صورت دستی روی انها نصب و اعمال میکردند اما مشکل اینجا بود که اگر یک سرور خراب میشد دوباره باید کل مراحل قبل را به صورت دستی انجام میدادند که بسیار طاقت فرسا بود ، بعدا ها این ایده به وجود امد که زیرساخت های سامانه را مانند خود نرم افزار به صورت کد در بیاوریم و انها را به صورت خودکار و نسخه بندی شده روی گیت اعمال کنیم . IaC  به این معنی است که زیرساخت های سامانه را بدون نیاز به عملیات های دستی به صورت خودکار انجام دهیم. API Gateway &amp; Service Meshدر زمانی که سامانه های نرم افزاری از معماری یکپارچه (Monolithic) استفاده میکردند ، فقط یک نقطه تبادل پیام با کل سیستم وجود داشت یعنی تنها از یک طریق ، پیام بین سیستم و کلاینت رد و بدل میشد . با روی کار آمدن معماری میکروسرویس و تقسیم سیستم به تعداد زیادی سرویس کوچک ، کلاینت ها مجبور بودند با چندین سیستم تعامل داشته باشند که ارتباط شبکه ای کلاینت با سامانه را بسیار پیچیده میکرد ، اینجا بود که API Gateway ابداع شد و دروازه ای بود بین کلاینت ها و سیستم به این صورت که درخواست کلاینت ها به سرویس API Gateway وارد شده و به سمت سرویس مورد نظر هدایت میشدند .با افزایش تعداد سرویس ها در معماری میکروسرویس ، ارتباط بین این سرویس ها نیز دچار پیچیدگی شد و همچنین از کار افتادن یک سرویس روی سرویس های دیگر تاثیر میگذاشت اینها باعث شد که Service Mesh پدید آید که امنیت و مدیریت ارتباط بین سرویس ها را فراهم میکرد. . در این روش یک پروکسی کنار هر سرویس قرار میدهیم که تمام ترافیک ورودی و خروجی از ان میگذرد که به ان سایدکار میگویند. ساید کار ها در یک هسته مرکزی به نام کنترل پلن مدیریت میشوند. CQRS (Command Query Responsibility Segregation)در گذشته معماری سامانه های نرم افزاری به این شکل بود که معمولا یک دیتابیس هم مسئول خواندن اطلاعات و هم نوشتن بود . این روش برای سیستم های کوچک خوب بود اما مشکل اینجا بود که وقتی سامانه بزرگ میشد ، عملیات خواندن و نوشتن با هم باعث کندی سیستم میشد .بعد ها این ایده به وجود امد که بیاییم نوشتن و خواندن را از هم جدا کنیم . به این صورت که یک دیتابیس مخصوص ثبت اطلاعات قرار میدهیم و یک دیتابیس جداگانه هم مخصوص نمایش اطلاعات داریم که خیلی سریع جواب کلاینت را میدهد . این دو دیتابیس با هم از طریق رویداد ها هماهنگ میشوند به این معنی که هر بار چیزی از دیتابیس مسئول نوشتن کم یا به ان اضافه شود ، رویدادی تولید میشود که سمت خواندن را هم به روز میکند . مزیت آن سرعت و مقیاس پذیری بالا است اما عیب ان پیچیدگی بیشتر سیستم است و اینکه اطلاعات خواندن ممکن است چند لحظه از نوشتن عقب بماند .Event-Driven Architecture (EDA)  سامانه های نرم افزاری قدیمی به این شکل کار می کردند که برای انجام یک کار، بخش های مختلف باید مستقیما به هم دستور می دادند. مثلا در یک فروشگاه وقتی خریدی انجام می شد، بخش ثبت سفارش باید مستقیما به انبار و پیامک دستور می داد. مشکل اینجا بود که اگر سیستم پیامک خراب می شد، کل فرایند خرید هم از کار می افتاد. بعد ها این ایده به وجود امد که سیستم ها بر اساس رویداد ها کار کنند. یعنی بخش ثبت سفارش فقط یک رویداد تولید می کند و ان را در یک فضای مشترک می گذارد. حالا بخش های انبار و پیامک که منتظر این رویداد هستند، ان را دریافت کرده و کار خودشان را انجام می دهند در واقع بخش های مختلف سیستم بجای اینکه منتظر پیامی از سوی دیگری باشند که ممکن است با از کار افتادن بخشی مختل شود ان بخش خراب شده باشد و نتواند ارسال کند ، باید گوش به زنگ یک رویداد باشند . این کار باعث می شود وابستگی بخش ها به هم کم شود و اگر یک بخش خراب شد، بقیه سامانه به کار خود ادامه دهد.Serverless Architecture در گذشته برای اجرای یک نرم افزار، حتما باید یک سرور فیزیکی یا مجازی اجاره می کردیم و همیشه هزینه ان را می پرداختیم، حتی اگر در طول روز هیچ کاربری از سامانه استفاده نمی کرد. مدیریت این سرور ها و تامین امنیت ان ها هم کاملا بر عهده خودمان بود. با گذشت زمان مفهوم معماری بدون سرور شکل گرفت. اما سرورلس به این معنی نیست که سروری وجود ندارد، بلکه به این معنی است که ما دیگر هیچ درگیری با مدیریت سرور نداریم. در این روش ما فقط کد برنامه را می نویسیم و ان را روی سرویس های ابری قرار می دهیم. شرکت ارائه دهنده خدمات ابری خودش منابع لازم را اختصاص داده و آنها را بدون نیاز به ارتباط مستقیم ما با سرور مدیریت میکند. برخلاف سرور سنتی که همیشه روشن است، در سرورلس منابع فقط هنگام وقوع یک رویداد یا درخواست، کد شما را اجرا می کنند و بلافاصله پس از اتمام، منابع آزاد می شوند.API-first Approach در روش های سنتی توسعه نرم افزار، روال کار به این صورت بود که ابتدا رابط کاربری و بخش های ظاهری برنامه طراحی می شد و بعد از ان برنامه نویسان سراغ نوشتن بک اند و دیتابیس می رفتند. در نهایت اگر نیاز بود که سامانه به سیستم دیگری متصل شود، یک رابط یا ای پی ای برای ان می نوشتند. اما این کار باعث می شد API ها کیفیت خوبی نداشته باشند و کار بین تیم های فرانت اند و بک اند کند شود. در رویکرد جدید API-first این روند برعکس شده است. در اینجا قبل از ساخت ظاهر، ابتدا توافق می شود که ارتباطات به چه صورت باشند و ورودی و خروجی ان ها مشخص می شود. با این کار تیم ها می توانند به صورت همزمان کار خود را شروع کنند و سامانه خیلی سریع تر اماده می شود.Domain Driven Design خیلی وقت ها در پروژه های نرم افزاری بزرگ، مشکل از برنامه نویسی نیست بلکه مشکل این است که برنامه نویسان زبان متخصصان ان کسب و کار را نمی فهمند. مثلا در یک سیستم بانکی، برنامه نویس ها فقط به دیتابیس و کد فکر می کنند ولی مدیران بانک در مورد مفاهیم مالی و حساب ها حرف می زنند. این اختلاف باعث می شود نرم افزار نهایی نیاز های واقعی کسب و کار را براورده نکند. طراحی مبتنی بر دامنه که توسط اریک اوانز در کتابش معرفی شده ، راه حلی برای این مشکل است. اریک درباره اهمیت شناخت دامنه اینگونه بیان کرده : اگر نمی دانی کسب وکارت واقعاً چگونه کار می کند، هر معماری هم بسازی، شکست می خورد. در روشDomain Driven Design  قبل از هرگونه کدنویسی، برنامه نویسان و متخصصان کسب و کار دور هم جمع می شوند و یک زبان مشترک می سازند. سپس کل معماری سیستم، اسم کلاس ها و ساختار نرم افزار دقیقا بر اساس همان مفاهیم واقعی دامنه مدل سازی می شود تا نرم افزار کاملا شبیه دنیای واقعی کار کند. لازم به ذکر است در پروژه های ساده که قوانین کسب و کاری سختی وجود ندارد استفاده از این روش لزومی ندارد.Hexagonal architecture در معماری های لایه ای قدیمی، هسته برنامه ما که همان قوانین اصلی کسب و کار است، به دیتابیس یا رابط کاربری و ... وابسته بود. اگر روزی تصمیم می گرفتیم دیتابیس را عوض کنیم یا مثلا بجای وب سایت از اپلیکیشن موبایل استفاده کنیم، باید بخش زیادی از کد های اصلی را هم تغییر می دادیم که بسیار خطرناک و زمان بر بود. معماری شش ضلعی برای حل این مشکل ابداع شد. در این معماری، منطق اصلی نرم افزار در مرکز قرار می گیرد و کاملا از دنیای بیرون ایزوله می شود. ارتباط این هسته با بیرون فقط از طریق پورت ها و اداپتور ها انجام می شود(پورت ها اینترفیس و اداپتور ها پیاده سازی آن است.) یعنی اگر بخواهیم دیتابیس را عوض کنیم، هسته اصلی اصلا متوجه این تغییر نمی شود و فقط کافی است اداپتور مربوط به دیتابیس جدید را به سیستم وصل کنیم.Event Sourcing در حالت عادی دیتابیس ها به این صورت کار می کنند که فقط وضعیت فعلی اطلاعات را ذخیره می کنند. مثلا وقتی موجودی حساب بانکی شما تغییر می کند، سامانه عدد قبلی را پاک می کند و عدد جدید را جایگزین می کند. مشکل این روش این است که ما تاریخچه تغییرات را از دست می دهیم و نمی دانیم این عدد چگونه به دست امده است. در این روش به جای ذخیره کردن وضعیت نهایی، تمام اتفاقات و رویداد هایی که باعث تغییر شده اند را به ترتیب ذخیره می کنیم. مثلا ثبت می کنیم که اول 500 تومان واریز شد، بعد 100 تومان برداشت شد. با این کار ما همیشه یک تاریخچه کامل از تمام اتفاقات سامانه داریم و اگر خطایی رخ دهد، می توانیم با اجرای دوباره رویداد ها، سیستم را به گذشته برگردانیم.Low-code/No-code platformsدر سال های نه چندان دور، برای ساختن هر نرم افزاری حتما نیاز به تیم های بزرگ برنامه نویسی بود که باید خط به خط کد ها را با زبان های مختلف می نوشتند. این کار بسیار زمان بر و پر هزینه بود و افراد عادی نمی توانستند ایده های خود را سریع عملی کنند. با گذشت زمان پلتفرم های بدون کد (No-code) مثل joapp (برای ساخت اپلیکیشن اندروید) به وجود آمدند. این پلتفرم ها محیط هایی هستند که در آن ها افراد می توانند بدون نیاز به کدنویسی، و فقط با کشیدن و رها کردن اجزای گرافیکی، نرم افزار های خودشان را بسازند. این ابزارها باعث می شوند افراد معمولی که دانش برنامه نویسی ندارند هم بتوانند ایده هایشان را تبدیل به نرم افزار کنند و سرعت تولید سامانه ها برای کارهای ساده به شدت افزایش پیدا کند.در کنار پلتفرم های بدون کد، دسته دیگری به نام پلتفرم های Low-code نیز وجود دارند. این پلتفرم ها برای توسعه دهندگان حرفه ای طراحی شده اند و به انها اجازه می دهند با نوشتن حداقل کد سرعت توسعه را چندین برابر کنند. تفاوت اصلی در این است که در Low-code  هنوز هم می توان کد دستی نوشت، اما کارهای تکراری و زیرساختی توسط پلتفرم انجام می شود. یک مثال معروف از این دسته، OutSystems یا Microsoft Power Apps  است که برای ساخت اپلیکیشن های سازمانی قدرتمند استفاده می شود.Business Process Management Systems (BPMS)  در سازمان های بزرگ، انجام کارها شامل مراحل و بخش هایی است. مثلا برای ثبت درخواست وام صندوق رفاه دانشجویی در سامانه بهستان، ابتدا دانشجو باید درخواست خود را در سامانه ثبت کند، بعد مدیر دانشکده تایید کند و در نهایت به معاونت اموزشی یا اداره رفاه دانشجو برسد تا تایید نهایی انجام و وام پرداخت شود. در گذشته این روال ها یا کاملا روی کاغذ بود یا اینکه باید برنامه نویس ها برای هر کدام از این مراحل، کدنویسی هایی انجام می دادند که تغییر دادن آن ها هم بسیار سخت و زمان بر بود. سیستم های مدیریت فرایند کسب و کار به وجود آمدند تا این مشکل را حل کنند. در این سیستم ها، ما می توانیم فرایندهای کاری سازمان را به صورت تصویری و نموداری مدل سازی کنیم و سیستم خودش این نمودارها را به یک برنامه اجرایی تبدیل می کند. با این کار، اتوماتیک کردن روال های اداری خیلی سریع انجام می شود. Message Queue (such as Kafka and RabbitMQ) وقتی که ما چند سرویس داریم که با هم مستقیما پیام رد و بدل میکنند ، اگر یکی از انها به مشکل بخورد و در سمت دیگر پیام های همزمان زیادی ارسال شود ، آنگاه باعث کندی یا قطعی کامل میشود. فرض کنید ، زمان انتخاب واحد نیمسال جدید فرا می رسد و ناگهان هزاران دانشجو همزمان وارد سامانه بهستان می شوند و درخواست انتخاب واحد می دهند. سیستم باید برای هر دانشجو، پس از ثبت درخواست، یک گزارش تایید انتخاب واحد مثلا به صورت ایمیل یا پیامک و همچنین یک صورتحساب مالی ارسال کند. اگر سامانه بخواهد همه این کارها را در همان لحظه انجام دهد ، یعنی همزمان با ثبت درخواست، گزارش و صورتحساب را هم تولید و ارسال کند قطعا کند می شود و یا از کار می افتد.اینجاست که صف های پیام وارد می شوند. این ابزارها مثل یک صندوق پستی بزرگ عمل می کنند. سامانه بهستان به جای اینکه خودش درگیر ارسال ایمیل و تولید گزارش شود، فقط پیام درخواست انتخاب واحد دانشجو را داخل این صف می گذارد و سریعا به دانشجو پاسخ درخواست شما ثبت شد را نمایش می دهد. در سمت دیگر، یک سرویس پردازشگر که مختص ارسال ایمیل و تولید گزارش است، سر فرصت پیام ها را یکی یکی از صف برمی دارد، مدارک و وضعیت مالی دانشجو را بررسی می کند، گزارش را تولید و ایمیل می کند. این کار باعث می شود سامانه بهستان زیر فشار ناگهانی انتخاب واحد دوام بیاورد، هیچ درخواستی گم نشود، و دانشجو مجبور نباشد منتظر بماند تا همه درخواست ها انجام شود.Containers (eg., Docker) and Container orchestration (e.g., Kubernetes) در گذشته یکی از بزرگترین مشکلات برنامه نویس ها این بود که نرم افزار روی سیستم خودشان به درستی کار می کرد اما وقتی ان را روی سرور اصلی می بردند، به دلیل تفاوت سیستم عامل یا نسخه کتابخانه ها، با ارور های مختلف مواجه می شدند. کانتینرها (مثل Docker) برای حل همین مشکل به وجود آمدند. ایده ساده است، شما نرم افزارتان را به همراه همه چیزهایی که برای اجرا نیاز دارد مثل کتابخانه ها، فایل های تنظیمات و ... داخل یک بسته ایزوله به نام ایمیج می گذارید. وقتی این ایمیج را اجرا می کنید، یک کانتینر ساخته می شود. کانتینرها در مقایسه با ماشین های مجازی خیلی سبک ترند و سریعا اجرا می شوند چون هسته سیستم عامل را با هم به اشتراک می گذارند . مزیت اصلی: یک کانتینر در هر جایی دقیقا یکسان اجرا می شود، چون همه وابستگی هایش را همراه خودش دارد. اما وقتی سیستم شما بزرگ می شود، مثلا به صد ها کانتینر می رسد، مدیریت دستی آن ها غیرممکن می شود. چه کسی قرار است هر ساعت چک کند که کدام کانتینر از کار افتاده و آن را دوباره راه بیندازد؟ چه کسی تصمیم می گیرد وقتی ترافیک زیاد شد، تعداد کانتینرها را افزایش دهد؟ کانتینرها چطور همدیگر را پیدا کنند؟ ارکستراسیون کانتینر مثل Kubernetes اینجاست تا همه این کارها را خودکار کند. کوبرنتیز مانند یک فرمانده مرکزی عمل می کند که روی یک کلاستر از سرورها نصب می شود و مدام وضعیت همه کانتینرها را رصد می کند و مسئول مدیریت انها استMulti-Tenancy Architecture فرض کنید شما یک نرم افزار حسابداری ساخته اید و می خواهید ان را به شرکت های مختلف بفروشید. در روش های قدیمی، باید برای هر شرکت یک سرور و دیتابیس جداگانه تهیه می کردید و یک نسخه اختصاصی از نرم افزار را نصب می کردید. این روش بسیار پر هزینه بود و وقتی می خواستید نرم افزار را اپدیت کنید، باید این کار را تک تک برای همه شرکت ها انجام می دادید. معماری چند مستاجری این مشکل را حل کرد. در این معماری، شما فقط یک نسخه از نرم افزار و دیتابیس را روی یک سرور بالا می اورید، اما به گونه ای طراحی می کنید که چندین شرکت مختلف بتوانند همزمان از ان استفاده کنند، بدون اینکه اطلاعاتشان با هم قاطی شود. با این کار هزینه های نگهداری به شدت کاهش می یابد.Data Migration در طول عمر یک سامانه نرم افزاری، مواقعی پیش می آید که مجبور می شویم سیستم های قدیمی را با سیستم های جدید جایگزین کنیم یا نوع دیتابیس را تغییر دهیم. در این زمان، اطلاعات ارزشمندی که طی سال ها در سیستم قدیمی جمع شده اند نباید از بین بروند و باید به سیستم جدید منتقل شوند. به این فرایند انتقال داده می گویند. این کار فقط کپی کردن ساده نیست، چون معمولا ساختار اطلاعات در سیستم جدید با سیستم قدیمی فرق دارد. بنابراین در این فرایند باید ابتدا داده ها استخراج شوند (Extract) ، سپس تمیز سازی شده و به فرمت سیستم جدید تبدیل شوند (Transform)  و در نهایت با دقت بالایی در دیتابیس جدید لود شوند.(Load)  این سه مرحله در مهاجرت داده با نام اختصاری ETL شناخته می شود. اشتباه در این مسیر می تواند باعث از دست رفتن اطلاعات مهم مشتریان شود.  منابع:WikipediaByteByteGoRed HatZommitDeepSeek , Gemini</description><category>gamenikocraft</category><author>gamenikocraft</author><pubDate>Mon, 01 Jun 2026 23:35:39 +0330</pubDate></item></channel></rss>