<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های امین مستوری نژاد</title><link>https://virgool.ir/feed/@amin.montazer1381</link><description></description><language>fa</language><pubDate>2026-11-11 11:59:21</pubDate><image><url>https://files.virgool.ir/upload/users/4883652/avatar/avatar.png</url><title>امین مستوری نژاد</title><link>https://virgool.ir/@amin.montazer1381</link></image><item><title>📖قبل از طراحی نرم‌افزار، تیم‌هایتان را درست طراحی کنید</title><link>https://virgool.ir/@amin.montazer1381/قبل-از-طراحی-نرم-افزار-تیم-هایتان-را-درست-طراحی-کنید-i7ceombpq3pv</link><description>کتاب Team Topologies، راهنمایی کاربردی برای طراحی تیم‌ها، تعاملات سازمانی و ایجاد جریان سریع‌تر ارزشمدتی پیش مطالعه کتاب Team Topologies نوشته‌ی Matthew Skelton و Manuel Pais را شروع کردم. قبل از خواندن کتاب تصور می‌کردم قرار است با مجموعه‌ای از توصیه‌های مدیریتی درباره تقسیم نیروها، چارت سازمانی و نحوه تشکیل تیم‌های نرم‌افزاری مواجه شوم؛ اما هرچه بیشتر جلو رفتم، متوجه شدم موضوع کتاب بسیار عمیق‌تر است.این کتاب فقط درباره این نیست که «چه تیم‌هایی داشته باشیم؟»؛ بلکه سؤال مهم‌تری مطرح می‌کند:چطور باید انسان‌ها، تیم‌ها، معماری نرم‌افزار و جریان ارزش را طوری کنار هم قرار دهیم که کارها سریع‌تر، امن‌تر و با اصطکاک کمتر پیش بروند؟بسیاری از مشکلاتی که در ظاهر فنی به نظر می‌رسند، در واقع از فناوری شروع نمی‌شوند. گاهی یک سیستم به این دلیل پیچیده، کند و وابسته شده که تیم‌های سازنده آن نیز به همان شکل پیچیده، جدا افتاده و وابسته سازمان‌دهی شده‌اند.به زبان ساده، ممکن است تصور کنیم مشکل ما پایگاه داده، معماری، زیرساخت، فرایند استقرار یا ابزارهای DevOps است؛ اما ریشه اصلی مشکل در مرزهای اشتباه تیم‌ها، مسئولیت‌های نامشخص، پاسکاری‌های زیاد و ارتباطات کنترل‌نشده باشد. 😵‍💫🏢 چارت سازمانی، واقعیت سازمان را نشان نمی‌دهدیکی از نخستین موضوعاتی که کتاب Team Topologies به چالش می‌کشد، اعتماد بیش از حد به چارت‌های سازمانی است. چارت سازمانی معمولا تصویری مرتب، منطقی و رسمی از سازمان نشان می‌دهد؛ مدیران در بخش‌های بالاتر قرار دارند، واحدها به‌ صورت منظم زیرمجموعه آن‌ها هستند و خطوط مشخص می‌کنند هر فرد باید به چه کسی گزارش دهد، اما شیوه واقعی انجام کار در سازمان معمولا با این تصویر تفاوت زیادی دارد.واقعیت پشت چارت سازمانی در عمل، افراد برای حل مسائل از مسیرهای غیررسمی استفاده می‌کنند؛ برای مثال، ممکن است یک توسعه‌دهنده برای رفع یک مشکل مستقیما با فردی از تیم زیرساخت، امنیت یا محصول ارتباط برقرار کند، حتی اگر در چارت سازمانی هیچ خط مستقیمی میان آن‌ها وجود نداشته باشد. کتاب توضیح می‌دهد که در هر سازمان، سه ساختار به‌ صورت همزمان وجود دارد: ساختار رسمی که در چارت سازمانی دیده می‌شود، ساختار غیررسمی که از روابط، اعتماد و میزان نفوذ افراد شکل می‌گیرد و ساختار خلق ارزش که نشان می‌دهد کار در واقعیت چگونه از یک ایده آغاز می‌شود و در نهایت به دست مشتری می‌رسد. نکته مهم این است که بهبود عملکرد یک واحد، الزاما باعث افزایش سرعت کل سازمان نمی‌شود؛ ممکن است یک تیم وظیفه خود را در چند ساعت انجام دهد، اما برای دریافت تایید نهایی مجبور باشد تا جلسه هفتگی مدیران منتظر بماند! 😅در چنین شرایطی، سریع بودن آن تیم تاثیر چندانی بر سرعت واقعی تحویل نخواهد داشت. بنابراین، به‌جای تمرکز جداگانه بر کارایی هر واحد، باید کل جریان حرکت کار را از زمان شکل‌گیری ایده تا رسیدن ارزش نهایی به مشتری بررسی کرد و گلوگاه‌هایی را از بین برد که باعث انتظار، پاسکاری و کند شدن فرایند می‌شوند.🪞 قانون کانوی؛ نرم‌افزار آینه سازمان استیکی از تأثیرگذارترین مفاهیم کتاب، قانون کانوی بود.این قانون به زبان ساده می‌گوید: معماری سیستمی که یک سازمان تولید می‌کند، بازتابی از ساختار ارتباطی همان سازمان است.برای مثال، اگر چهار تیم کاملا جدا روی یک سیستم کار کنند، به احتمال زیاد خروجی آن‌ها نیز به چهار بخش جدا تبدیل می‌شود. اگر همه تیم‌ها برای تغییر داده‌ها به یک تیم متمرکز پایگاه داده وابسته باشند، سیستم نیز احتمالا حول یک پایگاه داده بزرگ، مشترک و وابسته شکل می‌گیرد.این موضوع  نشان داد که معماری نرم‌افزار فقط حاصل تصمیم معماران و برنامه‌نویسان نیست. مدیرانی که تیم‌ها را تقسیم می‌کنند، بودجه را تخصیص می‌دهند یا افراد را از یک تیم به تیم دیگر منتقل می‌کنند، حتی بدون نوشتن یک خط کد، روی معماری نهایی سیستم اثر می‌گذارند. به همین دلیل، طراحی سازمان و طراحی معماری نرم‌افزار را نمی‌توان از یکدیگر جدا کرد.کتاب برای استفاده آگاهانه از این قانون، مفهوم مانور معکوس کانوی را معرفی می‌کند. در این رویکرد، ابتدا مشخص می‌کنیم دوست داریم سیستم چه معماری‌ای داشته باشد و سپس تیم‌ها و مسیرهای ارتباطی را طوری طراحی می‌کنیم که آن معماری را تقویت کنند. مثلا اگر می‌خواهیم چند سرویس مستقل داشته باشیم، اما همه تیم‌ها برای کوچک‌ترین تغییر به یک تیم مرکزی DBA وابسته باشند، ساختار سازمان با معماری موردنظر ما تضاد دارد. راه‌حل می‌تواند این باشد که مهارت‌های مربوط به پایگاه داده را وارد خود تیم‌های سازنده کنیم تا هر تیم بتواند سرویس و داده‌های خودش را مستقل مدیریت کند.با هماهنگ کردن ساختار تیم‌ها با معماری موردنظر، می‌توان وابستگی به تیم‌های متمرکز را کاهش داد و سرویس‌های مستقل‌تری ایجاد کرد👥 تیم فقط چند نفر کنار هم نیستتیم را نباید صرفا مجموعه‌ای از افراد متخصص دانست. یک تیم واقعی، واحدی زنده با هدف، اعتماد، تجربه، مسئولیت و شیوه یادگیری مشترک است. چون در بسیاری از سازمان‌ها، افراد مثل قطعات قابل‌ تعویض در نظر گرفته می‌شوند. برای یک پروژه چند نفر را کنار هم قرار می‌دهند، بعد از پایان پروژه تیم را منحل می‌کنند و اعضا را به بخش‌های مختلف می‌فرستند. مدتی بعد، برای پروژه‌ای دیگر دوباره ترکیب تازه‌ای ساخته می‌شود.این روش در ظاهر انعطاف‌پذیر است، اما هزینه پنهان بزرگی دارد. اعضای تیم برای اعتماد کردن، شناخت توانایی‌های یکدیگر، پیدا کردن زبان مشترک و رسیدن به هماهنگی واقعی به زمان نیاز دارند. با هر جابه‌جایی، بخش زیادی از این سرمایه انسانی از بین می‌رود. 😕یکی از جملات جالب کتاب این بود که: بهتر است کار را به سمت تیم‌های پایدار ببریم، نه اینکه افراد را دائما به سمت کارهای موقت جابه‌جا کنیم. چون تیم‌های پایدار و بلندمدت به مرور صاحب دانش عمیق‌تری می‌شوند، اشتباهات گذشته را به خاطر می‌سپارند، اعتماد بیشتری می‌سازند و مسئولیت نتیجه کارشان را بهتر می‌پذیرند.کتاب همچنین با اشاره به محدودیت‌های روابط انسانی و عدد دانبار توضیح می‌دهد که تیم‌های کوچک، حدود هفت تا نه نفر، شانس بیشتری برای شکل دادن اعتماد عمیق، ارتباط موثر و تصمیم‌گیری سریع دارند. بزرگ‌تر شدن بی‌دلیل تیم معمولا باعث افزایش جلسات، کانال‌های ارتباطی و سردرگمی می‌شود.🧠 بار شناختی؛ مشکلی که معمولاً دیده نمی‌شودیکی از بخش‌های موردعلاقه من در کتاب، بحث بار شناختی تیم بود.ما معمولا برای برنامه‌ریزی، فقط تعداد افراد و ساعت کاری آن‌ها را محاسبه می‌کنیم؛ انگار ذهن اعضای تیم از قبل هیچ مسئولیت، نگرانی یا پیچیدگی دیگری ندارد. اما هر تیم ظرفیت محدودی برای درک فناوری‌ها، سرویس‌ها، قوانین کسب‌وکار، ابزارها و فرایندها دارد.وقتی یک تیم هم‌زمان باید چندین زبان برنامه‌نویسی، زیرساخت، پایگاه داده، سیستم قدیمی، ابزار استقرار، فرایند امنیتی و سرویس مختلف را مدیریت کند، به‌تدریج تمرکزش را از دست می‌دهد. اعضا دائماً بین موضوعات مختلف جابه‌جا می‌شوند و در نهایت به جای تسلط واقعی، فقط تلاش می‌کنند کارها را somehow جلو ببرند! 😅کتاب بار شناختی را به سه نوع تقسیم می‌کند:🔸 بار ذاتی: پیچیدگی طبیعی کاری که باید یاد بگیریم؛ مثلاً دانش یک زبان برنامه‌نویسی یا فناوری مشخص.🔸 بار اضافی: پیچیدگی‌ای که ارزش مستقیمی ایجاد نمی‌کند؛ مثل حفظ کردن ده‌ها دستور عجیب برای راه‌اندازی یک محیط تست.🔸 بار مرتبط و ارزش‌آفرین: فشاری که صرف حل مسئله اصلی کسب‌وکار، طراحی و خلق راه‌حل بهتر می‌شود.سازمان خوب باید تلاش کند بار اضافی را با اتوماسیون، ابزارهای ساده و پلتفرم‌های مناسب کاهش دهد تا ذهن تیم برای حل مسائل واقعی آزاد بماند. اضافه کردن مسئولیت‌های بیشتر به یک تیم بدون حذف پیچیدگی‌های قبلی، به معنای توانمندسازی نیست؛ گاهی فقط روشی محترمانه برای خسته کردن اعضای تیم است!معماری نیز باید با همین ظرفیت هماهنگ باشد. هیچ بخش از سیستم نباید آن‌قدر بزرگ و پیچیده شود که یک تیم نتواند آن را به‌طور کامل درک، تغییر، اجرا و پشتیبانی کند.🧩 چهار توپولوژی بنیادین تیمییکی از عملی‌ترین بخش‌های کتاب، معرفی چهار نوع اصلی تیم است. نکته مهم این است که هدف، ساختن عنوان‌های شغلی جدید نیست؛ بلکه روشن کردن مأموریت، مرز مسئولیت و شیوه ارتباط تیم‌هاست.چهار ساختار بنیادین کتاب شامل تیم هم‌راستا با جریان، تیم توانمندساز، تیم زیرسیستم پیچیده و تیم یا گروه پلتفرم است🟡 ۱. تیم هم‌راستا با جریانStream-aligned Teamاین تیم، مهم‌ترین نوع تیم در کتاب است. تیم هم‌راستا با جریان روی یک جریان مشخص از ارزش تمرکز دارد؛ مثلا یک محصول، سرویس، سفر کاربر، قابلیت کسب‌ و کار یا گروه خاصی از مشتریان. این تیم باید بتواند کار را تا حد ممکن از ابتدا تا انتها پیش ببرد؛ یعنی فقط کدنویسی نکند، بلکه در طراحی، تست، استقرار، مانیتورینگ، پشتیبانی و دریافت بازخورد نیز نقش داشته باشد. تیم باید به نتیجه‌ای که مشتری دریافت می‌کند نزدیک باشد، نه فقط به بخشی از کد. اگر تیم توسعه یک ویژگی را بسازد، آن را به تیم تست تحویل دهد، سپس تیم تست آن را به تیم استقرار بدهد و بعد تیم عملیات مسئول مشکلات محیط واقعی شود، هیچ‌کس مالک واقعی نتیجه نهایی نیست. هر گروه فقط بخش خودش را انجام می‌دهد و مشکل را به نفر بعدی پاس می‌دهد.تیم هم‌راستا با جریان تلاش می‌کند این پاسکاری‌ها را حذف کند و مالکیت صفر تا صد را در یک تیم پایدار نگه دارد. نمونه شناخته‌شده این تفکر، قانون تیم‌های دوپیتزایی آمازون است؛ تیم‌هایی کوچک که مسئول ساخت و اجرای سرویس خودشان هستند. اصل معروف آن نیز این است:You build it, you run it.یعنی اگر چیزی را می‌سازی، باید مسئول رفتار آن در محیط واقعی هم باشی.🟣 ۲. تیم توانمندسازEnabling Teamگاهی تیم‌های جریان باید فناوری یا روش جدیدی یاد بگیرند؛ مثلا تست خودکار، امنیت نرم‌ افزار، استقرار پیوسته، معماری ابری یا مشاهده‌پذیری. اگر بخواهند همه این موضوعات را به‌ تنهایی و از صفر یاد بگیرند، سرعتشان کاهش پیدا می‌کند.اینجا تیم توانمندساز وارد می‌شود. وظیفه این تیم انجام دائمی کار به جای دیگران نیست؛ بلکه کمک می‌کند تیم‌های دیگر سریع‌تر یاد بگیرند، موانع خود را بشناسند و در نهایت مستقل شوند.به نظرم جالب‌ترین ویژگی تیم توانمندساز این است که باید برای بی‌نیاز شدن دیگران از خودش تلاش کند. اگر یک تیم سال‌ها برای انجام یک کار ساده به تیم توانمندساز وابسته بماند، توانمندسازی واقعی اتفاق نیفتاده است.این تیم نباید از بالا دستور بدهد که چه فناوری‌ای استفاده شود. باید وارد مسئله واقعی تیم شود، درد آن را بفهمد، همراهش کار کند و دانش را منتقل کند. 🌱🟠 ۳. تیم زیرسیستم پیچیدهComplicated-Subsystem Teamبعضی بخش‌های سیستم به دانش تخصصی عمیقی نیاز دارند؛ مثلا یک الگوریتم تشخیص چهره یا مدل ریاضی خاص. منطقی نیست که همه تیم‌های جریان، متخصص عمیق همان حوزه باشند. در چنین شرایطی، یک تیم زیرسیستم پیچیده مسئول توسعه و نگهداری آن بخش می‌شود.تفاوت مهم این تیم با تیم‌های کامپوننت سنتی این است که هر قطعه مشترک نرم‌افزار نباید به یک تیم جدا سپرده شود. تشکیل این نوع تیم فقط زمانی منطقی است که پیچیدگی تخصصی زیرسیستم، بار شناختی سنگینی به تیم‌های دیگر تحمیل کند.یعنی معیار اصلی، «قابل استفاده بودن توسط چند تیم» نیست؛ بلکه عمق تخصص و کاهش بار شناختی است.🔵 ۴. تیم یا گروه پلتفرمPlatform Team / Platform Groupingهدف پلتفرم این است که زندگی تیم‌های توسعه را آسان‌تر کند. تیم پلتفرم قابلیت‌هایی مانند استقرار، مانیتورینگ، ثبت لاگ، محیط تست، زیرساخت یا سرویس‌های مشترک را به شکل سلف‌سرویس ارائه می‌دهد تا تیم‌های جریان مجبور نباشند برای هر کار، منتظر پاسخ یک تیم دیگر بمانند. پلتفرم باید مانند یک محصول واقعی مدیریت شود و تیم‌های توسعه، مشتریان داخلی آن هستند. بنابراین فقط اینکه پلتفرم از نظر فنی کار کند کافی نیست؛ باید استفاده از آن آسان، مستند، قابل‌اعتماد و متناسب با نیاز کاربران باشد.یکی از مفاهیم جالب کتاب Thinnest Viable Platform یا «کمینه‌ترین پلتفرم زیست‌پذیر» است. یعنی پلتفرم نباید از روز اول تبدیل به یک هیولای عظیم و پیچیده شود! 🐉گاهی ساده‌ترین پلتفرم ممکن، فقط یک صفحه راهنما با فهرستی از سرویس‌های تأییدشده است. سپس با مشخص شدن نیازهای واقعی، پلتفرم به‌تدریج رشد می‌کند. در سازمان‌های بزرگ، پلتفرم معمولا فقط یک تیم هشت‌ نفره نیست؛ بلکه می‌تواند گروهی از چند تیم باشد که در کنار هم یک قابلیت منسجم ارائه می‌کنند.🚫 چند ضدالگوی مهم که توجهم را جلب کردکتاب فقط الگوهای خوب را معرفی نمی‌کند؛ درباره اشتباهات رایجی هم هشدار می‌دهد. یکی از این اشتباهات، تشکیل تیم‌ها به‌صورت واکنشی و بدون طراحی بلندمدت است. مثلا بعد از یک خرابی بزرگ، سریعا یک تیم جدید ایجاد می‌شود یا بعد از خرید فناوری ابری، نام تیم زیرساخت به «تیم Cloud» تغییر می‌کند؛ بدون اینکه مسئولیت‌ها، مدل تعامل یا روش ارائه خدمات تغییر کند.تغییر نام، به‌تنهایی ساختار را اصلاح نمی‌کند. 🙂ضدالگوی دیگر، جابه‌جایی دائمی افراد میان پروژه‌هاست. مدیر ممکن است احساس کند منابع را به‌صورت انعطاف‌پذیر مدیریت می‌کند، اما در واقع اعتماد، دانش مشترک و هویت تیمی را از بین می‌برد. همچنین کتاب نسبت به تشکیل یک تیم دائمی DevOps هشدار می‌دهد؛ تیمی که همه تیم‌ها برای استقرار و اجرای کارهایشان به آن وابسته شوند. در این حالت، DevOps به جای حذف گلوگاه، خودش به گلوگاه جدید تبدیل می‌شود.وظیفه درست چنین تیم‌هایی باید ساخت قابلیت‌های سلف‌سرویس، آموزش و انتقال دانش باشد، نه انجام همیشگی مراحل تحویل به جای تیم‌های محصول. کتاب درباره کپی کورکورانه مدل اسپاتیفای نیز هشدار می‌دهد. مفاهیمی مانند Squad، Tribe، Chapter و Guild جالب‌اند؛ اما مدل اسپاتیفای یک تصویر ثابت و نسخه جهانی برای همه سازمان‌ها نبود. این ساختار نتیجه فرهنگ، شرایط و مسیر تکامل همان شرکت بود.این بخش برایم یادآور شد که کپی کردن ظاهر یک مدل، بدون درک مسئله‌ای که آن مدل برای حلش ساخته شده، معمولاً فقط واژه‌های جدیدی به مشکلات قدیمی اضافه می‌کند.✂️ مرزهای نرم‌افزار باید در اندازه یک تیم باشندیکی دیگر از بخش‌های کتاب، انتخاب مرزهای سیستم با رویکرد تیم‌محور بود. وقتی یک سیستم بزرگ را به سرویس‌های کوچک‌تر تقسیم می‌کنیم، نباید فقط بپرسیم مرز فنی مناسب کجاست؛ بلکه باید بپرسیم:کدام تیم مالک این بخش خواهد بود؟آیا آن تیم می‌تواند کل این محدوده را درک کند؟برای تغییر آن، به چند تیم دیگر وابسته خواهد شد؟آیا این مرز با دامنه کسب‌وکار هماهنگ است؟آیا تیم می‌تواند آن را مستقل منتشر و پشتیبانی کند؟کتاب از مفاهیمی مانند Bounded Context در طراحی دامنه‌محور و Fracture Planes یا صفحات شکست استفاده می‌کند تا مرزهای طبیعی سیستم پیدا شوند.گاهی این مرز بر اساس حوزه کسب‌ و کار است، گاهی قوانین و مقررات، موقعیت جغرافیایی، نوع کاربر، نیازهای عملکردی یا حتی تفاوت فناوری‌ها. اما هشدار مهم این است که تقسیم یک مونولیت به چند سرویس، لزوما باعث استقلال نمی‌شود. اگر برای یک تغییر کوچک مجبور باشیم همزمان چند سرویس را تغییر دهیم، با چند تیم هماهنگ شویم و همه‌چیز را با هم منتشر کنیم، فقط یک مونولیت توزیع‌ شده ساخته‌ایم؛ یعنی پیچیدگی قبلی را با شبکه، API و عملیات بیشتر ترکیب کرده‌ایم! 😬مرز خوب مرزی است که به تیم اجازه دهد بخش خودش را با کمترین وابستگی به دیگران تغییر دهد.🤝 آیا همه تیم‌ها باید همیشه با هم همکاری کنند؟یکی از باورهای رایج این است که هرچه ارتباط و همکاری بیشتر باشد، نتیجه بهتر خواهد شد. کتاب این تصور را به‌طور جدی به چالش می‌کشد. ارتباط زیاد هزینه دارد؛ جلسه، هماهنگی، پیام، توضیح، انتظار و جابه‌جایی ذهنی ایجاد می‌کند. اگر همه برای انجام کارشان مجبور باشند دائما با همه صحبت کنند، احتمالا مرزها یا رابط‌های سیستم درست طراحی نشده‌اند.Collaboration vs X-as-a-Serviceکتاب سه حالت اصلی برای تعامل میان تیم‌ها معرفی می‌کند:🤝 Collaboration — همکاری نزدیکاین حالت برای کشف مسئله‌های جدید، آزمایش فناوری تازه و پیدا کردن مرزهای مناسب مفید است. دو تیم برای مدتی با تعامل زیاد کنار هم کار می‌کنند.مزیت آن، یادگیری و نوآوری سریع است؛ اما هزینه‌اش افزایش بار شناختی و کمرنگ شدن مرز مسئولیت‌هاست. بنابراین همکاری نزدیک بهتر است هدفمند و معمولا موقت باشد.اگر دو تیم برای همیشه مجبور باشند روی هر موضوعی با هم همکاری کنند، احتمالا تقسیم مسئولیت یا معماری سیستم نیاز به بازنگری دارد.🔌 X-as-a-Service — ارائه به‌صورت سرویسدر این حالت، یک تیم قابلیت مشخصی مانند API، ابزار یا پلتفرم را ارائه می‌دهد و تیم دیگر با کمترین هماهنگی از آن استفاده می‌کند.این روش مسئولیت‌ها را روشن و تحویل را قابل‌پیش‌بینی می‌کند؛ اما فقط زمانی موفق است که سرویس باکیفیت، قابل‌اعتماد و آسان باشد.اگر مصرف‌کننده برای هر بار استفاده مجبور باشد ساعت‌ها با تیم ارائه‌دهنده جلسه بگذارد، آن رابطه در عمل سرویس‌محور نیست.🌱 Facilitating — تسهیل‌گریدر این حالت، یک تیم به تیم دیگر کمک می‌کند تا مانعی را برطرف کند، مهارت تازه‌ای یاد بگیرد یا روش بهتری برای انجام کار پیدا کند.برای موفقیت این مدل، هم «کمک کردن» و هم «کمک گرفتن» مهارت می‌خواهد. تیم دریافت‌کننده نیز باید ذهن باز داشته باشد و کمک را تهدیدی برای استقلال یا تخصص خودش تلقی نکند. نوع تعامل میان دو تیم نباید برای همیشه ثابت بماند. ممکن است دو تیم ابتدا برای کشف نیازها همکاری نزدیک داشته باشند، سپس بعد از تثبیت API یا سرویس، رابطه‌شان به X-as-a-Service تبدیل شود.حتی پژوهش‌های مطرح‌شده در کتاب نشان می‌دهند که همکاری مقطعی می‌تواند از همکاری دائمی مؤثرتر باشد؛ چون تیم‌ها هم از مزیت تبادل دانش استفاده می‌کنند و هم فرصت تفکر مستقل را از دست نمی‌دهند.📡 سازمان باید مثل یک موجود زنده حس کندبخش پایانی کتاب بنظرم از متفاوت‌ترین قسمت‌ها بود؛ چون توضیح می‌دهد ساختار تیمی نباید یک طراحی ثابت و همیشگی باشد.با تغییر فناوری، بازار، قوانین، اندازه سازمان و نیاز مشتری، ساختار مناسب نیز تغییر می‌کند. چیزی که امروز عالی عمل می‌کند، ممکن است شش ماه دیگر به مانع تبدیل شود. کتاب پیشنهاد می‌کند به اصطکاک میان تیم‌ها مثل یک سیگنال نگاه کنیم.برای مثال:⚠️ اگر تیمی برای انجام کارهای ساده دائما منتظر تیم دیگری است، وابستگی مشکل دارد.⚠️ اگر استفاده از یک پلتفرم به جلسات و توضیحات طولانی نیاز دارد، تجربه توسعه‌ دهنده ضعیف است.⚠️ اگر نرم‌افزار برای یک تیم بیش از حد بزرگ شده، مرزها باید بازطراحی شوند.⚠️ اگر سرعت انتشار کاهش یافته، ممکن است مشکل از خود برنامه‌نویسی نباشد و وابستگی‌های بین تیمی جریان را مسدود کرده باشند.⚠️ اگر یک تیم زیر بار مسئولیت‌ها، ابزارها و فناوری‌های متعدد فرسوده شده، بار شناختی آن از ظرفیتش عبور کرده است.در این نگاه، عملیات و محیط واقعی فقط آخرین مرحله تحویل نیستند؛ بلکه منبعی ارزشمند از داده و بازخوردند. خطاها، رفتار کاربران، مشکلات عملکردی و رخدادهای تولید باید مستقیما به تیم سازنده برگردند. جدا کردن کامل تیم ساخت از تیم نگهداری، این حلقه بازخورد را قطع می‌کند. تیمی که تصمیم‌های فنی را می‌گیرد باید پیامد آن تصمیم‌ها را در دنیای واقعی نیز ببیند. سازمان موفق فقط نرم‌افزار تولید نمی‌کند؛ بلکه دائما به سیگنال‌هایی که از مشتری، سیستم و تعامل تیم‌ها دریافت می‌کند گوش می‌دهد و خودش را اصلاح می‌کند.💡 این کتاب چه تغییری در نگاهم ایجاد کرد؟قبل از مطالعه این کتاب، وقتی صحبت از معماری نرم‌افزار می‌شد، ذهنم بیشتر به سمت میکروسرویس، پایگاه داده، API، زیرساخت و الگوهای طراحی می‌رفت.بعد از خواندن Team Topologies بیشتر متوجه شدم که معماری نرم‌افزار، فقط معماری کد نیست؛ معماری ارتباطات انسانی هم هست.یک معماری زیبا روی کاغذ، زمانی ارزش دارد که تیم‌های واقعی بتوانند آن را بفهمند، مالک آن باشند، تغییرش دهند و در محیط واقعی اجرا کنند.همچنین فهمیدم استقلال تیم به معنای قطع کامل ارتباط با دیگران نیست؛ بلکه یعنی تیم برای انجام کار روزمره خود پشت در تیم‌های دیگر متوقف نشود.این کتاب به من نشان داد که:✨ تیم باید واحد اصلی تحویل ارزش باشد، نه فرد.✨ تیم‌های پایدار از گروه‌های موقت مؤثرترند.✨ ارتباط بیشتر همیشه بهتر نیست؛ ارتباط باید هدفمند باشد.✨ پلتفرم باید پیچیدگی را پنهان کند، نه اینکه پیچیدگی تازه‌ای بسازد.✨ تیم توانمندساز باید دانش را پخش کند، نه اینکه آن را انحصاری نگه دارد.✨ مرزهای نرم‌افزار باید با ظرفیت شناختی تیم هماهنگ باشند.✨ ساختار تیم‌ها و نوع تعامل آن‌ها باید در طول زمان تکامل پیدا کند.✨ معیار نهایی موفقیت، تعداد خروجی‌ها یا سرعت کدنویسی نیست؛ بلکه سرعت و کیفیت رسیدن ارزش واقعی به مشتری است.🌟 حرف آخربرای من مهم‌ترین پیام کتاب این بود:برای ساختن نرم‌افزار بهتر، فقط نباید کد و فناوری را طراحی کنیم؛ باید تیم‌ها و تعاملات میان آن‌ها را نیز آگاهانه طراحی کنیم.سازمانی که انسان‌ها را فقط به‌عنوان منابع قابل‌جابه‌جایی ببیند، نمی‌تواند انتظار تیم‌های منسجم، معماری پایدار و جریان سریع ارزش داشته باشد. تیم خوب به زمان، اعتماد، مرز روشن، هدف مشترک و فضای کافی برای یادگیری نیاز دارد. معماری خوب نیز باید از همین واقعیت‌های انسانی پشتیبانی کند.اگر به معماری نرم‌افزار، کار تیمی، DevOps، مدیریت محصول یا طراحی سازمان علاقه دارید، پیشنهاد می‌کنم کتاب Team Topologies را تهیه یا دانلود کنید و با دقت بخوانید. 📥📚این کتاب از آن دسته کتاب‌هایی است که فقط چند مفهوم جدید به شما یاد نمی‌دهد؛ بلکه باعث می‌شود بسیاری از مشکلات قدیمی تیم و سازمانتان را با زاویه‌ای کاملاً متفاوت ببینید.احتمالا هنگام مطالعه بارها با خودتان خواهید گفت:«پس دلیل این همه جلسه، انتظار، پاسکاری و وابستگی در تیم ما همین بوده!» 😅و شاید بعد از خواندن آن، نگاهتان به مفهوم تیم، معماری و حتی مدیریت سازمان برای همیشه تغییر کند. 🌱✨اين مطلب، بخشی از تمرين‌های درس معماری نرم‌افزار در دانشگاه شهيد بهشتی است 🌱نویسنده: امین مستوری نژاددانشجوی مهندسی نرم افزار دانشگاه شهید بهشتیمرداد 1405</description><category>امین مستوری نژاد</category><author>امین مستوری نژاد</author><pubDate>Fri, 31 Jul 2026 11:55:59 +0330</pubDate></item><item><title>معماری نرم‌افزار را از دل پروژه‌های واقعی یاد بگیریم</title><link>https://virgool.ir/@amin.montazer1381/معماری-نرم-افزار-را-از-دل-پروژه-های-واقعی-یاد-بگیریم-k7hmzzhx1a9h</link><description>بیشتر کتاب‌های معماری نرم‌افزار از الگوها، سبک‌های معماری و اصول طراحی صحبت می‌کنند؛ اما همیشه یک سؤال مهم باقی می‌ماند: این اصول در یک نرم‌افزار واقعی، بزرگ و چندساله چگونه به کار گرفته می‌شوند؟کتاب The Architecture of Open Source Applications, Volume II: Structure, Scale, and a Few More Fearless Hacks دقیقاً به همین سؤال پاسخ می‌دهد. این کتاب به‌جای ارائه یک معماری فرضی و بی‌نقص، ما را به پشت صحنه تعدادی از مشهورترین پروژه‌های متن‌باز می‌برد و نشان می‌دهد که معماری آن‌ها چگونه شکل گرفته، چه مشکلاتی را حل کرده و در طول زمان چطور تغییر کرده است.مشخصات کتابنام کتاب: The Architecture of Open Source Applications, Volume II: Structure, Scale, and a Few More Fearless Hacksویراستاران: Amy Brown و Greg Wilsonموضوع: بررسی معماری واقعی نرم‌افزارهای متن‌باززبان: انگلیسیتعداد صفحات: ۳۸۹ صفحه در نسخه PDFتعداد فصل‌ها: ۲۴ فصلاین کتاب با مجوز Creative Commons Attribution 3.0 منتشر شده و نسخه کامل آن به‌صورت رایگان در دسترس است: https://ia801609.us.archive.org/13/items/aosa_v2/aosa_v2.pdfایده اصلی کتاب چیست؟نکته‌ای که از همان مقدمه کتاب توجه من را جلب کرد، مقایسه معماری ساختمان با معماری نرم‌افزار بود. یک معمار ساختمان در طول دوران آموزش و فعالیت حرفه‌ای خود، نمونه‌های بسیار زیادی از ساختمان‌ها را بررسی می‌کند؛ اما یک توسعه‌ دهنده نرم‌افزار معمولا فرصت ندارد ساختار داخلی تعداد زیادی نرم‌افزار بزرگ را از نزدیک ببیند. در نتیجه، ممکن است اشتباه‌هایی را تکرار کند که تیم‌های دیگر سال‌ها قبل با آن‌ها روبه‌رو شده‌اند.هدف این مجموعه آن است که طراحی نرم‌افزار را از طریق نمونه‌های واقعی آموزش دهد. یعنی به‌جای آنکه فقط بگوید یک سیستم «باید» چگونه طراحی شود، نشان می‌دهد سیستم‌های واقعی با محدودیت‌های فنی، نیازهای کاربران، کدهای قدیمی، تغییر فناوری و رشد پروژه چگونه کنار آمده‌اند. ویراستاران کتاب نیز تأکید می‌کنند که یکی از بهترین راه‌های یادگیری تفکر حرفه‌ای، بررسی شیوه فکر کردن متخصصان است.چه پروژه‌هایی در کتاب بررسی شده‌اند؟تنوع فصل‌های کتاب یکی از جذاب‌ترین ویژگی‌های آن است. در این کتاب معماری پروژه‌هایی مانند Git، nginx، MediaWiki، Moodle، matplotlib، Puppet، PyPy، SQLAlchemy، Twisted، ZeroMQ، FreeRTOS، GDB و Glasgow Haskell Compiler بررسی می‌شود. یک فصل نیز به معماری سیستم‌های توزیع‌شده و وب مقیاس‌پذیر اختصاص دارد و فصل دیگری فرایند مهندسی انتشار Firefox را توضیح می‌دهد.این تنوع باعث می‌شود معماری را فقط در قالب یک نوع نرم‌افزار نبینیم. بعضی فصل‌ها درباره وب‌سرورها هستند، بعضی درباره کامپایلرها، سیستم‌عامل‌های بلادرنگ، ابزارهای توسعه، سیستم‌های آموزشی، کتابخانه‌های علمی، زیرساخت‌های انتشار و سامانه‌های پیام‌رسانی صحبت می‌کنند.نکته مهم این است که فصل‌ها فقط معرفی پروژه نیستند. نویسندگان معمولا توضیح می‌دهند که پروژه از چه مسئله‌ای شروع شده، اجزای اصلی آن چیست، چه تصمیم‌هایی در طراحی گرفته شده و کدام انتخاب‌ها در ادامه نیازمند اصلاح بوده‌اند.معماری همیشه مجموعه‌ای از بده‌بستان‌هاستدر معماری نرم‌افزار تقریبا هیچ تصمیمی بدون هزینه نیست. در فصل نخست، ویژگی‌هایی مانند دسترس‌پذیری، کارایی، قابلیت اطمینان، مقیاس‌پذیری، مدیریت‌پذیری و هزینه در کنار یکدیگر بررسی می‌شوند. افزایش یکی از این ویژگی‌ها ممکن است ویژگی دیگری را تحت تأثیر قرار دهد؛ برای مثال، افزودن سرورهای بیشتر می‌تواند مقیاس‌پذیری را افزایش دهد، اما همزمان هزینه و پیچیدگی نگهداری سیستم را نیز بیشتر می‌کند.این فصل با مثال یک سامانه میزبانی تصویر، موضوعاتی مانند جداسازی سرویس خواندن و نوشتن، افزونگی، پارتیشن‌بندی داده، کش، پراکسی، ایندکس، متعادل‌سازی بار و صف را توضیح می‌دهد. چیزی که این بخش را کاربردی می‌کند، تأکید آن بر این موضوع است که یک راه‌حل واحد برای تمام سیستم‌ها وجود ندارد. ابتدا باید الگوی استفاده، حجم داده، تعداد درخواست‌ها، نوع خرابی‌ها و محدودیت‌های هزینه مشخص شود و سپس درباره معماری تصمیم گرفت.معماری فقط ساختار کد نیستفصل مربوط به Firefox Release Engineering نگاه جالبی به معماری دارد. در این فصل متوجه می‌شویم که معماری یک محصول بزرگ فقط شامل ماژول‌ها، کلاس‌ها و سرویس‌ها نیست؛ فرایند انتشار، خودکارسازی، تست، امضای دیجیتال، هماهنگی تیم‌ها و مدیریت خطاهای انسانی نیز بخشی از معماری عملیاتی سیستم محسوب می‌شوند.تیم موزیلا تلاش کرده بود دخالت‌های دستی را در فرایند انتشار Firefox کاهش دهد، زیرا هر مرحله دستی می‌توانست فرصتی برای ایجاد خطای انسانی باشد. یکی از درس‌های مهم این فصل، انجام بررسی پس از هر انتشار و اصلاح حداقل یک مشکل قبل از انتشار بعدی است. این رویکرد نشان می‌دهد که معماری خوب الزاما با یک باز طراحی بزرگ به وجود نمی‌آید؛ گاهی حاصل مجموعه‌ای از بهبودهای کوچک، پیوسته و آگاهانه است.چرا فصل nginx برایم جذاب بود؟فصل nginx نمونه خوبی از معماری‌ای است که بر اساس یک مسئله مشخص شکل گرفته است. وب‌سرورهای قدیمی‌تر معمولا برای هر اتصال، پردازه یا رشته جدیدی ایجاد می‌کردند. این روش در بارهای پایین قابل قبول بود، اما با افزایش شدید تعداد اتصال‌ها، مصرف حافظه و پردازنده نیز بالا می‌رفت.nginx با معماری رویدادمحور طراحی شد تا بتواند تعداد زیادی اتصال هم‌زمان را با مصرف منابع کنترل‌شده مدیریت کند. این فصل نشان می‌دهد که موفقیت nginx فقط نتیجه سریع‌تر بودن کد آن نیست؛ بلکه از شناخت درست مسئله، تمرکز بر هدف اصلی و انتخاب یک ساختار معماری متناسب با آن ناشی شده است. یکی از درس‌های پایانی این فصل نیز اهمیت ساختار اولیه کد و تمرکز تیم توسعه بر قابلیت‌های اصلی محصول است.نمودار معماری nginxنقطه قوت اصلی کتاببه نظرم مهم‌ترین مزیت کتاب این است که معماری را به‌عنوان یک تصویر ثابت و نهایی نمایش نمی‌دهد. پروژه‌های معرفی‌شده در کتاب طی سال‌ها تغییر کرده‌اند، نیازهای تازه‌ای پیدا کرده‌اند، با محدودیت‌های جدید رو به‌ رو شده‌اند و گاهی مجبور شده‌اند بخش‌هایی از معماری قدیمی خود را بازطراحی کنند.در بعضی فصل‌ها حتی درباره تصمیم‌هایی صحبت می‌شود که در زمان خود منطقی بوده‌اند، اما بعدا به مانعی برای توسعه تبدیل شده‌اند. همین صداقت باعث می‌شود کتاب واقعی‌تر از منابعی باشد که فقط نسخه نهایی و مرتب یک معماری را نشان می‌دهند.بنظرم معماری نرم‌افزار بیشتر از آنکه انتخاب چند فناوری یا ترسیم چند نمودار باشد، فرایند تصمیم‌گیری در شرایط محدودیت و تغییر است. یک معمار باید بداند چرا تصمیمی گرفته شده، چه هزینه‌ای دارد و در چه زمانی باید آن را بازنگری کند.آیا قدیمی بودن کتاب مشکل ایجاد می‌کند؟نسخه دوم کتاب در سال ۲۰۱۳ منتشر شده است؛ بنابراین طبیعی است که بعضی فناوری‌ها، نسخه نرم‌افزارها و آمارهای مطرح‌شده در آن قدیمی باشند. بااین‌حال، ارزش اصلی کتاب در نام ابزارها یا نسخه‌های خاص نیست، بلکه در شیوه تحلیل مسائل معماری است.موضوعاتی مانند جداسازی مسئولیت‌ها، مدیریت پیچیدگی، مقیاس‌پذیری، افزونگی، خودکارسازی، توسعه‌پذیری، کنترل وابستگی‌ها و تکامل تدریجی سیستم همچنان از مسائل اصلی پروژه‌های نرم‌افزاری هستند. به همین دلیل، هنگام مطالعه بهتر است بیشتر بر منطق تصمیم‌ها تمرکز کنیم تا جزئیات مربوط به نسخه‌های قدیمی فناوری‌ها.این کتاب برای چه کسانی مناسب است؟این کتاب برای دانشجویان مهندسی نرم‌افزار، برنامه‌نویسان، طراحان سیستم و افرادی که قصد دارند وارد حوزه معماری نرم‌افزار شوند، منبع ارزشمندی است. البته برخی فصل‌ها تخصصی‌اند و ممکن است برای مطالعه آن‌ها به آشنایی اولیه با سیستم‌عامل، شبکه، کامپایلر، پایگاه داده یا سیستم‌های توزیع‌شده نیاز باشد.ساختار مستقل فصل‌ها یک مزیت مهم محسوب می‌شود؛ لازم نیست کتاب را حتما از ابتدا تا انتها و به‌ترتیب مطالعه کرد. می‌توان بر اساس علاقه، فصل مربوط به Git، nginx، MediaWiki، SQLAlchemy، ZeroMQ یا هر پروژه دیگری را انتخاب کرد و سپس سراغ فصل‌های بعدی رفت.جمع‌بندیکتاب The Architecture of Open Source Applications, Volume II فرصتی فراهم می‌کند تا معماری را نه در قالب مثال‌های کوچک دانشگاهی، بلکه در دل نرم‌افزارهایی ببینیم که سال‌ها توسعه یافته‌اند و کاربران واقعی داشته‌اند.پس از مطالعه این کتاب، معماری نرم‌افزار برای من کمتر شبیه مجموعه‌ای از قوانین قطعی و بیشتر شبیه مجموعه‌ای از تصمیم‌های منطقی، بده‌بستان‌ها، تجربه‌ها و اصلاحات پیوسته به نظر می‌رسد. شاید مهم‌ترین پیام کتاب این باشد که برای ساختن سیستم‌های بهتر، فقط نباید موفقیت پروژه‌های دیگر را ببینیم؛ باید دلیل تصمیم‌ها، محدودیت‌ها، اشتباه‌ها و مسیر تکامل آن‌ها را نیز بررسی کنیم.این کتاب دقیقا چنین امکانی را فراهم می‌کند و به همین دلیل، می‌تواند منبعی جذاب برای هرکسی باشد که می‌خواهد معماری نرم‌افزار را از تجربه پروژه‌های واقعی یاد بگیرد.منبع و دریافت کتابBrown, Amy &amp; Wilson, Greg (Editors)The Architecture of Open Source Applications, Volume II: Structure, Scale, and a Few More Fearless Hacksدانلود و مطالعه رایگان نسخه PDF کتابوب‌سایت رسمی مجموعه: www.aosabook.orgنویسنده: امین مستوری نژاددانشجوی مهندسی نرم افزار دانشگاه شهید بهشتیتیر 1405</description><category>امین مستوری نژاد</category><author>امین مستوری نژاد</author><pubDate>Sat, 11 Jul 2026 12:45:08 +0330</pubDate></item><item><title>زیرساخت باید در خدمت برنامه باشد، نه مانعی در مسیر آن</title><link>https://virgool.ir/@amin.montazer1381/زیرساخت-باید-در-خدمت-برنامه-باشد-نه-مانعی-در-مسیر-آن-i8pmt74pm6gt</link><description>عنوان سخنرانی: Application-Driven Infrastructureهمایش: XConf Europe 2025سخنران: Kief Morrisبرگزارکننده: Thoughtworksمدت ویدئو: ۲۷ دقیقه و ۱۹ ثانیهلینک ویدئو: https://youtu.be/sG3Cgf8x0_k?si=iLX2jNLDTNBWEFoAامروزه بسیاری از سازمان‌ها از رایانش ابری، خطوط تحویل خودکار و زیرساخت به‌عنوان کد استفاده می‌کنند؛ اما با وجود این ابزارها، آماده‌سازی محیط و زیرساخت همچنان می‌تواند یکی از کندترین بخش‌های توسعه نرم‌افزار باشد. مهم‌ترین برداشتی که من از سخنرانی Application-Driven Infrastructure داشتم این بود که خودکارسازی به‌تنهایی کافی نیست. اگر فرایند قدیمی حفظ شود و فقط اجرای آن با ابزارهای جدید انجام شود، همچنان تیم توسعه برای دریافت پایگاه داده، شبکه، دسترسی یا محیط اجرایی باید درخواست ثبت کند و منتظر تیم زیرساخت بماند. در این حالت، ابزارها مدرن شده‌اند، اما شیوه همکاری و معماری تحویل زیرساخت تغییر اساسی نکرده است.Kief Morris مدل سنتی را به‌صورت رویکردی از پایین به بالا توصیف می‌کند. در این مدل، تیم زیرساخت ابتدا یک محیط بزرگ و تقریبا یکپارچه می‌سازد و سپس تیم‌های برنامه باید راهی برای اجرای نرم‌افزار خود در همان محیط پیدا کنند. مشکل اینجاست که زیرساخت بدون شناخت دقیق نیازهای هر برنامه طراحی می‌شود و برای هر تغییر نیز هماهنگی میان چند تیم ضروری است. نتیجه معمولا ایجاد صف درخواست‌ها، انتظار طولانی، وابستگی سازمانی و کاهش سرعت تحویل نرم‌افزار است. حتی اگر همه منابع با Terraform یا ابزارهای مشابه ایجاد شوند، این وابستگی همچنان باقی می‌ماند؛ زیرا کنترل فرایند هنوز در اختیار یک تیم مرکزی است.راه‌حل پیشنهادی سخنران، معکوس‌کردن جهت کنترل زیرساخت است. در رویکرد زیرساخت برنامه‌محور، نقطه شروع دیگر سرور، شبکه یا کلاستر نیست؛ بلکه خود برنامه و نیازهای آن است. تیم توسعه مشخص می‌کند برنامه برای اجرا به چه قابلیت‌هایی نیاز دارد؛ مثلا یک پایگاه داده امن، فضای ذخیره‌سازی، صف پیام یا سرویس مشاهده‌پذیری. سپس هم‌زمان با استقرار برنامه، مولفه‌های زیرساختی مناسب به‌صورت خودکار ایجاد و پیکربندی می‌شوند. به‌جای اینکه توسعه‌دهنده پس از آماده‌شدن یک محیط عمومی تلاش کند برنامه را با آن سازگار کند، زیرساخت لازم بر اساس نیاز برنامه و در زمان مناسب در اختیارش قرار می‌گیرد.یکی از مفاهیم اصلی سخنرانی، طراحی زیرساخت به شکل مؤلفه‌های قابل‌ترکیب است. به نظر من، این بخش ارتباط روشنی با معماری ماژولار در نرم‌افزار دارد. همان‌طور که یک برنامه بزرگ را به اجزای دارای مسئولیت و رابط مشخص تقسیم می‌کنیم، زیرساخت نیز نباید یک مجموعه عظیم و وابسته باشد. می‌توان قابلیت‌هایی مانند پایگاه داده، شبکه، مدیریت رازها و مانیتورینگ را به اجزایی استاندارد تبدیل کرد که هرکدام قرارداد و گزینه‌های پیکربندی مشخصی دارند. تیم برنامه این اجزا را متناسب با نیاز خود انتخاب و ترکیب می‌کند، بدون آنکه مجبور باشد جزئیات سطح پایین پیاده‌سازی تمام آن‌ها را بداند. Morris در توضیح تحول Infrastructure as Code نیز بر اهمیت ماژول‌ها، پشته‌ها و ترکیب چند مولفه زیرساختی تاکید می‌کند.نکته مهم این است که خودخدمتی به معنای آزادی بدون کنترل نیست. در نگاه اول ممکن است تصور شود واگذاری ایجاد زیرساخت به تیم‌های برنامه، امنیت و یکپارچگی را کاهش می‌دهد؛ اما سخنران جداسازی مسئولیت‌ها را پیشنهاد می‌کند. تیم پلتفرم می‌تواند یک مولفه استاندارد برای ایجاد پایگاه داده طراحی کند که الزامات امنیتی، پشتیبان‌گیری، رمزنگاری، ثبت رخداد و سیاست‌های سازمانی از ابتدا در آن قرار داده شده باشد. تیم برنامه فقط نوع سرویس و پارامترهای مجاز را مشخص می‌کند. بنابراین، کنترل و استانداردهای سازمانی حذف نمی‌شوند؛ بلکه به‌جای بررسی دستی هر درخواست، درون مولفه‌ها و فرایند خودکار قرار می‌گیرند.این شیوه از نظر امنیتی نیز جداسازی مناسبی ایجاد می‌کند. توسعه‌دهنده لازم نیست مجوز مستقیم ساخت تمام منابع ابری را داشته باشد. او نیاز برنامه را اعلام می‌کند و یک کنترل‌گر یا سرویس پلتفرم که مجوزهای لازم را دارد، زیرساخت موردنیاز را ایجاد می‌کند. در نتیجه، تیم برنامه اختیار کافی برای انجام کار خود دارد، اما به دسترسی گسترده و خطرناک نیاز ندارد. از دید من، این تعادل میان استقلال تیم و حاکمیت سازمانی یکی از مهم‌ترین مزایای رویکرد مطرح‌شده در سخنرانی است.هم‌راستا‌شدن چرخه عمر برنامه و زیرساخت نیز نکته ارزشمند دیگری بود. در معماری سنتی، ممکن است منابع زیرساختی مدت‌ها پس از پایان آزمایش یا حذف برنامه همچنان باقی بمانند و هزینه ایجاد کنند. در مدل برنامه‌محور، زیرساخت می‌تواند همراه با برنامه ایجاد، تغییر و در صورت بی‌نیازی حذف شود. این هماهنگی علاوه بر کاهش کار دستی، دید بهتری نسبت به مالکیت و هزینه منابع فراهم می‌کند؛ زیرا مشخص است هر منبع برای کدام برنامه و با چه هدفی ایجاد شده است. مقاله Morris درباره Infrastructure as Data نیز توضیح می‌دهد که منابع می‌توانند بر اساس توصیف استقرار برنامه و از طریق یک حلقه کنترل، به‌طور مداوم با وضعیت موردانتظار هماهنگ نگه داشته شوند.ساخت یک پلتفرم داخلی نباید به پنهان‌کردن کامل زیرساخت از توسعه‌دهنده منجر شود. هدف این نیست که تیم برنامه هیچ درکی از کارایی، امنیت، ظرفیت یا هزینه نداشته باشد؛ بلکه باید جزئیات کم‌ارزش و تکراری از مسیر او حذف شوند تا بتواند روی تصمیم‌های مرتبط با محصول تمرکز کند. یک پلتفرم خوب مسیر معمول را ساده می‌کند، اما در صورت وجود نیاز واقعی، باید امکان گسترش و افزودن قابلیت‌های جدید را نیز فراهم سازد. اگر تمام تغییرها همچنان فقط توسط تیم مرکزی انجام شوند، همان صف قدیمی این بار پشت یک پرتال زیباتر پنهان خواهد شد. مطالب پیشین Morris درباره معماری پلتفرم نیز میان توانمندسازی تیم‌ها و محدودکردن آن‌ها تفاوت قائل می‌شود.به نظر من، اجرای این رویکرد فقط با خرید یک ابزار یا ایجاد یک پرتال Self-Service کامل نمی‌شود. مؤلفه‌ها باید رابط‌های پایدار، نسخه‌بندی روشن، تست خودکار، مستندات مناسب و مشاهده‌پذیری کافی داشته باشند. تیم پلتفرم نیز باید مصرف‌کنندگان خود را مانند کاربران یک محصول در نظر بگیرد و کیفیت تجربه توسعه‌دهنده را بررسی کند. معیار موفقیت نباید صرفا تعداد منابع ساخته‌شده یا میزان استفاده از Terraform باشد؛ بلکه باید دید آیا زمان انتظار تیم‌ها کاهش یافته، تغییرات سریع‌تر و مطمئن‌تر منتشر شده‌اند و تیم‌های برنامه استقلال بیشتری پیدا کرده‌اند یا خیر. سخنران در معرفی نسخه دیگر این ارائه نیز بر ایجاد بهبودهای قابل‌اندازه‌گیری در اثربخشی تحویل نرم‌افزار تاکید می‌کند.در مجموع، این سخنرانی باعث شد تفاوت میان خودکارکردن زیرساخت و اصلاح معماری تحویل زیرساخت را بهتر درک کنم. ممکن است یک سازمان از ابزارهای پیشرفته استفاده کند، اما همچنان ساختاری کند و وابسته داشته باشد. زیرساخت برنامه‌محور تلاش می‌کند کنترل را به محل شناخت نیاز منتقل کند: تیم برنامه نیاز را مشخص می‌کند و پلتفرم آن را با استفاده از مؤلفه‌های استاندارد، امن و قابل‌ترکیب اجرا می‌کند. به نظرم، پیام اصلی سخنرانی این است که زیرساخت زمانی ارزشمند است که مسیر ارائه نرم‌افزار را کوتاه‌تر کند؛ نه اینکه خود به محصولی پیچیده تبدیل شود که تیم‌ها برای عبور از آن به درخواست، هماهنگی و انتظار نیاز داشته باشند.منابعویدئوی رسمی Application-Driven Infrastructure در کانال Thoughtworks :https://youtu.be/sG3Cgf8x0_k?si=iLX2jNLDTNBWEFoAصفحه رسمی XConf Europe 2025 در Thoughtworks :https://www.thoughtworks.com/about-us/events/xconf/2025/europeگفت‌وگوی Infrastructure as Code in 2025 با Kief Morris :https://www.thoughtworks.com/insights/podcasts/technology-podcasts/infrastructure-as-code-in-2025مقاله Infrastructure as Data نوشته Kief Morris :https://infrastructure-as-code.com/posts/infrastructure-as-data.htmlاين مطلب، بخشی از تمرين‌های درس معماری نرم‌افزار در دانشگاه شهيدبهشتی است 🌱</description><category>امین مستوری نژاد</category><author>امین مستوری نژاد</author><pubDate>Sat, 11 Jul 2026 00:19:21 +0330</pubDate></item><item><title>نوسازی برای نوآوری؛ چگونه معماری‌های قدیمی را بدون یک بازنویسی پرخطر متحول کنیم؟</title><link>https://virgool.ir/@amin.montazer1381/نوسازی-برای-نوآوری-چگونه-معماری-های-قدیمی-را-بدون-یک-بازنویسی-پرخطر-متحول-کنیم-klqdeosg7wc1</link><description>عنوان سخنرانی: Renovate to Innovate: Fundamentals of Transforming Legacy Architectureترجمه عنوان: نوسازی برای نوآوری؛ مبانی تحول معماری‌های قدیمیسخنران: Rashmi Venugopalهمایش: QCon San Francisco 2024مدت ویدئو: ۳۰ دقیقه و ۵۵ ثانیهلینک ویدئو: https://youtu.be/brHepv_JNNg?si=GyCpb_SuZ1v1PleSوقتی اصطلاح «سیستم قدیمی» یا Legacy System را می‌شنویم، معمولا سیستمی فرسوده، ناکارآمد و پر از بدهی فنی را تصور می‌کنیم که باید هرچه سریع‌تر کنار گذاشته شود. اما قدیمی‌شدن یک سیستم همیشه نشانه طراحی بد یا شکست تیم فنی نیست. گاهی یک سیستم دقیقا به این دلیل به Legacy تبدیل می‌شود که در گذشته موفق بوده، مدت زیادی مورد استفاده قرار گرفته و کسب‌ و کار از توانایی‌های اولیه آن فراتر رفته است. سخنران تاکید می‌کند که سیستم‌های قدیمی، تا حدی محصول طبیعی موفقیت و رشد سازمان هستند؛ مسئله اصلی این نیست که چرا چنین سیستم‌هایی به وجود آمده‌اند، بلکه این است که آیا سازمان توانایی نوسازی آن‌ها را دارد یا اجازه می‌دهد مانع رشد آینده شوند.تعریفی که در این سخنرانی از سیستم Legacy ارائه می‌شود، این هست که یک سیستم فقط به دلیل استفاده از فناوری قدیمی، Legacy محسوب نمی‌شود؛ بلکه زمانی می‌توان آن را قدیمی دانست که دیگر نتواند با نیازهای در حال تغییر کسب‌وکار همراه شود. چنین سیستمی ممکن است هنوز کار کند، اما اضافه‌کردن قابلیت جدید به آن بیش از حد زمان ببرد، نگهداری آن پرهزینه باشد یا کیفیت تجربه کاربران به‌ تدریج کاهش پیدا کند. این نگاه باعث می‌شود سلامت معماری را فقط با جدیدبودن زبان برنامه‌ نویسی یا ابزارهای آن نسنجیم، بلکه توانایی سیستم برای پشتیبانی از اهداف فعلی و آینده کسب‌وکار را نیز در نظر بگیریم.سخنران سه نوع پیچیدگی را از نشانه‌های مهم سیستم‌های قدیمی معرفی می‌کند. نخست، پیچیدگی سازمانی است؛ یعنی زمانی که انجام یک تغییر ساده به هماهنگی میان چندین تیم و فرد نیاز دارد. دوم، پیچیدگی عملیاتی است که بر اثر ضعف در خودکارسازی، تست، مانیتورینگ و مشاهده‌پذیری ایجاد می‌شود. سوم نیز پیچیدگی شناختی است؛ حالتی که در آن دانش سیستم فقط در ذهن چند نفر باقی مانده، مستندات به‌روز نیستند و درک معماری برای اعضای جدید دشوار شده است. نتیجه مشترک این پیچیدگی‌ها، کاهش سرعت نوآوری است. در چنین شرایطی، ممکن است انتظار مدیران این باشد که یک قابلیت در چند هفته آماده شود، اما ساختار سیستم باعث شود همان کار ماه‌ها طول بکشد.بخش دیگری از سخنرانی به دلایل قدیمی‌ شدن سیستم‌ها اختصاص دارد. علاوه بر تغییر سریع فناوری، دو مفهوم فرسودگی تدریجی نرم‌افزار و آنتروپی معماری مطرح می‌شوند. فرسودگی تدریجی می‌تواند به‌صورت کدهای استفاده‌نشده، تکرار کد، مستندات ناقص یا از دست‌ رفتن دانش افراد ظاهر شود. آنتروپی معماری نیز زمانی افزایش پیدا می‌کند که قابلیت‌های جدید بدون توجه کافی به ساختار اولیه به سیستم اضافه شوند. معمولا این تغییرات با هدف تحویل سریع‌تر انجام می‌شوند، اما تکرار آن‌ها به‌مرور انسجام معماری را کاهش می‌دهد. معماری‌ها معمولا در یک اتفاق بزرگ خراب نمی‌شوند؛ بلکه مجموعه‌ای از تصمیم‌های کوچک و ظاهرا منطقی، به‌ تدریج آن‌ها را به ساختاری دشوار برای نگهداری تبدیل می‌کند.یکی از بخش‌های روشن و کاربردی ارائه، تفاوت میان بازآرایی کد و نوسازی فنی بود. سخنران برای توضیح این تفاوت از مثال کمد لباس استفاده می‌کند. بازآرایی مانند مرتب‌کردن وسایل داخل کمد است؛ ساختار اصلی حفظ می‌شود، اما محتویات منظم‌تر و قابل‌ دسترسی‌تر می‌شوند. نوسازی فنی شبیه خراب‌کردن دیوار و تبدیل یک کمد معمولی به فضای بزرگ‌تر و متفاوت است. در بازآرایی، قابلیت‌های اصلی سیستم تغییر نمی‌کنند؛ اما نوسازی زمانی انجام می‌شود که ساختار موجود دیگر پاسخ‌گوی نیازهای جدید نیست و باید توانایی‌هایی ایجاد شود که قبلا وجود نداشته‌اند. بنابراین بازنویسی یا تغییر معماری نباید واکنش همیشگی ما به بدهی فنی باشد؛ گاهی بازآرایی کافی است و گاهی تغییر بنیادین ضرورت دارد.برای اجرای موفق نوسازی، نخستین راهکار سخنران استفاده از معماری تکاملی است. در این رویکرد، معماری از ابتدا یک ساختار کامل و تغییرناپذیر در نظر گرفته نمی‌شود، بلکه با تغییر نیازهای کسب‌ و کار تکامل پیدا می‌کند. تیم ابتدا باید شاخص‌هایی قابل‌ اندازه‌گیری برای ویژگی‌های مهم سیستم، مانند کارایی، مقیاس‌پذیری، امنیت یا نگهداری‌پذیری، تعریف کند. سپس تغییرات به‌ صورت کوچک انجام شوند، مرتب منتشر شوند و نتیجه آن‌ها با این معیارها ارزیابی شود. تحویل مداوم و حلقه‌های بازخورد نیز کمک می‌کنند تیم بدون انجام یک مهاجرت بزرگ و یک‌باره، مسیر خود را به‌تدریج اصلاح کند.راهبرد دوم با عبارت «ابتدا کاری کن که کار کند، سپس درستش کن و در نهایت سریعش کن» توضیح داده می‌شود. در مرحله اول، هدف اثبات امکان‌ پذیر بودن راه‌حل و ساخت یک نمونه اولیه است؛ نه رسیدن به کدی بی‌نقص. در مرحله دوم، تست‌ها، حالت‌های مرزی و معیارهای کیفی بررسی می‌شوند و راه‌حل به یک محصول حداقلی قابل‌استفاده تبدیل می‌شود. مرحله سوم نیز فقط به افزایش سرعت اجرای برنامه مربوط نیست؛ مستندسازی، تحویل مداوم، مانیتورینگ و مشاهده‌ پذیری نیز در این مرحله قرار می‌گیرند، زیرا سرعت توسعه و عملیات تیم را افزایش می‌دهند. به نظرم، این تقسیم‌بندی از گرفتارشدن تیم در کمال‌گرایی و تحلیل بیش‌ از حد جلوگیری می‌کند و یک پروژه بزرگ نوسازی را به نقاط عطف قابل‌ کنترل تبدیل می‌سازد.سومین راهکار، توسعه مبتنی بر کنارگذاری یا Deprecation-Driven Development است. معمولا در پروژه‌های نرم‌افزاری موفقیت با تعداد قابلیت‌های جدید سنجیده می‌شود، درحالی‌که حذف کدها، فناوری‌ها و قابلیت‌های کم‌ارزش نیز می‌تواند به همان اندازه مهم باشد. سخنران پیشنهاد می‌کند پیش از انتقال تمام قابلیت‌های سیستم قدیمی، ارزش واقعی هرکدام بررسی شود. اگر هزینه نگهداری یا مهاجرت یک قابلیت بیشتر از ارزش تجاری آن باشد، شاید بهترین تصمیم حذف آن باشد. مثال پایان سرویس DVD نتفلیکس نشان می‌دهد که کنارگذاشتن آگاهانه یک محصول می‌تواند اولویت‌های مهندسی را روشن کند و از ادامه سرمایه‌گذاری روی بخشی که دیگر با آینده کسب‌ و کار هماهنگ نیست، جلوگیری کند.راهبرد چهارم به طراحی آگاهانه ساختار سازمان مربوط است. معماری نرم‌افزار را نمی‌توان مستقل از نحوه سازمان‌دهی تیم‌ها تغییر داد. بر اساس قانون کانوی، ساختار ارتباطی تیم‌ها بر معماری سیستم‌هایی که تولید می‌کنند اثر می‌گذارد. برای مثال، اگر تیم‌ها فقط بر اساس تخصص‌هایی مانند فرانت‌اند، بک‌اند و پایگاه داده جدا شده باشند، توسعه هر قابلیت ممکن است به هماهنگی گسترده میان چند تیم نیاز داشته باشد. در مقابل، تیم‌های محصول‌محور و چندتخصصی می‌توانند برخی تغییرات را با وابستگی کمتری انجام دهند. بنابراین، نوسازی معماری گاهی بدون بازنگری در مسئولیت‌ها و مسیرهای ارتباطی سازمان، به نتیجه مطلوب نمی‌رسد.به نظرم، نقطه قوت اصلی این سخنرانی آن است که نوسازی معماری را صرفا یک پروژه فنی یا مهاجرت از فناوری قدیمی به فناوری جدید نمی‌داند. موفقیت چنین تغییری به معیارهای معماری، شیوه انتشار، توانایی حذف قابلیت‌های کم‌ ارزش، ساختار تیم‌ها و حتی نگرش افراد وابسته است. البته این ارائه یک دستورالعمل ثابت برای همه سازمان‌ها ارائه نمی‌دهد و خود سخنران نیز تاکید می‌کند که راه‌ حل جادویی واحدی وجود ندارد. هر تصمیم باید با توجه به شرایط، اهداف و محدودیت‌های همان سازمان گرفته شود.در مجموع، برداشت من این است که هدف نوسازی، ساختن معماری‌ای کاملا جدید و بدون نقص نیست؛ بلکه آزادکردن سیستم و سازمان از محدودیت‌هایی است که سرعت نوآوری را کاهش داده‌اند. یک نوسازی موفق باید تدریجی، قابل‌اندازه‌گیری و هماهنگ با نیازهای واقعی کسب‌وکار باشد. همچنین باید بپذیریم سامانه‌ای که امروز مدرن محسوب می‌شود، ممکن است در آینده به یک سیستم Legacy تبدیل شود؛ بنابراین مهم‌تر از انتخاب یک فناوری خاص، ایجاد توانایی دائمی برای یادگیری، تغییر و نوسازی است.منابعویدئوی رسمی سخنرانی Renovate to Innovate :https://youtu.be/brHepv_JNNg?si=GyCpb_SuZ1v1PleSویدئو و متن کامل سخنرانی در InfoQ :https://www.infoq.com/presentations/scale-paymentsصفحه رسمی سخنرانی در QCon San Francisco 2024 :https://qconsf.com/presentation/nov2024/renovate-innovate-fundamentals-transforming-legacy-architectureمقاله سخنران درباره تحول معماری‌های قدیمی در InfoQ :https://www.infoq.com/articles/fundamentals-of-transforming-legacy-architectureاين مطلب، بخشی از تمرين‌های درس معماری نرم‌افزار در دانشگاه شهيدبهشتی است 🌱</description><category>امین مستوری نژاد</category><author>امین مستوری نژاد</author><pubDate>Fri, 10 Jul 2026 20:00:15 +0330</pubDate></item><item><title>معمار خوب همه تصمیم‌ها را نمی‌گیرد؛ دیگران را برای تصمیم‌گیری بهتر توانمند می‌کند</title><link>https://virgool.ir/@amin.montazer1381/معمار-خوب-همه-تصمیم-ها-را-نمی-گیرد-دیگران-را-برای-تصمیم-گیری-بهتر-توانمند-می-کند-gjrwzemxkcqo</link><description>عنوان سخنرانی: Thinking Like an Architectهمایش: QCon London 2024سخنران: Gregor Hohpeمدت سخنرانی: ۴۹ دقیقه و ۳۳ ثانیهلینک ویدئو: https://youtu.be/Oib06l1CHME?si=-Il4q1-8wPLsom0Hوقتی واژه «معمار نرم‌افزار» را می‌شنویم، ممکن است فردی را تصور کنیم که از بقیه اعضای تیم باتجربه‌تر است، همه فناوری‌ها را می‌شناسد و تصمیم‌های مهم پروژه را به‌تنهایی می‌گیرد. مهم‌ترین نکته‌ای که من از سخنرانی Thinking Like an Architect دریافت کردم، رد همین تصور بود. Gregor Hohpe توضیح می‌دهد که معماری بیش از آنکه یک عنوان سازمانی باشد، نوعی شیوه تفکر است. ممکن است فردی عنوان معمار را نداشته باشد، اما مانند یک معمار فکر کند؛ در مقابل، داشتن این عنوان نیز به‌ تنهایی نشان‌دهنده توانایی معماری نیست.به نظرم، یکی از ماندگارترین مفاهیم این ارائه، معرفی معمار به‌عنوان تقویت‌کننده هوش جمعی یا IQ Amplifier بود. وظیفه معمار این نیست که باهوش‌ترین فرد اتاق باشد و برای همه نسخه آماده بپیچد. او باید به اعضای تیم کمک کند مسئله را از زاویه‌های بیشتری ببینند، پیامد تصمیم‌ها را درک کنند، گزینه‌های پنهان را پیدا کنند و میان مزایا و هزینه‌های هر انتخاب تعادل برقرار سازند. در چنین نگاهی، موفقیت معمار با تعداد تصمیم‌هایی که شخصا گرفته است سنجیده نمی‌شود؛ بلکه با کیفیت تصمیم‌هایی سنجیده می‌شود که دیگران با کمک او گرفته‌اند.مفهوم مهم بعدی، آسانسور معمار است. سخنران سازمان را به ساختمانی چندطبقه تشبیه می‌کند: مدیران و تصمیم‌گیران کسب‌وکار در طبقات بالا و تیم‌های فنی در موتورخانه قرار دارند. معمار ارزشمند کسی نیست که فقط در یکی از این طبقات حضور داشته باشد؛ بلکه کسی است که بتواند میان آن‌ها رفت‌وآمد کند و ارتباط معناداری میان اهداف کسب‌وکار و واقعیت‌های فنی به وجود آورد. برای مثال، تیم فنی ممکن است درباره خودکارسازی، DevOps، مشاهده‌پذیری و مقیاس‌پذیری صحبت کند، درحالی‌که مدیران بیشتر نگران امنیت، دسترس‌پذیری و هزینه هستند. وظیفه معمار این است که نشان دهد خودکارسازی چگونه به بروزرسانی منظم، کاهش آسیب‌پذیری، بازیابی سریع‌تر و مدیریت بهتر هزینه منجر می‌شود.این بخش برای من اهمیت زیادی داشت، زیرا نشان داد ارتباط معماری فقط ساده‌ کردن اصطلاحات فنی نیست. سخنران تأکید می‌کند که هنگام صحبت با مدیران نباید موضوع را بیش‌ از حد سطحی کرد؛ آن‌ها ممکن است جزئیات فنی را ندانند، اما در زمینه کسب‌ و کار و تصمیم‌گیری سازمانی تخصص دارند. معمار باید جزئیاتی را انتخاب کند که برای تصمیم موردنظر معنادار باشند. استفاده از استعاره‌های مرتبط با حوزه فعالیت سازمان نیز می‌تواند مخاطب را وارد فرایند فکرکردن کند. در غیر این صورت، توضیح مجموعه‌ای از اصطلاحات مانند Kubernetes، معماری رویدادمحور یا Serverless عملاً به این جمله تبدیل می‌شود: «به من اعتماد کنید و بودجه را در اختیارم بگذارید.»موضوع دیگر تفاوت میان یک نمودار شلوغ و یک مدل مفید بود. گاهی تصور می‌کنیم هرچه نمودار معماری جزئیات و جعبه‌های بیشتری داشته باشد، حرفه‌ای‌تر است. اما Hohpe توضیح می‌دهد که قدرت مدل در حذف آگاهانه جزئیات غیرضروری و برجسته‌کردن بخش‌های مهم است. یک مدل خوب قرار نیست نسخه کاملی از واقعیت باشد؛ بلکه باید به سؤال مشخصی پاسخ دهد. همان‌طور که برای یک منطقه می‌توان نقشه جاده‌ای، سیاسی، توپوگرافی یا تراکم جمعیت تهیه کرد، برای یک سیستم نیز نمی‌توان فقط یک نمودار را پاسخ‌گوی تمام نیازها دانست. پیش از رسم معماری باید پرسید این مدل قرار است چه مسئله‌ای را روشن کند و مخاطب آن چه کسی است.یکی دیگر از ویژگی‌های تفکر معماری، توانایی مشاهده ابعاد بیشتر یک مسئله است. بسیاری از اختلاف‌های فنی به این دلیل ایجاد می‌شوند که مسئله فقط در یک محور دیده می‌شود؛ مثلا سرعت در برابر کیفیت، استانداردسازی در برابر نوآوری یا استفاده از خدمات ابری در برابر وابستگی به فروشنده. معمار می‌تواند با افزودن یک بعد جدید، این تضاد ظاهری را تغییر دهد. برای نمونه، تست خودکار می‌تواند سرعت و کیفیت را هم‌زمان افزایش دهد و یک پلتفرم مشترک می‌تواند با استانداردکردن زیرساخت، امکان تنوع و نوآوری بیشتری را در سطح محصول فراهم کند. این بخش به من نشان داد که گاهی پاسخ معماری انتخاب یکی از دو طرف نیست؛ بلکه تغییر مدل مسئله و پیداکردن راهی برای دستیابی به هر دو هدف است.در بخش دیگری از سخنرانی، تصمیم‌های معماری به «خریدوفروش اختیار» تشبیه می‌شوند. با استاندارد کردن یک رابط یا پروتکل، برخی آزادی‌ها محدود می‌شوند، اما در مقابل، گزینه‌های ارزشمند دیگری مانند استفاده از زبان‌های برنامه‌نویسی مختلف یا جایگزینی پیاده‌سازی‌ها به دست می‌آیند. همچنین به‌تعویق‌انداختن یک تصمیم، در محیط‌های غیرقابل‌پیش‌بینی می‌تواند ارزشمند باشد. برای مثال، زیرساخت کشسان این امکان را فراهم می‌کند که ظرفیت سیستم بعدا و متناسب با میزان واقعی تقاضا افزایش یابد. هرچه عدم‌قطعیت بیشتر باشد، ارزش چنین گزینه‌هایی نیز بیشتر می‌شود. از همین منظر، سخنران معماری و چابکی را مخالف یکدیگر نمی‌داند؛ هر دو برای مواجهه با تغییر و ناشناخته‌ها به کار می‌روند.توانایی بزرگ‌نمایی و کوچک‌نمایی نیز بخش مهمی از نقش معمار است. وقتی فقط روی یک کامپوننت یا تیم تمرکز می‌کنیم، ممکن است عملکرد آن مناسب به نظر برسد؛ اما با نگاه‌ کردن به کل سیستم، مشکلات مربوط به ارتباط میان اجزا، انتقال تغییرات، افزایش تاخیر یا ناهماهنگی تیم‌ها آشکار می‌شوند. گاهی هر تیم به‌ صورت محلی عملکرد خوبی دارد، اما مجموع این بهینه‌سازی‌های محلی، نتیجه مطلوبی برای کل سازمان ایجاد نمی‌کند. برداشت من این است که معمار باید هم جزئیات فنی را بفهمد و هم بتواند چند قدم عقب‌تر بایستد و رفتار کل سیستم را بررسی کند؛ زیرا بسیاری از مشکلات واقعی نه داخل جعبه‌ها، بلکه در ارتباط میان آن‌ها شکل می‌گیرند.آخرین نکته مهم سخنرانی، پرهیز از تصمیم‌های مطلق و سیاه‌وسفید بود. عبارت‌هایی مانند «همه‌چیز باید میکروسرویس باشد»، «همیشه از کانتینر استفاده کنید» یا «تمام ارتباطات باید رویدادمحور باشند»، بیشتر از آنکه نشان‌دهنده تفکر معماری باشند، نشانه نادیده‌ گرفتن شرایط مسئله هستند. دنیای معماری از طیف‌های خاکستری و Trade-off ها تشکیل شده است. یک انتخاب ممکن است برای سیستمی مناسب و برای سیستم دیگری کاملا اشتباه باشد. بنابراین معمار باید به‌جای تکرار فناوری‌های محبوب، محدودیت‌ها، هزینه‌ها، ریسک‌ها و پیامدهای هر انتخاب را بررسی کند.در مجموع، این سخنرانی نگاهم را نسبت به نقش معمار نرم‌افزار تغییر داد. پیش از آن، بیشتر تصور می‌کردم معمار کسی است که فناوری مناسب را انتخاب و ساختار نهایی سیستم را طراحی می‌کند. اما اکنون فکر می‌کنم بخش مهم‌تر این نقش، ایجاد زبان مشترک، ارائه مدل‌های قابل‌فهم، آشکارکردن گزینه‌ها، مشخص‌کردن مصالحه‌ها و مرتبط‌ساختن تصمیم‌های فنی با اهداف سازمان است. معمار خوب جواب تمام سؤال‌ها را از قبل نمی‌داند؛ بلکه به تیم کمک می‌کند سؤال‌های بهتری بپرسد و با آگاهی بیشتری تصمیم بگیرد.منابعویدئوی رسمی سخنرانی در کانال GOTO Conferences :https://youtu.be/Oib06l1CHME?si=-Il4q1-8wPLsom0Hویدئو و متن کامل سخنرانی در InfoQ :https://www.infoq.com/presentations/architect-lessonsصفحه رسمی سخنرانی در QCon London 2024 :https://qconlondon.com/presentation/apr2024/thinking-architectمقاله Thinking Like an Architect در InfoQ :https://www.infoq.com/articles/thinking-like-architectاين مطلب، بخشی از تمرين‌های درس معماری نرم‌افزار در دانشگاه شهيدبهشتی است 🌱</description><category>امین مستوری نژاد</category><author>امین مستوری نژاد</author><pubDate>Fri, 10 Jul 2026 18:17:34 +0330</pubDate></item><item><title>معماری در برابر ناشناخته‌ها؛ مروری بر نظریه Residuality</title><link>https://virgool.ir/@amin.montazer1381/معماری-در-برابر-ناشناخته-ها-مروری-بر-نظریه-residuality-feareh8acogl</link><description>عنوان سخنرانی: Residues: Time, Change and Uncertainty in Software Architectureهمایش: GOTO Copenhagen 2025سخنران: Barry O’Reillyمدت سخنرانی: حدود ۴۷ دقیقهلینک ویدئو: https://youtu.be/D8qQUHrksrE?si=-EBSeU6zVS-Lu07Aیکی از پرسش‌هایی که همیشه در معماری نرم‌افزار مطرح می‌شود این است که چگونه می‌توان سیستمی طراحی کرد که با تغییر نیازمندی‌ها، رشد کسب‌وکار و رخدادهای پیش‌بینی‌نشده از بین نرود. Barry O’Reilly در این سخنرانی به‌جای معرفی یک سبک معماری یا فناوری جدید، نگاه بنیادی‌تری به این مسئله دارد. او معتقد است مشکل اصلی معماری نرم‌افزار، فقط انتخاب میان میکروسرویس، مونولیت، معماری رویدادمحور یا فناوری‌های مختلف نیست؛ مشکل مهم‌تر این است که معماری در یک محیط ثابت ساخته نمی‌شود. محیط کسب‌وکار، رفتار کاربران، قوانین، بازار و فناوری‌ها دائماً تغییر می‌کنند، درحالی‌که ساختار نرم‌افزار معمولاً بسیار خشک‌تر و محدودتر است.پیش از دیدن این سخنرانی، عدم قطعیت را بیشتر به‌عنوان مشکلی می‌دیدم که باید با جمع‌آوری دقیق‌تر نیازمندی‌ها و پیش‌بینی ریسک‌ها کاهش پیدا کند. اما نکته اصلی ارائه این است که عدم قطعیت را نمی‌توان به‌طور کامل حذف کرد؛ زیرا معمولا همان اتفاق‌هایی بیشترین آسیب را به سیستم وارد می‌کنند که از قبل در فهرست ریسک‌ها قرار نگرفته‌اند. به همین دلیل، معمار باید به‌جای تلاش برای پیش‌بینی دقیق آینده، معماری را برای روبه‌روشدن با آینده‌های متفاوت آماده کند.سخنران برای توضیح این دیدگاه، نظریه‌ای با عنوان Residuality Theory معرفی می‌کند. در این نظریه، سیستم نرم‌افزاری فقط به‌صورت مجموعه‌ای از کامپوننت‌ها و فرایندها دیده نمی‌شود، بلکه به‌صورت مجموعه‌ای از «باقی‌مانده‌ها» یا Residue ها مدل می‌شود. Residue بخشی از معماری است که پس از واردشدن یک فشار یا تغییر جدی، همچنان قابل استفاده باقی می‌ماند. در نتیجه، سؤال اصلی دیگر این نیست که «در حالت عادی اجزای سیستم چگونه با یکدیگر کار می‌کنند؟»، بلکه این است که «وقتی شرایط عادی از بین رفت، چه چیزی از سیستم باقی می‌ماند و هنوز می‌تواند به کار خود ادامه دهد؟»یکی از بخش‌های جالب سخنرانی، ارتباط معماری نرم‌افزار با علم پیچیدگی است. در یک سیستم پیچیده، تعداد ارتباط‌ها و حالت‌های احتمالی آن‌قدر زیاد است که بررسی همه آن‌ها عملاً امکان‌پذیر نیست. بااین‌حال، سیستم معمولا به تعداد محدودی وضعیت خاص تمایل پیدا می‌کند که در این نظریه Attractor نامیده می‌شوند. برای مثال، ممکن است چند رخداد ظاهرا متفاوت، سیستم را به وضعیت مشترکی مانند قطع کامل سرویس، ازدست‌رفتن امکان پرداخت یا وابستگی شدید به یک جزء خاص هدایت کنند. بنابراین، به‌جای پیش‌بینی تمام رخدادهای ممکن، باید این وضعیت‌های تکرارشونده و خطرناک را شناسایی کرد.فرایند پیشنهادی Residuality با یک معماری اولیه و نسبتا ساده آغاز می‌شود که مسئله اصلی را حل می‌کند. سپس تیم، مجموعه‌ای از Stressor ها یا عوامل فشار را به معماری وارد می‌کند. این فشارها می‌توانند فنی باشند، مانند قطع شبکه یا ازکارافتادن پایگاه داده؛ اما ممکن است به تغییر قوانین، رفتار غیرمنتظره کاربران، تغییر بازار یا حتی سناریوهای بسیار بعید مربوط باشند. هدف از این کار، پیش‌بینی دقیق آینده نیست، بلکه خارج‌کردن ذهن تیم از فرضیات محدود فعلی است. پس از هر فشار بررسی می‌شود که معماری به چه وضعیتی وارد می‌شود، چه اجزایی از کار می‌افتند و چه بخش‌هایی باقی می‌مانند. سپس Residue های به‌دست‌آمده با یکدیگر ترکیب می‌شوند تا معماری نهایی در برابر طیف گسترده‌تری از تغییرات دوام بیاورد.در سخنرانی، این مفاهیم با نمونه‌ای از سامانه شارژ خودروهای الکتریکی توضیح داده می‌شوند. همچنین از تحلیل سرایت یا Contagion Analysis برای بررسی این موضوع استفاده می‌شود که چگونه اختلال در یک بخش می‌تواند به بخش‌های دیگر منتقل شود و باعث شکست زنجیره‌ای شود. این مثال نشان می‌دهد که گاهی مشکل اصلی، خراب‌شدن یک کامپوننت نیست، بلکه میزان وابستگی اجزا به یکدیگر و سرعت گسترش اختلال در کل سیستم است. سخنران با کمک مفاهیمی مانند شبکه‌های کافمن و تحلیل روابط میان اجزا، تلاش می‌کند پیچیدگی و سرایت شکست را به شکلی قابل‌بررسی‌تر نمایش دهد.برداشت من این است که Residuality قصد ندارد اهمیت نیازمندی‌ها، تجربه مهندسی یا مدیریت ریسک را کاملا انکار کند. ارزش اصلی آن در این است که اعتماد بیش‌ازحد ما به پیش‌بینی را به چالش می‌کشد. حتی کامل‌ترین سند نیازمندی‌ها نیز بر اساس دانسته‌های امروز نوشته می‌شود، درحالی‌که معماری باید سال‌ها در محیطی فعالیت کند که بخشی از آن هنوز ناشناخته است. به همین دلیل، معماری مناسب فقط معماری‌ای نیست که نیاز فعلی را به‌درستی پیاده‌سازی کند؛ بلکه باید بتواند در شرایطی که فرضیات اولیه دیگر معتبر نیستند نیز بخشی از ارزش خود را حفظ کند.یکی از جمله‌های کلیدی این دیدگاه را می‌توان این‌گونه خلاصه کرد: معماری نباید فقط طراحی شود، بلکه باید مانند یک مدل، تحت فشار «آموزش» داده شود. برای ارزیابی نتیجه نیز می‌توان معماری اولیه و معماری اصلاح‌شده را با مجموعه جدیدی از Stressor ها آزمایش کرد و بررسی کرد کدام‌یک در برابر رخدادهای ناشناخته دوام بیشتری دارند. این نگاه، تصمیم‌گیری معماری را از یک فعالیت مبتنی بر سلیقه یا تجربه فردی، به فرایندی شفاف‌تر، قابل‌ آزمایش‌تر و قابل‌ آموزش تبدیل می‌کند.در مجموع، این سخنرانی باعث شد معماری نرم‌افزار را کمتر به‌ عنوان یک نمودار ثابت و بیشتر به‌ عنوان ساختاری ببینم که باید در برابر حرکت دائمی محیط اطراف خود دوام بیاورد. وظیفه معمار این نیست که آینده را دقیق پیش‌بینی کند؛ بلکه باید محدودیت پیش‌بینی را بپذیرد، معماری را در معرض فشارهای متنوع قرار دهد و ساختاری ایجاد کند که با تغییر یک فرض، تمام سیستم فرو نریزد. به نظرم، این نوع نگاه برای سیستم‌هایی که در محیط‌های پیچیده، متغیر و غیرقابل‌پیش‌بینی فعالیت می‌کنند، بسیار کاربردی و ارزشمند است.منابعویدئوی رسمی سخنرانی در کانال GOTO Conferences :https://youtu.be/D8qQUHrksrE?si=-EBSeU6zVS-Lu07Aصفحه رسمی سخنرانی در GOTO :https://gotopia.tech/sessions/3595/residues-time-change-and-uncertainty-in-software-architectureگزارش InfoQ درباره Residuality Theory :https://www.infoq.com/news/2025/10/architectures-residuality-theoryمعرفی کتاب Residues در GOTO :https://gotopia.tech/books/120/residues-time-change-and-uncertainty-in-software-architectureاين مطلب، بخشی از تمرين‌های درس معماری نرم‌افزار در دانشگاه شهيدبهشتی است 🌱</description><category>امین مستوری نژاد</category><author>امین مستوری نژاد</author><pubDate>Fri, 10 Jul 2026 13:11:11 +0330</pubDate></item><item><title>معماری خوب از پیچیدگی شروع نمی‌شود؛ با نیاز واقعی رشد می‌کند</title><link>https://virgool.ir/@amin.montazer1381/معماری-خوب-از-پیچیدگی-شروع-نمی-شود-با-نیاز-واقعی-رشد-می-کند-sniu1gzqrr7a</link><description>عنوان سخنرانی: Master Software Architecture: From Simplicity to Complexityسخنران: Maciej “MJ” Jedrzejewskiهمایش: GOTO Copenhagen 2025مدت سخنرانی: حدود ۴۶ دقیقهلینک ویدئو: https://youtu.be/ZCrCqbblXjk?si=MEnV_fgd6H-6pSw9وقتی درباره معماری نرم‌افزار صحبت می‌کنیم، معمولا اولین چیزهایی که به ذهن می‌رسد میکروسرویس، معماری رویدادمحور، Kubernetes، صف پیام و پایگاه‌ داده‌های توزیع‌ شده هستند. با این حال، سخنرانی «تسلط بر معماری نرم‌افزار؛ از سادگی تا پیچیدگی» به این موضوع اشاره دارد که معماری خوب الزاما معماری پیچیده نیست. به نظر سخنران، معماری نرم‌افزار یک طرح ثابت و نهایی نیست که در ابتدای پروژه طراحی شود و تا پایان بدون تغییر باقی بماند؛ بلکه ساختاری زنده و تکامل‌یابنده است که باید همراه با نیازهای کسب‌وکار، رشد کاربران، تغییرات تیم و محدودیت‌های محیطی تغییر کند.یکی از نکات مهم سخنرانی این است که پیچیدگی نباید پیش از آنکه واقعا به آن نیاز داشته باشیم، وارد سیستم شود. گاهی تیم‌های توسعه برای حل مشکلاتی که هنوز وجود ندارند، از همان ابتدای پروژه سراغ معماری‌های توزیع‌شده، سرویس‌های متعدد و ابزارهای پیشرفته می‌روند. این تصمیم ممکن است در ظاهر حرفه‌ای به نظر برسد، اما در عمل هزینه توسعه، استقرار، تست، مانیتورینگ و رفع خطا را افزایش می‌دهد. سخنران با اشاره به تجربه پروژه‌های واقعی توضیح می‌دهد که در برخی موارد، تیم‌ها سیستم‌های توزیع‌شده‌ای ساخته‌اند که اساسا نیازی به توزیع‌شدن نداشته‌اند یا مؤلفه‌هایی به معماری اضافه کرده‌اند که تنها مسائل فرضی را حل می‌کردند.بنظرم مفهوم «باز نگه‌داشتن درها» یکی از ارزشمندترین بخش‌های این ارائه بود. هر تصمیم معماری علاوه بر مزایایی که ایجاد می‌کند، تعدادی از انتخاب‌های آینده را نیز محدود می‌سازد. بنابراین معمار نباید خیلی زود تصمیم‌های پرهزینه و سخت‌برگشت بگیرد. نقطه شروع مناسب می‌تواند یک سیستم ساده، قابل‌فهم و قابل‌آزمایش باشد؛ سیستمی که نیاز فعلی را پاسخ دهد، اما امکان توسعه و تغییر آن در آینده نیز حفظ شده باشد. سادگی در اینجا به معنای طراحی ضعیف یا بی‌توجهی به آینده نیست، بلکه به معنای پرهیز از پرداخت هزینه برای آینده‌ای است که هنوز درباره آن اطلاعات کافی نداریم.سخنران مسیر تکامل معماری را با چهار مفهوم اصلی سادگی، نگهداشت‌پذیری، رشد و پیچیدگی توضیح می‌دهد. در مرحله سادگی، هدف این است که سیستم با کمترین پیچیدگی ضروری ساخته شود و ارزش موردنیاز را سریع‌تر در اختیار کاربر قرار دهد. با رشد محصول، نگهداشت‌ پذیری اهمیت بیشتری پیدا می‌کند؛ یعنی زمانی که تیم برای اضافه‌کردن قابلیت‌های جدید بیش از حد با ساختار موجود درگیر می‌شود، باید مرز ماژول‌ها، وابستگی‌ها و نحوه سازمان‌دهی کد بازبینی شود. در مرحله رشد نیز ابزارهایی مانند کش، نسخه‌های خواندنی پایگاه‌داده، ماژولارکردن سیستم یا میکروسرویس‌ها زمانی ارزشمند می‌شوند که یک مشکل واقعی در مقیاس، عملکرد یا استقلال تیم‌ها وجود داشته باشد. در نهایت، پیچیدگی‌های سنگین‌تر مانند قوانین خاص، پردازش‌های توزیع‌شده یا منطق دامنه پیشرفته باید در پاسخ به نیازهای واقعی وارد معماری شوند، نه صرفاً به دلیل محبوب‌بودن یک فناوری.موضوع مهم دیگر، نقش استقرار، انتشار و تست در تکامل معماری است. من پیش از دیدن این سخنرانی بیشتر به تست به‌ عنوان ابزاری برای پیداکردن خطا نگاه می‌کردم؛ اما در این ارائه، تست به‌ عنوان شبکه ایمنی تغییر معرفی می‌شود. زمانی می‌توان یک معماری ساده را با اطمینان به ساختاری کامل‌تر تبدیل کرد که تست‌های مناسب، بازخورد سریع و فرایند انتشار کنترل‌شده وجود داشته باشند. استراتژی‌های مناسب استقرار و انتشار نیز تشریفات اضافی نیستند؛ بلکه کمک می‌کنند تغییرات معماری به‌صورت تدریجی، قابل‌کنترل و با ریسک کمتر انجام شوند.سخنران همچنین تاکید می‌کند که امنیت نباید قابلیتی باشد که پس از کامل‌ شدن سیستم به آن اضافه شود. امنیت باید در تمام مراحل تکامل معماری، از ساده‌ترین نسخه تا پیچیده‌ترین حالت، موردتوجه قرار گیرد. به‌تعویق‌انداختن تصمیم‌های امنیتی می‌تواند باعث ایجاد بدهی فنی شود که اصلاح آن در آینده بسیار پرهزینه‌تر خواهد بود.به نظر من، نقطه قوت اصلی این سخنرانی، نگاه واقع‌ گرایانه و غیرابزارمحور آن به معماری است. این ارائه تلاش نمی‌کند یک سبک معماری را برای همه پروژه‌ها مناسب معرفی کند. پیام آن این است که انتخاب معماری باید از شناخت مسئله، دامنه کسب‌وکار، محدودیت‌ها، توانایی تیم و شواهد واقعی حاصل شود. البته به دلیل گستردگی موضوعات، درباره برخی تکنیک‌ها جزئیات اجرایی زیادی ارائه نمی‌شود؛ اما هدف سخنرانی نیز آموزش یک فناوری خاص نیست، بلکه اصلاح شیوه فکرکردن درباره تصمیم‌های معماری است.در نهایت، مهم‌ترین نتیجه‌ای که من از این سخنرانی گرفتم این است که وظیفه معمار، ساختن پیچیده‌ترین سیستم ممکن نیست. معمار خوب کسی است که پیچیدگی ضروری را از پیچیدگی نمایشی تشخیص دهد، تا جای ممکن تصمیم‌های برگشت‌ناپذیر را به تعویق بیندازد و شرایطی فراهم کند که سیستم بتواند بدون فروپاشی رشد کند. معماری موفق معماری‌ای نیست که از روز اول برای تمام آینده آماده باشد؛ بلکه معماری‌ای است که امروز قابل‌فهم و مفید باشد و فردا نیز بتوان آن را با هزینه‌ای منطقی تغییر داد.منابعویدئوی رسمی سخنرانی در کانال GOTO Conferences :https://youtu.be/ZCrCqbblXjk?si=MEnV_fgd6H-6pSw9صفحه رسمی سخنرانی در GOTO :https://gotopia.tech/sessions/3660/master-software-architecture-from-simplicity-to-complexityصفحه سخنران در GOTO Copenhagen 2025 :https://gotocph.com/2025/speakers/3894/maciej-jedrzejewskiمعرفی کتاب Master Software Architecture: A Pragmatic Guide :https://mastersoftwarearchitecturebook.comاين مطلب، بخشی از تمرين‌های درس معماری نرم‌افزار در دانشگاه شهيدبهشتی است 🌱</description><category>امین مستوری نژاد</category><author>امین مستوری نژاد</author><pubDate>Fri, 10 Jul 2026 12:41:10 +0330</pubDate></item><item><title>اگر مهندس نرم‌افزاری این مفاهیم را باید بشناسی</title><link>https://virgool.ir/@amin.montazer1381/اگر-مهندس-نرم-افزاری-این-مفاهیم-را-باید-بشناسی-lomsjbgrkkms</link><description>دنیای توسعه نرم‌افزار در سال‌های اخیر فقط به نوشتن کد محدود نشده و مفاهیم جدیدی وارد معماری و طراحی سیستم‌ها شده‌اند که شناخت آن‌ها برای هر مهندس نرم‌افزار، توسعه‌ دهنده یا حتی علاقه‌مند به تکنولوژی اهمیت زیادی دارد. از معماری‌های Event-Driven و Serverless گرفته تا مفاهیمی مثل MLOps، CQRS، Service Mesh و Kubernetes، هرکدام بخشی از چالش‌های سیستم‌های مدرن را حل می‌کنند و باعث می‌شوند نرم‌افزارها مقیاس‌پذیرتر، منعطف‌تر و قابل نگهداری‌تر شوند. در این مطلب سعی میکنم 20 تا از مهم‌ترین مفاهیم و ترندهای معماری نرم‌افزار مدرن را راجبش صحبت کنم تا دید بهتری نسبت به دنیای سیستم‌های امروزی پیدا کنیم✌️1. Chaos Engineeringوقتی اولین بار با عبارت مهندسی آشوب روبرو شدم، کمی عجیب به نظر رسید🤔چرا باید عمدا به سیستم‌هایمان آسیب بزنیم؟ اما وقتی عمیق‌تر رفتم، متوجه شدم این رویکرد یکی از هوشمندانه‌ترین استراتژی‌هایی است که در دنیای معماری نرم‌افزار مدرن وجود دارد.Chaos Engineering یعنی عمداً و به‌صورت کنترل‌شده، خرابی و اختلال را در یک سیستم وارد کردن تا ببینیم آیا آن سیستم می‌تواند در برابر شرایط واقعی و غیرمنتظره دوام بیاورد یا نه. ایده اصلی میگه بهتر است ما یک خرابی را در محیطی کنترل‌شده شبیه‌سازی کنیم، تا اینکه خرابی ناخواسته در محیط واقعی و زمانی که کاربران از سرویس استفاده می‌کنند اتفاق بیفتد.Netflix یکی از پیشگامان این حوزه است. آن‌ها ابزاری به نام Chaos Monkey ساختند که به‌صورت تصادفی سرورهای تولیدی را خاموش می‌کرد تا ببینند سیستم چطور واکنش نشان می‌دهد. در ابتدا این ایده دیوانه‌وار به نظر می‌رسید، اما نتیجه آن شد که Netflix یکی از مقاوم‌ترین سیستم‌های توزیع‌شده دنیا را ساخت.مراحل اجرای یک آزمایش Chaos Engineering معمولا به این شکل است که ابتدا وضعیت عادی سیستم را تعریف می‌کنیم (Steady State)، سپس یک فرضیه می‌سازیم مثل اگر یک سرور از دسترس خارج شود، سیستم همچنان پاسخگو خواهد بود، بعد آزمایش را در محیطی کنترل‌ شده اجرا می‌کنیم، نتایج را مشاهده می‌کنیم، و در نهایت یاد می‌گیریم و سیستم را بهبود می‌دهیم.چیزی که این رویکرد را متمایز می‌کند این است که از امیدواریم مشکلی پیش نیاید خارج می‌شویم و وارد بیایید مشکلات را قبل از رخ دادن پیدا کنیم، می‌شویم. این تغییر نگرش در سیستم‌های بزرگ و توزیع‌شده بسیار ارزشمند است.منابع‎[1] “اصول مهندسی آشوب” (Principles of Chaos Engineering), وبسایت رسمی (Persian translation) https://principlesofchaos.org/fa.[2] A. Basiri, Chaos Engineering – Gremlin, بلاگ شرکت Gremlin (2022) https://www.gremlin.com/chaos-engineering/2. Backend for Frontend (BFF)تصور کنید یک API دارید که باید هم به اپلیکیشن موبایل، هم به وب‌اپلیکیشن، و هم به یک Smart TV پاسخ دهد. مشکل اینجاست که هر یک از این کلاینت‌ها نیازهای کاملاً متفاوتی دارند؛ موبایل به داده‌های سبک‌تر نیاز دارد، وب به داده‌های غنی‌تر، و Smart TV ممکن است ساختار کاملاً دیگری بخواهد. Pattern مشهور به BFF یا Backend for Frontend دقیقاً برای حل این چالش به وجود آمده است.ایده اصلی BFF ساده است، یعنی به جای اینکه یک Backend عمومی برای همه کلاینت‌ها داشته باشیم، برای هر نوع کلاینت یک Backend جداگانه و اختصاصی می‌سازیم. یعنی یک BFF برای موبایل، یک BFF برای وب، و یک BFF برای Smart TV. هر BFF دقیقا همان داده‌هایی را که کلاینت متناظرش نیاز دارد فراهم می‌کند. نه بیشتر، نه کمتر.این Pattern اولین بار توسط Sam Newman در کتابش درباره Microservices معرفی شد. مزیت اصلی‌اش این است که تیم Frontend می‌تواند BFF مختص خودش را کنترل کند و نیازی نیست منتظر تیم Backend بماند تا تغییرات مورد نیازش را پیاده‌سازی کند. همچنین هر BFF می‌تواند داده‌ها را به شکلی که کلاینتش نیاز دارد تجمیع، فیلتر و قالب‌بندی کند.یک مثال ملموس بخوام بگم این هست که فرض کنید صفحه پروفایل کاربر در موبایل فقط به نام، عکس و آخرین فعالیت نیاز دارد، اما همین صفحه در وب شامل تاریخچه خریدها، تنظیمات حساب، پیام‌ها و موارد دیگری هم هست. با BFF، هر کلاینت دقیقا همان چیزی را می‌گیرد که نیاز دارد، بدون اینکه داده‌های اضافه‌ای منتقل شود یا کلاینت مجبور به چندین درخواست جداگانه شود.البته BFF هزینه‌هایی هم دارد چون نگهداری چندین Backend می‌تواند پیچیدگی را افزایش دهد. به همین دلیل معمولا BFF در کنار یک API Gateway استفاده می‌شود تا مسیریابی و اعتبارسنجی مشترک در یک جا مدیریت شود.منابع‎[1] S. Newman, “Backends For Frontends,” Sam Newman’s blog (2019) https://samnewman.io/patterns/architectural/backends-for-frontends[2] Microsoft, “Backends for Frontends pattern,” Azure Architecture Center (2017) https://docs.microsoft.com/azure/architecture/patterns/bff[3] M. Johnson, “Building Mobile Apps with an API and BFF,” AWS Compute Blog (2019) https://aws.amazon.com/blogs/mobile/backends-for-frontends/3. AI for Software Engineering (AI4SE)یکی از جذاب‌ترین تحولاتی که در سال‌های اخیر در دنیای مهندسی نرم‌افزار رخ داده، ورود هوش مصنوعی به فرآیندهای توسعه نرم‌افزار است. AI4SE یا هوش مصنوعی برای مهندسی نرم‌افزار یعنی استفاده از تکنیک‌ها و ابزارهای AI در مراحل مختلف چرخه‌ی حیات نرم‌افزار؛ از نوشتن کد تا تست، از بررسی کد تا دیباگ کردن.وقتی درباره AI4SE فکر می‌کنم، اولین چیزی که به ذهنم می‌رسد ابزارهایی مثل GitHub Copilot است که به‌صورت Real-time کد پیشنهاد می‌دهد. اما این فقط یک گوشه از این حوزه است. AI4SE طیف گسترده‌ای از کاربردها را شامل می‌شود.GitHub Copilotدر حوزه تولید کد، مدل‌های زبانی بزرگ مثل GPT-4 و Claude می‌توانند تکه‌های کد بنویسند، Boilerplate تولید کنند، و حتی کدهای موجود را Refactor کنند. در حوزه تست، AI می‌تواند به‌صورت خودکار Test Caseهای جدید تولید کند یا باگ‌های احتمالی را شناسایی کند. در Code Review هم مدل‌ها می‌توانند مشکلات امنیتی، کارایی پایین، یا نقض اصول طراحی را پیدا کنند.یکی از کاربردهای خیلی جالب، تبدیل زبان‌های طبیعی به کد است (Natural Language to Code). یعنی توسعه‌دهنده می‌گوید یک تابع بنویس که لیستی از اعداد را می‌گیرد و میانگین آن‌ها را برمی‌گرداند و AI کد آن را می‌نویسد. این به ویژه برای کاهش زمان توسعه و کمک به توسعه‌دهندگان تازه‌کار بسیار مفید است.البته AI4SE چالش‌هایی هم دارد. کدهای تولیدشده توسط AI همیشه صحیح نیستند و ممکن است باگ‌های ظریفی داشته باشند. همچنین درباره حقوق مالکیت معنوی کدهای تولیدشده هنوز بحث‌های حقوقی جدی وجود دارد. علاوه بر این، وابستگی بیش از حد به AI ممکن است مهارت‌های بنیادی توسعه‌دهندگان را کاهش دهد.منابع‎[1] Chen, M., et al. (2021). Evaluating Large Language Models Trained on Code. arXiv:2107.03374.[2] Barr, E. T., Harman, M., McMinn, P., Shahbaz, M., &amp; Yoo, S. (2015). The Oracle Problem in Software Testing: A Survey. IEEE Transactions on Software Engineering, 41(5), 507–5254. Software Engineering for AI (SE4AI)اگر AI4SE درباره کمک AI به مهندسان نرم‌افزار بود، SE4AI دقیقا برعکس است. چگونه اصول و روش‌های مهندسی نرم‌افزار را برای ساختن سیستم‌های هوش مصنوعی به کار ببریم؟ این سوال به نظر ساده می‌رسد، اما چالش‌های خاص خودش را دارد.ساخت یک سیستم مبتنی بر AI با توسعه نرم‌افزار سنتی تفاوت‌های اساسی دارد. در نرم‌افزار سنتی، رفتار سیستم کاملا با کد تعریف می‌شود. اما در سیستم‌های AI، رفتار سیستم از داده یاد می‌گیرد. این یعنی وقتی مشکلی پیش می‌آید، ممکن است نه در کد، بلکه در داده‌های آموزشی یا در مدل باشد.SE4AI تلاش می‌کند پاسخ دهد که چطور سیستم‌های AI را به شکل قابل نگهداری، قابل تست، و قابل مقیاس‌گذاری طراحی کنیم. برای مثال، یکی از بزرگترین چالش‌ها تست سیستم‌های ML است. در نرم‌افزار سنتی، خروجی برای یک ورودی مشخص کاملا قابل پیش‌بینی است. اما یک مدل ML ممکن است برای ورودی‌های مشابه خروجی‌های متفاوتی بدهد.یکی از مفاهیم کلیدی در SE4AI، مدیریت بدهی فنی (Technical Debt) در سیستم‌های ML است. مقاله‌ای از Google با عنوان &#39;Hidden Technical Debt in Machine Learning Systems&#39; نشان داد که کد واقعی ML معمولا بخش کوچکی از یک سیستم ML را تشکیل می‌دهد و بخش عمده پیچیدگی در مدیریت داده، پایپلاین‌ها، و Serving قرار دارد.SE4AI همچنین شامل مهندسی داده، نظارت بر مدل‌ها (Model Monitoring)، مدیریت Versioning مدل‌ها، و طراحی سیستم‌هایی است که وقتی مدل تغییر می‌کند به‌خوبی به‌روزرسانی شوند. این حوزه روز به روز اهمیت بیشتری پیدا می‌کند چون سیستم‌های AI به‌سرعت در حال ورود به محصولات واقعی هستند.منابع‎[1] Sculley, D., et al. (2015). Hidden Technical Debt in Machine Learning Systems. Advances in Neural Information Processing Systems (NIPS), 28.[2] Amershi, S., et al. (2019). Software Engineering for Machine Learning: A Case Study. ICSE-SEIP 2019.[3] Serban, A. C., van den Berg, K., Visser, J., &amp; Zaidman, A. (2020). Adoption and Effects of Software Engineering Best Practices in Machine Learning. ESEM 2020.5. MLOpsهر کسی که تجربه ساخت یک مدل Machine Learning داشته باشد می‌داند که ساخت مدل فقط نیمی از کار است و نیم دیگر استقرار آن در محیط تولید و نگهداری‌اش در طول زمان است. MLOps یا Machine Learning Operations، مجموعه‌ای از اصول، ابزارها و روش‌هایی است که این فرآیند را ساختارمند می‌کند.MLOps ترکیبی از DevOps و مهندسی داده و مهندسی ML است. همانطور که DevOps فاصله بین توسعه و عملیات را کاهش داد، MLOps فاصله بین تحقیقات ML (که در دفترچه‌های Jupyter و محیط‌های آزمایشگاهی انجام می‌شود) و محصولات واقعی را کاهش می‌دهد.چرخه حیات یک مدل ML در MLOps معمولا شامل این مراحل است: جمع‌آوری و پردازش داده، آموزش مدل، ارزیابی و اعتبارسنجی مدل، استقرار (Deployment)، نظارت بر عملکرد (Monitoring)، و در صورت نیاز، بازآموزی (Retraining). کل این چرخه باید تا حد ممکن خودکار و قابل تکرار باشد.یکی از مهم‌ترین مفاهیم در Model Drift ،MLOps است. منظور این است که عملکرد یک مدل در طول زمان ممکن است کاهش یابد چون دنیای واقعی تغییر می‌کند اما مدل با داده‌های قدیمی آموزش دیده. به همین دلیل نظارت مستمر بر دقت مدل در محیط تولید ضروری است.ابزارهای محبوب در MLOps شامل MLflow برای ردیابی آزمایش‌ها، Kubeflow برای اجرای پایپلاین‌های ML روی Kubernetes، DVC برای نسخه‌بندی داده، و Seldon یا BentoML برای Serving مدل هستند. پلتفرم‌های ابری مثل AWS SageMaker، Google Vertex AI و Azure ML هم مجموعه کاملی از ابزارهای MLOps ارائه می‌دهند.ابزار Kubeflowمنابع‎[1] Kreuzberger, D., Kühl, N., &amp; Hirschl, S. (2022). Machine Learning Operations (MLOps): Overview, Definition, and Architecture. arXiv:2205.02302.[2] Sculley, D., et al. (2015). Hidden Technical Debt in Machine Learning Systems. NIPS 2015.[3] Google Cloud. (2022). MLOps: Continuous delivery and automation pipelines in machine learning. https://cloud.google.com/architecture/mlops-continuous-delivery-and-automation-pipelines-in-machine-learning6. Infrastructure as Code (IaC)در روزگار نه‌ چندان دوری، مدیران سیستم باید به‌صورت دستی وارد سرورها می‌شدند، دستوراتی تایپ می‌کردند و زیرساخت را پیکربندی می‌کردند. این روش نه تکرارپذیر بود، نه قابلیت مستندسازی را داشت، و نه مقیاس‌پذیر بود. Infrastructure as Code یا IaC آمد تا این روش را متحول کند.IaC به معنای مدیریت و تأمین زیرساخت (سرورها، شبکه، پایگاه‌داده و غیره) از طریق فایل‌های کد قابل خواندن توسط ماشین به جای فرآیندهای دستی است. به عبارت ساده‌تر، وضعیت مطلوب زیرساخت را در یک فایل کد توصیف می‌کنیم و یک ابزار مسئول می‌شود که آن زیرساخت را ایجاد کند.مزایای این رویکرد زیاد است. اول، تکرارپذیری است، یعنی همان کد را می‌توان برای ایجاد محیط توسعه، تست و تولید استفاده کرد و مطمئن بود که همه یکسان هستند. دوم، نسخه‌بندی آن است، یعنی کد زیرساخت مثل هر کد دیگری در Git نگهداری می‌شود و می‌توان تاریخچه تغییرات را دید. سوم، مستندسازی آن است، یعنی خود کد، بهترین مستندات ممکن برای زیرساخت است.دو ابزار اصلی در این حوزه عبارتند از Terraform که از HashiCorp است و رویکرد Declarative دارد (یعنی می‌گوییم چه می‌خواهیم، نه چطور ایجاد کنیم)، و Ansible که رویکرد Imperative دارد و بیشتر برای پیکربندی سرورهای موجود استفاده می‌شود. پلتفرم‌های ابری هم ابزارهای اختصاصی خود مثل AWS CloudFormation و Azure ARM Templates دارند.یکی از اصول مهم در IaC، «Idempotency» است. یعنی اگر همان کد را چندین بار اجرا کنیم، نتیجه همیشه یکسان است و تغییر اضافه‌ای ایجاد نمی‌شود. این اصل باعث می‌شود بتوانیم با اطمینان، کد زیرساخت را اجرا و مجدداً اجرا کنیم.منابع‎[1] Morris, K. (2020). Infrastructure as Code: Dynamic Systems for the Cloud Age (2nd ed.). O&#39;Reilly Media.[2] HashiCorp. (2023). Terraform Documentation. https://developer.hashicorp.com/terraform/docs7. API Gateway &amp; Service Meshدر معماری Microservices، ده‌ها یا حتی صدها سرویس کوچک با هم در ارتباط هستند. مدیریت این ارتباطات، احراز هویت، Load Balancing، Logging و غیره به سرعت پیچیده می‌شود. دو Pattern مکمل برای حل این چالش‌ها وجود دارند که API Gateway و Service Mesh هستند.API Gateway نقطه ورودی واحد برای تمام درخواست‌های خارجی به سیستم است. به جای اینکه کلاینت مستقیما با سرویس‌های داخلی صحبت کند، با API Gateway صحبت می‌کند و Gateway درخواست را به سرویس مناسب هدایت می‌کند. علاوه بر مسیریابی، API Gateway معمولا وظایفی مثل احراز هویت (Authentication)، Rate Limiting، Caching، لاگ‌گیری، و SSL Termination را هم انجام می‌دهد. ابزارهای معروف این حوزه شاملKong، AWS API Gateway، و Nginx هستند.Service Mesh اما با مشکل متفاوتی سروکار دارد؛ ارتباطات سرویس‌ به‌ سرویس (Service-to-Service) در داخل سیستم. وقتی سرویس A باید با سرویس B صحبت کند، چطور مطمئن می‌شویم این ارتباط امن، قابل مشاهده و مقاوم در برابر خرابی است؟ Service Mesh این منطق را از کد سرویس‌ها خارج می‌کند و در یک لایه زیرساختی جداگانه قرار می‌دهد.در Service Mesh مدرن مثل Istio یا Linkerd، یک Sidecar Proxy (معمولا Envoy) کنار هر سرویس مستقر می‌شود. این پروکسی تمام ترافیک ورودی و خروجی سرویس را می‌گیرد و وظایفی مثل mTLS (رمزنگاری ارتباطات سرویس‌ به‌ سرویس)، Circuit Breaking، Retry، Distributed Tracing و Load Balancing را مدیریت می‌کند، بدون اینکه کد سرویس چیزی بداند.تفاوت کلیدی این دو این هست که API Gateway بیشتر برای کنترل ترافیک شمال-جنوب (خارج به داخل) استفاده می‌شود، در حالی که Service Mesh برای ترافیک شرق-غرب (سرویس‌ به‌ سرویس داخلی). در بسیاری از معماری‌های مدرن، این دو در کنار هم به کار می‌روند.منابع‎[1] Richardson, C. (2018). Microservices Patterns. Manning Publications.[2] Istio Project. (2023). Istio Documentation. https://istio.io/latest/docs8. CQRS (Command Query Responsibility Segregation)یکی از اصول کلاسیک در طراحی نرم‌افزار این است که یک متد یا عملیات باید یا یک عمل انجام دهد یا یک مقدار برگرداند، نه هر دو. CQRS یا جداسازی مسئولیت دستور و پرسش این ایده را در سطح معماری سیستم پیاده‌سازی می‌کند.در CQRS، سیستم به دو بخش جداگانه تقسیم می‌شود. Command Side مسئول تغییر وضعیت سیستم است؛ یعنی چیزهایی مثل محصول جدید اضافه کن، سفارش ثبت کن، موجودی را به‌روزرسانی کن. Query Side مسئول خواندن و گزارش‌گیری است. یعنی چیزهایی مثل لیست محصولات را نشان بده، وضعیت سفارش را برگردان. این دو بخش مدل‌های داده، منطق و حتی پایگاه‌ داده‌های متفاوتی می‌توانند داشته باشند.چرا این جداسازی مهم است؟ در بسیاری از سیستم‌ها، نیازهای خواندن و نوشتن کاملا متفاوت هستند. ممکن است نوشتن نیاز به Consistency قوی داشته باشد و از یک پایگاه‌ داده رابطه‌ای استفاده کند، در حالی که خواندن نیاز به سرعت بالا دارد و بهتر است از یک پایگاه‌ داده بهینه‌شده برای جستجو مثل Elasticsearch استفاده شود.CQRS به خودی خود یک Pattern نسبتا ساده است، اما معمولا با Event Sourcing ترکیب می‌شود. در این ترکیب، هر Command یک Event تولید می‌کند، آن Event در یک Event Store ذخیره می‌شود، و Query Side با خواندن این Eventها وضعیت فعلی را می‌سازد.یک نکته مهم: CQRS همیشه مناسب نیست. برای سیستم‌های ساده، این Pattern پیچیدگی غیرضروری اضافه می‌کند. این Pattern بیشتر در سیستم‌هایی مفید است که نیاز به مقیاس‌پذیری جداگانه برای عملیات خواندن و نوشتن دارند، یا که منطق کسب‌وکار پیچیده‌ای دارند.منابع‎[1] Young, G. (2010). CQRS Documents. https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf[2] Fowler, M. (2011). CQRS. https://martinfowler.com/bliki/CQRS.html[3] Vernon, V. (2013). Implementing Domain-Driven Design. Addison-Wesley Professional.9. Event-Driven Architecture (EDA)در معماری‌های سنتی، وقتی سرویس A به نتیجه عمل سرویس B نیاز دارد، مستقیما آن را فراخوانی می‌کند و منتظر پاسخ می‌ماند. این رویکرد Synchronous ساده و قابل فهم است، اما در مقیاس‌های بزرگ به سرعت تبدیل به گلوگاه می‌شود. معماری رویداد‌محور یا EDA این مشکل را با تغییر بنیادی در نحوه ارتباط اجزای سیستم حل می‌کند.در EDA، اجزای سیستم از طریق رویدادها (Events) با یکدیگر ارتباط برقرار می‌کنند. یک سرویس رویدادی منتشر می‌کند (مثلا کاربر جدیدی ثبت‌نام کرد)، سپس کار خود را ادامه می‌دهد بدون اینکه منتظر واکنش باشد. سرویس‌های دیگری که به این رویداد اهمیت می‌دهند آن را می‌شنوند و واکنش نشان می‌دهند. مثلا سرویس ایمیل یک ایمیل خوش‌آمدگویی می‌فرستد، سرویس آمار کاربر جدید را ثبت می‌کند.سه مفهوم اصلی در EDA وجود دارد؛ Event Producer که رویداد را تولید می‌کند، Event Broker که رویدادها را دریافت و توزیع می‌کند (مثل Apache Kafka یا RabbitMQ)، و Event Consumer که به رویدادهای مورد علاقه‌اش گوش می‌دهد و پردازش می‌کند.مزایای اصلی EDA عبارتند از Loose Coupling یا اتصال شل بین سرویس‌ها (سرویس‌ها نمی‌دانند چه کسی به رویدادهایشان گوش می‌دهد)، Scalability بالا (هر Consumer می‌تواند به‌صورت مستقل مقیاس‌پذیری شود)، و امکان اضافه کردن Consumer جدید بدون تغییر در Producer.اما EDA چالش‌هایی هم دارد. Debugging در سیستم‌های EDA دشوارتر است چون جریان اطلاعات خطی نیست. همچنین مدیریت Eventual Consistency، وضعیتی که داده‌ها در سیستم‌های مختلف در لحظه‌های مختلف به‌روزرسانی می‌شوند، پیچیدگی منطق کسب‌وکار را افزایش می‌دهد.Event Driven Architectureمنابع‎[1] Stopford, B. (2018). Designing Event-Driven Systems. O&#39;Reilly Media.[2] Richardson, C. (2018). Microservices Patterns. Manning Publications.[3] Fowler, M. (2017). What do you mean by &#39;Event-Driven&#39;?https://martinfowler.com/articles/201701-event-driven.html10. Serverless Architectureنام Serverless کمی گمراه‌کننده است؛ چون سرور همچنان وجود دارد، اما ما به عنوان توسعه‌ دهنده دیگر نگران مدیریت، پیکربندی، و مقیاس‌دهی آن نیستیم. Serverless یک مدل اجرایی است که در آن فقط کد خود را می‌نویسیم و ارائه‌دهنده ابری مسئول همه چیز دیگر، از تامین منابع گرفته تا مقیاس‌دهی خودکار است.مهم‌ترین شکل Serverless، Function as a Service یا FaaS است. در این مدل، کد به صورت توابع مستقل نوشته می‌شود که در پاسخ به رویدادها مثل یک درخواست HTTP، آپلود یک فایل، یا دریافت یک پیام، اجرا می‌شوند. AWS Lambda ،Google Cloud Functions و Azure Functions معروف‌ترین نمونه‌های FaaS هستند.مدل پرداخت در Serverless هم متفاوت است. به جای اینکه برای سرور اجاره داده شده در طول شبانه‌ روز هزینه پرداخت کنیم، فقط برای زمانی که کدمان واقعا اجرا می‌شود هزینه می‌دهیم. این برای workload هایی که ترافیک نامنظم و ناپیوسته دارند بسیار مقرون‌به‌صرفه است.مزایای اصلی Serverless، عدم نیاز به مدیریت سرور (که باری از دوش توسعه‌دهنده برمی‌دارد)، مقیاس‌پذیری خودکار تا بی‌نهایت، و مدل هزینه Pay-per-use. اما معایب هم وجود دارند؛ Cold Start یعنی اولین اجرای یک تابع بعد از مدتی غیرفعال بودن ممکن است کند باشد. همچنین محدودیت‌هایی در زمان اجرا (معمولا حداکثر چند دقیقه) و حافظه وجود دارد. و Debugging و Testing محلی دشوارتر است.Serverless برای همه کارها مناسب نیست. برنامه‌هایی که نیاز به پردازش طولانی‌مدت، حالت دائمی، یا Latency بسیار پایین دارند معمولا گزینه‌های بهتری دارند. اما برای API‌ های رویداد محور، پردازش فایل، تبدیل داده، و automation taskها، Serverless انتخاب عالی است.منابع‎[1] Roberts, M. (2018). Serverless Architectures. https://martinfowler.com/articles/serverless.html[2] Baldini, I., et al. (2017). Serverless Computing: Current Trends and Open Problems. Research Advances in Cloud Computing. Springer.[3] Amazon Web Services. (2023). AWS Lambda Developer Guide. https://docs.aws.amazon.com/lambda/latest/dg/welcome.html11. API-First Approachدر دنیایی که اپلیکیشن‌های موبایل، وب، IoT، و سرویس‌های شخص ثالث همگی به سیستم ما متکی هستند، طراحی API دیگر یک کار ثانویه بعد از ساخت سیستم نیست و باید اولین و اصلی‌ترین قدم باشد. رویکرد API-First دقیقا همین را می‌گوید.در رویکرد API-First، قبل از اینکه حتی یک خط کد پیاده‌سازی بنویسیم، API را طراحی می‌کنیم و مستندسازی می‌کنیم. این طراحی به عنوان قرارداد (Contract) بین تیم‌های Frontend، Backend، و تیم‌های خارجی عمل می‌کند. همه می‌دانند چه Endpointهایی وجود خواهد داشت، چه داده‌ای ارسال و دریافت می‌شود، و چه خطاهایی ممکن است رخ دهد.استاندارد OpenAPI که قبلا Swagger نامیده می‌شد، معمولا برای توصیف API استفاده می‌شود. با داشتن این مستند، می‌توان به‌ صورت خودکار Client SDK، Server Stub، مستندات تعاملی، و حتی Mock Serverها تولید کرد. Mock Server به تیم Frontend اجازه می‌دهد قبل از اینکه Backend واقعی آماده شود، توسعه خود را شروع کند.مزایای این رویکرد توسعه موازی تیم‌های Frontend و Backend، کشف مشکلات طراحی قبل از پیاده‌سازی (اصلاح یک طراحی بد در مرحله قبل از کدنویسی بسیار ارزان‌تر از اصلاح آن بعد از پیاده‌سازی است)، مستندات همیشه به‌روز (چون از کد تولید می‌شوند)، و قابلیت Backward Compatibility بهتر.ابزارهای معروف در این حوزه شامل Swagger/OpenAPI برای توصیف API ،Postman برای تست و Mock Stoplight برای طراحی بصری API، و Pact برای Contract Testing هستند. API-First رویکردی است که به خصوص در سازمان‌هایی که محصولاتشان Platform هستند یا API را به شرکای تجاری ارائه می‌دهند، بسیار مهم است.منابع‎[1] Higginbotham, J. (2021). Principles of Web API Design: Delivering Value with APIs and Microservices. Addison-Wesley Professional.[2] OpenAPI Initiative. (2023). OpenAPI Specification. https://spec.openapis.org/oas/v3.1.0[3] Jacobson, D., Brail, G., &amp; Woods, D. (2011). APIs: A Strategy Guide. O&#39;Reilly Media.12. Domain-Driven Design (DDD)یکی از اصلی‌ترین چالش‌ها در توسعه نرم‌افزارهای پیچیده، شکاف بین دنیای کسب‌وکار و دنیای فنی است. توسعه‌دهندگان با زبان کد صحبت می‌کنند و کارشناسان دامنه با زبان کسب‌وکار. Domain-Driven Design یا DDD رویکردی است که این شکاف را کاهش می‌دهد.DDD که توسط Eric Evans در کتاب معروفش در سال ۲۰۰۳ معرفی شد، بر این ایده استوار است که مدل نرم‌افزار باید بازتاب عمیق دامنه کسب‌وکار باشد، نه صرفا یک سازمان‌دهی فنی. تمام کد، کلاس‌ها، و عملیات باید با واژگان و مفاهیمی که متخصصین کسب‌وکار استفاده می‌کنند نام‌گذاری و سازماندهی شوند.مفهوم محوری DDD، Ubiquitous Language یا زبان فراگیر است. این زبان مشترکی است که هم توسعه‌دهندگان و هم متخصصین کسب‌وکار از آن استفاده می‌کنند. یک واژه‌نامه مشترک که در مستندات، در کد و در مکالمات روزمره استفاده می‌شود. اگر در کسب‌وکار به چیزی سفارش می‌گویند، در کد هم باید Order باشد، نه Transaction یا Record.DDD مفاهیم سازماندهی دیگری هم دارد. Bounded Context مرزی است که یک مدل کسب‌وکار در آن معنای مشخصی دارد. مثلا محصول در زمینه انبارداری معنای متفاوتی نسبت به محصول در زمینه فروش دارد. Aggregate گروهی از Entity و Value Objectهاست که به عنوان یک واحد منسجم با هم مدیریت می‌شوند. Aggregate Root تنها نقطه ورودی برای تغییر در این گروه است.Domain Driven DesignDDD با Microservices ارتباط تنگاتنگی دارد. هر Bounded Context معمولا یک کاندیدای خوب برای تبدیل شدن به یک Microservice مستقل است. این رویکرد به سازمان‌ها کمک می‌کند سرویس‌هایی بسازند که با ساختار کسب‌وکار همسو هستند.منابع‎[1] Evans, E. (2003). Domain-Driven Design: Tackling Complexity in the Heart of Software. Addison-Wesley.[2] Vernon, V. (2013). Implementing Domain-Driven Design. Addison-Wesley Professional.[3] Millett, S., &amp; Tune, N. (2015). Patterns, Principles, and Practices of Domain-Driven Design. Wrox.13. Hexagonal Architectureیکی از مشکلات رایج در معماری نرم‌افزار این است که منطق کسب‌وکار با جزئیات زیرساختی مثل پایگاه‌داده، API خارجی، یا رابط کاربری درهم آمیخته می‌شود. این درهم‌آمیختگی باعث می‌شود تست کردن منطق، تغییر دادن پایگاه‌داده، یا اضافه کردن یک کانال جدید ارتباطی بسیار دشوار شود. Hexagonal Architecture این مشکل را با یک ایده ساده اما قدرتمند حل می‌کند.این معماری توسط Alistair Cockburn با نام Ports and Adapters معرفی شد. ایده اصلی این است که منطق اصلی کسب‌وکار (هسته سیستم) در مرکز قرار می‌گیرد و از طریق Portها که در واقع Interface هستند، با دنیای خارج ارتباط برقرار می‌کند. هیچ وابستگی مستقیمی از هسته به جزئیات خارجی وجود ندارد. Adapter نیز وظیفه ترجمه بین زبان دنیای خارج و زبان هسته را دارد.برای مثال، یک HTTP Adapter درخواست HTTP را می‌گیرد و آن را به یک فراخوانی متد روی هسته تبدیل می‌کند. یک Database Adapter متدهای Repository را که هسته می‌شناسد پیاده‌سازی می‌کند و با پایگاه‌داده واقعی ارتباط برقرار می‌کند.شش‌ضلعی بودن شکل این معماری معنای خاصی ندارد و فقط نشان می‌دهد که یک هسته با جهات متعدد وجود دارد. می‌توانیم از سمت API Web یا Primary/Driving Port، از سمت CLI، از سمت یک سیستم خارجی، یا از سمت تست‌ها به هسته دسترسی داشته باشیم.مهم‌ترین مزیت این معماری، تست‌پذیری عالی‌اش هست. چون هسته هیچ وابستگی به زیرساخت ندارد، می‌توان آن را کاملا بدون پایگاه‌ داده یا شبکه تست کرد. همچنین تعویض پایگاه‌ داده یا تغییر کانال ارتباطی بدون لمس کردن منطق کسب‌وکار ممکن است. Clean Architecture و Onion Architecture نیز ایده‌های مشابهی دارند.منابع‎[1] Cockburn, A. (2005). Hexagonal Architecture. https://alistair.cockburn.us/hexagonal-architecture/[2] Martin, R. C. (2017). Clean Architecture: A Craftsman&#39;s Guide to Software Structure and Design. Prentice Hall.[3] Wlaschin, S. (2018). Domain Modeling Made Functional. Pragmatic Bookshelf.14. Event Sourcingدر اکثر سیستم‌ها، وقتی چیزی تغییر می‌کند، مقدار قدیمی را با مقدار جدید جایگزین می‌کنیم. وقتی کاربر اسمش را عوض می‌کند، مقدار قدیمی از بین می‌رود. وقتی موجودی انبار تغییر می‌کند، فقط عدد جدید باقی می‌ماند.Event Sourcing این رویکرد را به کلی زیر سوال می‌برد.در Event Sourcing به جای ذخیره وضعیت فعلی، تمام رویدادهایی که به آن وضعیت منجر شده‌اند را ذخیره می‌کنیم. مثل اینکه به جای نگه داشتن موجودی فعلی حساب بانکی، تمام تراکنش‌ها را نگه می‌داریم. موجودی فعلی را در هر لحظه با جمع زدن همه تراکنش‌ها می‌توانیم محاسبه کنیم.این رویکرد مزایای بسیار جالبی دارد. اول، Audit Log کامل که تاریخچه کامل هر تغییری در سیستم ثبت شده است، یعنی کی چه کرده، کجا، و در پاسخ به چه رویدادی. دوم، قابلیت Time Travel که می‌توانیم وضعیت سیستم را در هر نقطه از زمان بازسازی کنیم. سوم، امکان Debug کردن کامل که در آن می‌توانیم دقیقا ببینیم چه اتفاقی افتاد که به یک باگ منجر شد.یکی از کاربردهای جذاب Event Sourcing، قابلیت Replay کردن رویدادهاست. اگر یک باگ کشف کنیم، می‌توانیم آن را رفع کنیم و سپس تمام رویدادهای تاریخی را دوباره پردازش کنیم تا وضعیت صحیح را به دست بیاوریم. یا اگر یک View جدید نیاز داشته باشیم، می‌توانیم از ابتدا تمام رویدادها را پردازش کنیم.چالش‌های Event Sourcing اول اینکه برای بازسازی وضعیت فعلی باید همه رویدادها را پردازش کنیم که با افزایش تعداد رویدادها کندتر می‌شود که این با Snapshot حل می‌شود. دوم، تکامل رویدادها (Event Schema Evolution) پیچیده است که اگر فرمت یک رویداد تغییر کند، با رویدادهای قدیمی چه کنیم؟ سوم، این رویکرد با تفکر CRUD رایج فاصله زیادی دارد و نیاز به تغییر ذهنیت دارد.منابع‎[1] Young, G. (2010). CQRS and Event Sourcing. https://cqrs.files.wordpress.com/2010/11/cqrs_documents.pdf[2] Fowler, M. (2005). Event Sourcing. https://martinfowler.com/eaaDev/EventSourcing.html[3] Vernon, V. (2016). Domain-Driven Design Distilled. Addison-Wesley Professional.15. Low-code / No-code Platformsبرای مدت‌های طولانی، ساخت نرم‌افزار مستلزم دانش عمیق برنامه‌نویسی بود. اما موج Low-code و No-code در حال تغییر این معادله است. این پلتفرم‌ها به افراد و سازمان‌ها اجازه می‌دهند بدون نوشتن یا با نوشتن کد کم اپلیکیشن‌های کاربردی بسازند.No-code پلتفرم‌هایی هستند که کاملا بدون کد کار می‌کنند و از رابط‌های بصری Drag and Drop استفاده می‌کنند؛ مثل Bubble، Webflow، یا Airtable. ولی Low-code پلتفرم‌هایی هستند که تا حد زیادی بصری هستند اما در مواقع لازم اجازه می‌دهند کد سفارشی هم بنویسیم؛ مثل OutSystems ،Mendix یا Microsoft Power Apps.این پلتفرم‌ها به چه دردی می‌خورند؟ به Citizen Developers و کارمندانی که دانش کسب‌ و کار عمیقی دارند اما برنامه‌نویس نیستند، اجازه می‌دهند ابزارهای مورد نیاز خودشان را بسازند. همچنین برای سازمان‌هایی که با کمبود نیروی فنی روبرو هستند، سرعت توسعه را به شکل چشمگیری افزایش می‌دهند.کاربردهای رایج شامل ساخت داشبوردهای داخلی، اتوماسیون فرآیندهای کسب‌وکار، فرم‌های سازمانی، و Prototyping سریع ایده‌ها هستند. برخی سازمان‌ها حتی محصولات کامل و پیچیده‌ای روی این پلتفرم‌ها ساخته‌اند.اما محدودیت‌هایی هم وجود دارد؛ مثل قابلیت سفارشی‌سازی محدود برای نیازهای پیچیده، وابستگی به ارائه‌ دهنده پلتفرم (Vendor Lock-in)، چالش‌های مقیاس‌ پذیری در برخی موارد، و سوالاتی درباره امنیت و رعایت مقررات. پلتفرم‌های Low-code/No-code ابزارهای قدرتمندی هستند، اما نباید به عنوان جایگزین کامل توسعه حرفه‌ای تلقی شوند.منابع[1] Forrester Research. (2021). The State Of Low-Code Platforms In 2021.[2] Cabot, J. (2020). About the complexities of low-code/no-code software development. IEEE Software Blog.[3] Gartner. (2022). Magic Quadrant for Enterprise Low-Code Application Platforms.16. Business Process Management Systems (BPMS)هر سازمانی فرآیندهایی دارد؛ از استخدام کارمند تا پردازش سفارش مشتری، از درخواست مرخصی تا تایید فاکتور. مدیریت این فرآیندها به شکل سیستماتیک، قابل اندازه‌گیری، و بهینه‌شده دقیقا حوزه‌ای است که BPMS یا سیستم‌های مدیریت فرآیند کسب‌ و کار به آن می‌پردازند.BPMS یک دسته از نرم‌افزارهاست که به سازمان‌ها کمک می‌کند فرآیندهای کسب‌وکارشان را مدل‌سازی، اجرا، نظارت، و بهینه‌سازی کنند. چرخه حیات در BPMS شامل چهار مرحله اصلی است؛ Design که به طراحی فرآیند با استفاده از استانداردهایی مثل BPMN گفته می‌شود، Deploy یعنی استقرار و اجرای فرآیند، Execute یعنی اجرای خودکار یا نیمه‌خودکار وظایف و Monitor که نظارت بر عملکرد و شناسایی بهبودها است.چرخه BPMBPMN یا Business Process Model and Notation، زبان استانداردی است که برای توصیف بصری فرآیندهای کسب‌وکار استفاده می‌شود. با BPMN می‌توانیم جریان کار، تصمیم‌گیری‌ها، وظایف موازی، رویدادها و مسئولیت‌ها را به شکلی گرافیکی نمایش دهیم که هم برای افراد فنی و هم برای افراد کسب‌ و کاری قابل فهم باشد.ابزارهای معروف BPMS شامل Camunda که هم Open Source و هم Enterprise دارد و بر پایه BPMN و DMN است، Activiti، IBM Business Process Manager، و Appian هستند. Camunda به خصوص در میان توسعه‌دهندگان محبوب است چون می‌توان آن را به‌راحتی در کد Java یا دیگر زبان‌ها جاسازی کرد.تفاوت BPMS با ابزارهای workflow ساده‌تر این است که BPMS یک چرخه کامل مدیریت فرآیند را پوشش می‌دهد و قابلیت‌های تحلیلی جدی دارد. می‌توان دید کدام مرحله گلوگاه است، میانگین زمان تکمیل هر فرآیند چقدر است و کجا خطا رخ می‌دهد.منابع[1] Dumas, M., La Rosa, M., Mendling, J., &amp; Reijers, H. A. (2018). Fundamentals of Business Process Management (2nd ed.). Springer.[2] Weske, M. (2019). Business Process Management: Concepts, Languages, Architectures (3rd ed.). Springer.[3] Object Management Group. (2013). Business Process Model and Notation (BPMN) 2.0.2. https://www.omg.org/spec/BPMN/2.0.217. Message Queue (such as Kafka and RabbitMQ)تصور کنید یک سیستم پرداخت آنلاین دارید که در لحظات اوج (مثلا Black Friday) هزاران درخواست در ثانیه دریافت می‌کند. اگر هر درخواست مستقیما به سرویس پردازش پرداخت ارسال شود، ممکن است سیستم تحت فشار خراب شود. Message Queue راه‌ حل این مشکل است.یک Message Queue (صف پیام) یک ابزار میانجی است که پیام‌ها را از فرستنده دریافت می‌کند، آن‌ها را ذخیره می‌کند، و با سرعتی که دریافت‌کننده می‌تواند پردازش کند به او تحویل می‌دهد. این مکانیزم یک بافر ایجاد می‌کند که تولیدکننده و مصرف‌کننده پیام را از هم جدا می‌کند.RabbitMQ یک Message Broker سنتی است که بر اساس پروتکل AMQP کار می‌کند. نقاط قوت آن در پیام‌رسانی مطمئن (Reliable Messaging)، routing انعطاف‌پذیر، و پشتیبانی از الگوهای مختلف مثلPublish/Subscribe Routing و Topic است. وقتی یک پیام توسط مصرف‌کننده پردازش شود، از صف حذف می‌شود.Apache Kafka رویکرد متفاوتی دارد. Kafka یک سیستم ثبت رویداد توزیع‌شده است که پیام‌ها را روی دیسک ذخیره می‌کند و برای مدت زمان قابل تنظیمی نگه می‌دارد. این یعنی چند Consumer متفاوت می‌توانند همان پیام را بخوانند، می‌توان پیام‌های قدیمی را دوباره خواند (Replay)، و حجم بسیار زیادی از داده را پردازش کرد. Kafka در Stream Processing، Event Sourcing و ادغام سیستم‌ها بسیار قوی است.چه وقت از کدام استفاده کنیم؟ RabbitMQ برای پیام‌رسانی سنتی، task queuing و وقتی که پیچیدگی routing نیاز داریم مناسب‌تر است. Kafka برای streaming داده‌های حجیم، Event Sourcing ،Real-time analytics و ادغام بین سیستم‌های مختلف انتخاب بهتری است. در بسیاری از معماری‌های بزرگ، هر دو ابزار همزمان استفاده می‌شوند.Kafka vs RabbitMQمنابع[1] Narkhede, N., Shapira, G., &amp; Palino, T. (2017). Kafka: The Definitive Guide. O&#39;Reilly Media.[2] Roy, M. (2019). RabbitMQ in Depth. Manning Publications.[3] Richardson, C. (2018). Microservices Patterns. Manning Publications.18. Containers &amp; Container orchestrationیکی از قدیمی‌ترین مشکلات در توسعه نرم‌افزار این بود که روی ماشین من کار می‌کند! یعنی اپلیکیشنی که در محیط توسعه درست اجرا می‌شود، در محیط تولید با مشکل مواجه می‌شود چون کتابخانه‌ها، تنظیمات، و محیط متفاوت است. Container برای حل این مشکل ساخته شد.یک Container یک بسته مستقل و قابل اجرا است که شامل کد اپلیکیشن، تمام کتابخانه‌های مورد نیاز، متغیرهای محیطی، و پیکربندی‌هاست. Container روی هر ماشینی که Docker (یا موتور Container مشابه) روی آن نصب باشد، به طور یکسان اجرا می‌شود. به این ترتیب محیط توسعه، تست، و تولید، یکسان هستند.Docker معروف‌ترین پلتفرم Container است. با یک Dockerfile که دستوراتی مثل از این Image پایه شروع کن، این فایل‌ها را کپی کن، این بسته‌ها را نصب کن را توصیف می‌کند، یک Docker Image ساخته می‌شود. از این Image می‌توان هر تعداد Container یکسان ایجاد کرد.Dockerاما وقتی اپلیکیشن از ده‌ها یا صدها Container تشکیل شده باشد چطور؟ اینجاست که Container Orchestration وارد می‌شود. Kubernetes (که معمولا K8s نامیده می‌شود) محبوب‌ترین سیستم Orchestration است. Kubernetes مسئولیت‌هایی مثل این را بر عهده می‌گیرد که زمان‌بندی و جایگذاری Container روی نودهای مناسب، راه‌اندازی مجدد Container‌های خراب، مقیاس‌پذیری خودکار بر اساس بار، مدیریت شبکه و Load Balancing و مدیریت اسرار (Secrets) و پیکربندی.تفاوت Container با ماشین مجازی (VM) در این است که Container خیلی سبک‌تر است چون به جای virtualize کردن کل سخت‌افزار، فقط فضای نرم‌افزار را ایزوله می‌کند و از Kernel سیستم عامل مشترک استفاده می‌کند. یک سرور می‌تواند صدها Container اجرا کند، در حالی که شاید ده‌ها VM داشته باشد.منابع[1] Burns, B., Grant, B., Oppenheimer, D., Brewer, E., &amp; Wilkes, J. (2016). Borg, Omega, and Kubernetes. ACM Queue, 14(1), 70–93.[2] Luksa, M. (2017). Kubernetes in Action. Manning Publications.[3] Docker Documentation. (2023). Docker Overview. https://docs.docker.com/get-started/overview19. Multi-Tenancy Architectureوقتی یک نرم‌افزار به عنوان سرویس (SaaS) به چندین سازمان یا مشتری (Tenant) ارائه می‌شود، یک سوال اساسی مطرح می‌شود که آیا برای هر مشتری یک نسخه جداگانه نرم‌افزار مستقر کنیم، یا همه مشتریان از یک نسخه مشترک استفاده کنند؟ معماری Multi-Tenancy پاسخ این سوال است.در معماری Multi-Tenant، یک نمونه واحد از نرم‌افزار به چندین مشتری سرویس می‌دهد، در حالی که داده‌ها و تنظیمات هر مشتری از دیگران جدا و ایزوله است. فکر کنید به سرویس‌هایی مثل Salesforce، Slack، یا Jira، هزاران سازمان از همان نرم‌افزار استفاده می‌کنند اما داده‌هایشان کاملاً از هم جداست.چندین استراتژی اصلی برای پیاده‌سازی Multi-Tenancy وجود دارد. روش اول، جداسازی در سطح پایگاه‌داده، یعنی هر Tenant یک Database جداگانه دارد. بیشترین ایزولاسیون را ارائه می‌دهد اما هزینه‌ بر است. روش دوم، Schema Separation هست، یعنی همه Tenantها در یک Database هستند اما هر کدام یک Schema جداگانه دارند. روش سوم، Row-level Separation هست، یعنی همه داده‌ها در یک Schema هستند و با یک Tenant ID از هم متمایز می‌شوند. این ارزان‌ترین روش است اما ایزولاسیون کمتری دارد.یکی از بزرگترین چالش‌ها در Multi-Tenancy که می‌شود بهش اشاره کرد، Noisy Neighbor است، وقتی یک Tenant با مصرف زیاد منابع بر عملکرد Tenantهای دیگر تاثیر می‌گذارد. مکانیزم‌هایی مثل Rate Limiting و Resource Quotas برای جلوگیری از این مشکل استفاده می‌شوند.علاوه بر جداسازی داده، یک Multi-Tenant سیستم باید امکاناتی مثل سفارشی‌سازی برای هر Tenant (Custom Branding، تنظیمات مختلف)، Tenant-level Authentication and Authorization و قابلیت Onboarding و Offboarding آسان Tenantها را فراهم کند.منابع[1] Bezemer, C.-P., &amp; Zaidman, A. (2010). Multi-tenant SaaS Applications: Maintenance Dream or Nightmare? IWPSE-EVOL 2010.[2] Chong, F., &amp; Carraro, G. (2006). Architecture Strategies for Catching the Long Tail. Microsoft MSDN.[3] AWS. (2022). SaaS Tenant Isolation Strategies. AWS Whitepaper. https://docs.aws.amazon.com/whitepapers/latest/saas-tenant-isolation-strategies20. Data Migrationآخرین مفهوم در این بخش، Data Migration یا انتقال داده است، موضوعی که ظاهرا ساده به نظر می‌رسد اما در عمل یکی از پر ریسک‌ترین فعالیت‌های مهندسی نرم‌افزار است. مهاجرت داده به فرآیند انتقال داده از یک سیستم، قالب، یا ساختار به سیستم، قالب، یا ساختار دیگر گفته می‌شود.Data Migration در چندین سناریوی اصلی رخ می‌دهد، تعویض پایگاه‌داده (مثلا از Oracle به PostgreSQL)، ارتقای نسخه نرم‌افزار (که ساختار جدول‌ها تغییر می‌کند)، ادغام دو سازمان (که داده‌های دو سیستم باید ترکیب شوند) و انتقال به فضای ابری.یک Data Migration معمولا شامل مراحل Extract (استخراج داده از منبع)، Transform (تبدیل داده به قالب مقصد و پاکسازی) و Load (بارگذاری در مقصد) است که با عنوان ETL شناخته می‌شود. مرحله Transform معمولا پیچیده‌ترین و زمان‌برترین بخش است که شامل داده‌های تکراری، داده‌های ناسازگار، فیلدهای اجباری که خالی هستند، یا ساختارهای متفاوت همه باید مدیریت شوند.یکی از مهم‌ترین چالش‌ها، مهاجرت بدون توقف سرویس (Zero-Downtime Migration) است. استراتژی رایج Dual Write است، یعنی در مدت مهاجرت، هر نوشتن هم در سیستم قدیمی و هم جدید انجام می‌شود. به تدریج ترافیک خواندن هم به سیستم جدید منتقل می‌شود. وقتی مطمئن شدیم همه چیز درست است، سیستم قدیمی خاموش می‌شود.فرآیند تکرار در AWS Database Migration Serviceاصل مهم در Data Migration این هست که هرگز بدون Rollback Plan مهاجرت نکن. باید همیشه برنامه‌ای برای بازگشت به وضعیت قبلی در صورت بروز مشکل وجود داشته باشد. همچنین تست Migration روی یک کپی از داده‌های واقعی (نه داده‌های تستی) قبل از اجرای واقعی ضروری است. بسیاری از پروژه‌های Migration به دلیل کم‌توجهی به این مرحله با شکست مواجه شده‌اند.منابع[1] Fowler, M. (2003). Patterns of Enterprise Application Architecture. Addison-Wesley.[2] Redman, T. C. (2018). If Your Data Is Bad, Your Machine Learning Tools Are Useless. Harvard Business Review.[3] AWS Documentation. (2023). Database Migration Guide. https://docs.aws.amazon.com/dms/latest/userguide/Welcome.htmlاگر تا اینجا همراه من بوده‌اید، احتمالا با مجموعه‌ای از مفاهیم و الگوهای مهم و پرکاربرد در دنیای مهندسی نرم‌افزار، معماری نرم افزار و توسعه نرم‌افزار مدرن آشنا شده‌اید. هدف من از نوشتن این مطالب، ارائه یک دید کلی، کاربردی و قابل فهم از موضوعاتی بود که امروزه در بسیاری از پروژه‌های واقعی و سازمان‌های فناوری مورد استفاده قرار می‌گیرند. طبیعتا هر یک از این مفاهیم دنیایی از جزئیات، تجربیات و مباحث تخصصی را در دل خود دارند و آنچه در این مجموعه ارائه شد، صرفا نقطه شروعی برای آشنایی بیشتر با آن‌هاست. امیدوارم مطالبی که در این نوشته‌ها با شما به اشتراک گذاشتم برایتان مفید، کاربردی و الهام‌بخش بوده باشد و بتواند در مسیر یادگیری، مطالعه یا حتی فعالیت حرفه‌ای شما کمک‌کننده باشد🌱نویسنده: امین مستوری نژاددانشجوی مهندسی نرم افزار دانشگاه شهید بهشتیخرداد 1405</description><category>امین مستوری نژاد</category><author>امین مستوری نژاد</author><pubDate>Sun, 31 May 2026 20:51:13 +0330</pubDate></item></channel></rss>