<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های آرمین مظفری</title>
        <link>https://virgool.io/feed/@arminm4</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-04-15 09:48:15</pubDate>
        <image>
            <url>https://static.virgool.io/images/default-avatar.jpg</url>
            <title>آرمین مظفری</title>
            <link>https://virgool.io/@arminm4</link>
        </image>

                    <item>
                <title>تست</title>
                <link>https://virgool.io/@arminm4/%D8%AA%D8%B3%D8%AA-o3zwxcae5wgz</link>
                <description>رویکرد نظریه گراف و تحلیل حلقه‌های علیتی در تشخیص اوتیسم از طریق شبکه‌های عملکردی مغز گزارش درس شبکه‌های پیچیدهچکیدهدر این گزارش، کاربرد نظریه گراف و تحلیل حلقه‌های علیتی برای تشخیص و تفکیک شبکه‌های عملکردی مغز در افراد مبتلا به اختلال طیف اوتیسم (ASD) و افراد سالم بررسی می‌شود. ابتدا داده‌های fMRI گردآوری شده و شبکه‌های عملکردی مغز با استفاده از آتلانسی مشخص تقسیم‌بندی می‌گردند. آنگاه، با استخراج گرافلت‌ها و سایر پارامترهای مهم گرافی (از جمله حلقه‌های بازخورد در سطوح مختلف رتبه)، تفاوت‌های ساختاری و دینامیکی میان دو گروه بررسی می‌گردد. نتایج نشان می‌دهد که الگوی تشکیل حلقه‌های بازخورد (Feedback Loops) در مغز سالم، تفاوت آماری معناداری با مغز اوتیسمی دارد و از این تفاوت‌ها می‌توان به‌عنوان بیومارکر بالقوه در طبقه‌بندی و غربالگری اوتیسم بهره جست. همچنین، روش‌های یادگیری ماشین و شبکه‌های عصبی برای طبقه‌بندی این تفاوت‌ها به‌کار برده شده‌اند که نتایج آن‌ها برتری رویکردهای مبتنی بر گراف و حلقه‌های علّی را در تشخیص اوتیسم نشان می‌دهد.۱. مقدمهاختلال طیف اوتیسم (ASD) یک اختلال رشدی عصبی است که با مشکلات ارتباطات اجتماعی، الگوهای رفتاری تکراری و چالش در تعاملات اجتماعی همراه است. تشخیص زودهنگام این اختلال، نقش بسزایی در بهبود فرایندهای توان‌بخشی و آموزشی دارد؛ به همین دلیل، پژوهش‌های متعددی به شناسایی نشانگرهای زیستی (Biomarkers) در تصویربرداری‌های مغزی پرداخته‌اند. در سال‌های اخیر، نظریه گراف و تحلیل شبکه به‌عنوان ابزارهای قدرتمندی برای شناخت ساختار و پویایی ارتباطات مغزی در حالت استراحت (Resting-state) یا حین انجام وظایف (Task-based) مطرح شده‌اند 1,21,2.علاوه بر این، مفهوم حلقه‌های علیتی (Causal Loops) یا بازخورد (Feedback) در شبکه‌های عصبی از اهمیت ویژه‌ای برخوردار است، چرا که بسیاری از رفتارها و فرایندهای شناختی مغز در بستر تعامل‌های تکرارشونده و بازگشتی شکل می‌گیرد 33. در این پژوهش، تلاش شده است تا با تکیه بر رویکرد نظریه گراف و بررسی حلقه‌های بازخورد در شبکه‌های عملکردی (Functional Connectivity)، تفاوت‌های ساختاری و دینامیکی مغز افراد سالم و افراد مبتلا به اوتیسم شناسایی گردد.۲. پیشینه مطالعاتیاستفاده از گرافلت‌ها برای تشخیص اوتیسم: گرافلت‌ها زیرساختارهای کوچک و غیرایزومورفیک در شبکه هستند که فراوانی آن‌ها ویژگی‌های توپولوژیک شبکه را بازتاب می‌دهد. براساس پژوهش‌های پیشین 44، محاسبه فراوانی گرافلت‌ها در شبکه‌های مغزی می‌تواند در طبقه‌بندی افراد سالم و مبتلا به اوتیسم مؤثر باشد.شبکه‌های عصبی عمیق: مطالعاتی 55 نشان داده‌اند که استفاده از شبکه‌های عصبی پیچشی (CNN) و داده‌های fMRI می‌تواند در شناسایی خودکار اوتیسم به دقت بالاتری منجر شود. با این حال، این رویکرد اغلب به داده‌های حجیم و برچسب‌دار نیاز دارد.پارامترهای جهانی و محلی در شبکه مغزی: پارامترهایی نظیر ضریب خوشه‌بندی، میانگین طول مسیر، کارایی شبکه و مرکزیت در تمایز شبکه‌های مغزی سالم و بیمار به کار رفته‌اند 66. برخی یافته‌ها نشان می‌دهند که در اوتیسم تغییرات قابل‌توجهی در پارامترهای محلی نیمکره راست مغز رخ می‌دهد 66.بررسی نقش اتصالات منفی: پژوهش‌ها 77 حاکی از آن هستند که لینک‌های منفی در شبکه مغزی—که پیش‌تر کمتر مورد توجه بودند—در پایداری و شکل‌گیری هاب‌های منفی مؤثر بوده و ممکن است در بیماری‌های عصبی تفاوت ایجاد کنند.۳. روش‌شناسی۳.۱. داده‌ها و پیش‌پردازشبرای انجام این مطالعه، داده‌های تصویربرداری تشدید مغناطیسی عملکردی (fMRI) از منابع عمومی مانند ABIDE، USC Multimodal Connectivity Database و سایر پایگاه‌های معتبر استخراج شد. سپس مراحل زیر بر روی داده‌ها اعمال گردید:اصلاح حرکت (Motion Correction) و نرمال‌سازی شدت (Intensity Normalization) جهت کاهش نویز حرکتی.حذف نویز فیزیولوژیک همچون سیگنال‌های مرتبط با ضربان قلب و تنفس.فیلترگذاری باند-پایین برای حذف سیگنال‌های با فرکانس بسیار بالا.تقسیم‌بندی مغز (Parcellation) با استفاده از آتلانس‌هایی نظیر Power-264 یا CC400 برای تعیین نقاط (ROIها).۳.۲. تشکیل شبکه‌های عملکردیپس از استخراج میانگین سیگنال BOLD در هر ROI، همبستگی میان ROIها به‌عنوان یال‌های شبکه در نظر گرفته شد. آستانه‌گذاری مبتنی بر چگالی شبکه (Density-based Thresholding) در بازه‌ای مانند ۰٫۱۵ تا ۰٫۳۲ صورت گرفت تا تعداد بهینه‌ای از یال‌ها در شبکه باقی بماند و به تخمین مناسبی از ساختار شبکه دست یابیم.۳.۳. استخراج و تحلیل گرافلت‌هاگرافلت‌ها (Graphlets) به‌عنوان زیرساختارهای کوچک در شبکه، به منظور استخراج ویژگی‌های توپولوژیک استفاده شدند 44. در این مرحله:شمارش گرافلت‌ها (تا ۵ یا ۶ گره) در هر شبکه انجام شد.گرافلت‌هایی با بیشترین قدرت تمایزبخشی میان دو گروه (سالم و اوتیسمی) انتخاب گردید.بردار ویژگی نهایی به طبقه‌بندهای مختلفی چون SVM، KNN و درخت تصمیم داده شد.۳.۴. تحلیل حلقه‌های بازخورد (Causal Loops)در بخش دیگری از این پژوهش، حلقه‌های علیتی و بازخوردی در شبکه بررسی گردیدند:تعریف رتبه (Rank): اگر اطلاعات پس از عبور از kk یال مجدداً به همان گره بازگردد، رتبه حلقه kk خواهد بود.انواع حلقه‌ها برای شبکه سالم، شبکه اوتیسمی و همچنین شبکه‌های تصادفی (Random Networks) استخراج شد.مقایسه شدت جریان اطلاعات در این حلقه‌ها نشان داد که در مغز سالم، میزان حلقه‌های بازخورد در رتبه‌های بالاتر بیشتر است، حال آنکه در شبکه‌های اوتیسمی و تصادفی رفتار متفاوتی مشاهده می‌شود.۴. نتایجتفاوت در حلقه‌های بازخورد: نتایج نشان داد که حلقه‌های بازخورد (Loops) با رتبه‌های بالا (مثلاً ۴ و ۵) در شبکه مغز سالم فراوان‌تر و قوی‌تر از مغز اوتیسمی است. این امر می‌تواند نشان‌دهنده پویایی بازخوردی پیچیده‌تر در مغز سالم باشد.مقایسه با شبکه‌های تصادفی: در شبکه‌های تصادفی، شدت حلقه‌های بازخورد به‌مراتب کمتر و به شکل سریع‌تری به صفر میل می‌کرد. این یافته مؤید آن است که ساختار واقعی مغز—چه در حالت سالم و چه در حالت اوتیسمی—دارای الگوی غیرتصادفی و سازمان‌یافته است.مقایسه شاخص‌های گرافی: پارامترهای جهانی مانند ضریب خوشه‌بندی و کارایی جهانی تفاوت‌های معناداری را نشان ندادند؛ اما شاخص‌های محلی (مانند Betweenness Centrality و Degree Centrality) در برخی نواحی نیمکره راست و همچنین توزیع لینک‌های منفی در شبکه اوتیسمی نسبت به گروه سالم تغییرات قابل‌توجه داشتند.دقت طبقه‌بندی: در آزمون‌های طبقه‌بندی، روش‌های مبتنی بر گرافلت‌ها و شاخص‌های بازخورد، به دقتی در حدود ۷۰ تا ۷۵ درصد دست یافتند که نسبت به برخی روش‌های مرسوم (مانند روش‌های ساده همبستگی) عملکرد بهتری داشت.۵. بحث و بررسییافته‌های این پژوهش اهمیت ساختار شبکه‌ای مغز و به‌ویژه حلقه‌های علّی و بازخوردی را در تشخیص و تمایز اوتیسم برجسته می‌سازد. درک بهتر مکانیزم‌های بازخوردی در مغز می‌تواند بینش‌های تازه‌ای درباره علت‌شناسی اختلال طیف اوتیسم و الگوهای ارتباط عملکردی در آن ارائه دهد. نتایج حاکی از آن است که استفاده از رویکرد تحلیل بازخورد و پویایی‌های علّی می‌تواند نسبت به روش‌های صرفاً مبتنی بر همبستگی، تصویر جامع‌تری از شبکه‌های عصبی ارائه کند.با این حال، محدودیت‌های موجود—از جمله اندازه کوچک نمونه، تفاوت در پروتکل‌های تصویربرداری مراکز مختلف و نویزهای حرکتی—می‌توانند بر پایداری نتایج تأثیرگذار باشند. همچنین، ادغام روش‌های یادگیری عمیق و افزایش حجم داده‌ها می‌تواند منجر به بهبود دقت تشخیص اوتیسم در مطالعات آتی شود.۶. جمع‌بندیرویکرد ترکیبی نظریه گراف و تحلیل حلقه‌های علیتی، راهکاری نویدبخش برای شناسایی الگوهای ناهنجار در شبکه‌های مغزی اوتیسم است. وجود تفاوت‌های آماری معنادار در ساختار و شدت حلقه‌های بازخورد، قابلیت این روش را در غربالگری و تشخیص اوتیسم برجسته می‌کند. آینده پژوهش در این حوزه، شامل توسعه مدل‌های چندوجهی، استفاده از تکنیک‌های عمیق یادگیری و بررسی جامع‌تر انواع داده‌های تصویربرداری خواهد بود. با گسترش پایگاه‌های داده و ارتقاء الگوریتم‌های تحلیلی، می‌توان به دقت و قابلیت تعمیم بیشتر در تشخیص اختلال طیف اوتیسم دست یافت.منابع و مراجع</description>
                <category>آرمین مظفری</category>
                <author>آرمین مظفری</author>
                <pubDate>Sat, 08 Feb 2025 14:18:25 +0330</pubDate>
            </item>
                    <item>
                <title>گزارش نهایی پروژه معماری نرم‌افزار دانشگاه شهید بهشتی</title>
                <link>https://virgool.io/@arminm4/%DA%AF%D8%B2%D8%A7%D8%B1%D8%B4-%D9%86%D9%87%D8%A7%DB%8C%DB%8C-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D9%86%D8%B1%D9%85-%D8%A7%D9%81%D8%B2%D8%A7%D8%B1-%D8%AF%D8%A7%D9%86%D8%B4%DA%AF%D8%A7%D9%87-%D8%B4%D9%87%DB%8C%D8%AF-%D8%A8%D9%87%D8%B4%D8%AA%DB%8C-p9nko9mbwezo</link>
                <description>این پست به بررسی معماری یک سیستم نرم‌افزاری فرضی در قالب درس معماری نرم‌افزار می‌پردازد. در این نوشتار، به تشریح چالش‌ها و تصمیم‌گیری‌های اتخاذ شده در فرآیند طراحی معماری این سیستم خواهیم پرداخت. کلیه فایل‌هایی که در این پست به آنها اشاره شده در یک مخزن گیت‌هاب به صورت عمومی در دسترس می‌باشد.لینک مخزن گیت‌هابابتدا به معرفی سیستم فرضی می‌پردازیم:سیستم جامع جستجوی آگهی‌های استخداممعرفی:این سیستم به منظور تسهیل فرآیند جستجوی کار و یافتن فرصت‌های شغلی مناسب طراحی شده است. سیستم با استفاده از کراولر، آگهی‌های استخدام را از سایت‌های مختلف کاریابی جمع‌آوری و در یک سامانه ذخیره می‌کند. کاربران با استفاده از برنامه موبایل یا وب‌سایت می‌توانند به آسانی به این آگهی‌ها دسترسی داشته باشند و نیاز به جستجوی جداگانه در هر سایت را نخواهند داشت.ویژگی‌ها:جستجوی یکپارچه: جستجوی آگهی‌های استخدام از تمام سایت‌های کاریابی در یکجاذخیره و دسته‌بندی: ذخیره و دسته‌بندی آگهی‌های مورد علاقه برای دسترسی آساناطلاع‌رسانی آنی: دریافت نوتیفیکیشن برای آگهی‌های جدید مطابق با علایق کاربر (ویژه)گزارش تحلیل پیشرفته بازار: دسترسی به گزارش‌های تحلیلی از بازار کار، حقوق و تقاضا برای تخصص‌های مختلف و... . (ویژه)بهبود رزومه: ارائه ابزارها و راهکارهایی برای ارتقای کیفیت رزومه و افزایش شانس یافتن شغل (ویژه)مزایا:صرفه‌جویی در زمان: جستجوی سریع و آسان آگهی‌های استخدامدسترسی به فرصت‌های بیشتر: یافتن آگهی‌های استخدامی از تمامی سایت‌های کاریابیشخصی‌سازی: دریافت آگهی‌های مرتبط با علایق و مهارت‌های کاربرافزایش شانس یافتن شغل: استفاده از ابزارهای تخصصی برای ارتقای رزومه و یافتن شغل مناسبمخاطبان:جویندگان کار: افراد در جستجوی شغل جدید یا ارتقای شغلیدانشجویان: فارغ‌التحصیلان جویای کارکارفرمایان: شرکت‌ها و سازمان‌ها به دنبال استخدام نیروی کارجمع‌بندی:این سیستم با ارائه یک راهکار جامع برای جستجوی آگهی‌های استخدام، به کارجویان در یافتن شغل مناسب و کارفرمایان در جذب نیروی کار مورد نیازشان کمک می‌کند.گام اول: تحلیل نیازمندی‌ها و طراحی پایهبرای توسعه سیستم فرضی مورد نظر، ابتدا باید به سراغ تحلیل نیازمندی‌ها و طراحی پایه سیستم نرم‌افزار می‌رفتیم. این فرآیند شامل مراحل زیر بود:1. تحلیل اولیه:تعیین محدوده کلی سیستمشناسایی محدودیت‌هامشخص کردن ویژگی‌های کارکردی و غیرکارکردی (کیفی) سیستم2. تدوین سند SRS:بر اساس اطلاعات جمع‌آوری شده در مرحله تحلیل اولیه، سندی به نام Software Requirements Specification (SRS) تدوین شد. این سند شامل شرح کاملی از نیازمندی‌های سیستم، از جمله اهداف، کارکردها، محدودیت‌ها و معیارهای کیفی بود.محدوده سیستم:این پروژه به تعریف یک سیستم جمع‌آوری و دسته‌بندی آگهی‌های استخدامی از منابع مختلف می‌پردازد. این سیستم امکان جمع‌آوری و نمایش آگهی‌های استخدامی از وبسایت‌ها، رسانه‌ها و منابع دیگر را فراهم می‌کند. کاربران قادرند با استفاده از این سیستم آگهی‌ها را بر اساس معیارهای مختلفی مانند مهارت‌ها، مکان، هزینه و سابقه کاری جستجو و فیلتر کنند. همچنین، امکان جستجوی پیشرفته و سفارشی‌سازی برای کاربران در نظر گرفته شده است. کاربران می‌توانند اشتراک ویژه خریداری کنند تا اعلان‌های استخدامی جدید را دریافت کنند. سیستم از لاگ‌های جستجو و تنظیمات شخصی‌سازی کاربران نیز پشتیبانی می‌کند. محدوده این پروژه به توسعه و بهبود این قابلیت‌ها و ارائه یک سامانه جامع برای جستجو و انتشار آگهی‌های استخدامی ادامه دارد و می‌تواند در آینده با توجه به نیازمندی‌ها و بازخوردهای مشتریان گسترش یابد.3. طراحی معماری:در این مرحله ما وارد بحث معماری نرم‌افزار شده‌ایم و کلیه کارهای قبلی برای طراحی معماری این سیستم لازم بودند. با استفاده از اطلاعات موجود در سند SRS، معماری مطلوب برای سیستم طراحی شد. این معماری شامل ساختار کلی سیستم، اجزای تشکیل دهنده آن و نحوه تعامل آنها با یکدیگر بود.مزایای این رویکرد:تضمین می‌کند که سیستم نهایی بر اساس نیازهای واقعی کاربران و با در نظر گرفتن محدودیت‌ها و معیارهای کیفی طراحی و توسعه یافته است.به عنوان یک نقشه راه برای توسعه سیستم عمل می‌کند و از بروز خطاها و انحرافات در طول فرآیند توسعه جلوگیری می‌کند.امکان برآورد دقیق‌تر زمان و هزینه توسعه را فراهم می‌کند.در این بخش، به بررسی تصمیمات معمارانه اتخاذ شده برای سیستم فرضی بر اساس نیازمندی‌های غیرکارکردی (کیفی) می‌پردازیم.نیازمندی‌های غیرکارکردی:در این بخش، مثال‌هایی از نیازمندی‌های غیر‌کارکردی (ویژگی‌های کیفی) به همراه یکی از معیار‌های سنجش برای آن‌ها که در سند وجود داشته، آمده است. کلیه ویژگی‌های کیفی و جزئیات بیشتر مربوط به آن‌ها در سند معماری (SAD) موجود در مخزن گیت‌هاب وجود دارد.  در دسترس بودن بالا (Availability): سیستم باید به طور مداوم در دسترس کاربران باشد و در صورت بروز خطا، میانگین زمان بازیابی  (MTTR) خطا کمتر از یک ساعت باشد.امنیت (Security): سیستم باید از اطلاعات کاربران در برابر دسترسی‌های غیرمجاز، سوء استفاده و افشا محافظت کند.قابلیت نگهداری (Maintainability): سیستم باید به گونه‌ای طراحی شود که به راحتی قابل نگهداری و ارتقا باشد.کارایی (Performance): این ویژگی به سرعت پاسخ‌دهی سیستم به درخواست‌های کاربران مربوط می‌شود. عملیات‌های حیاتی سیستم باید در کمتر از 2 ثانیه پاسخ داده شوند تا تجربه کاربری سریع و روانی را فراهم آورد.قابلیت مقیاس‌پذیری (Scalability): این سامانه باید قادر باشد تا حداقل ۱۰۰۰۰ کاربر و تراکنش را به صورت همزمان پشتیبانی کند، بدون آنکه عملکرد آن دچار افت شود.یکپارچگی (Integration): سیستم باید توانایی پشتیبانی از حداقل ۵+ سیستم خارجی را داشته باشد و به راحتی بتواند با API‌های مختلف ارتباط برقرار کند.قابلیت استفاده (Usability): این ویژگی به آسانی استفاده از سیستم توسط کاربران اشاره دارد. نرخ خطا باید کمتر از 1% باشد و کاربران بتوانند بدون نیاز به کمک و تنها با استفاده از رابط‌کاربری، سیستم را یاد بگیرند و از آن استفاده کنند.قابلیت اطمینان (Reliability): سیستم باید بتواند بین شکست‌های خود فاصله‌ی زمانی مناسبی داشته باشد (میانگین زمان بین شکست‌ها باید حداقل ۱۰۰۰ ساعت باشد) تا اطمینان حاصل شود که کاربران می‌توانند به طور مداوم از سرویس استفاده کنند.دسترس‌پذیری (Availability): سیستم باید توانایی فراهم کردن دسترسی مداوم به سرویس‌های خود را داشته باشد. هدف این است که سیستم بالا بودن بیش از 99.9% زمان را حفظ کند.یکنواختی (Consistency): داده‌ها و اطلاعات باید در سراسر سیستم یکنواخت و بدون تضاد باشند. این بدان معناست که در هر بخشی از سیستم که اطلاعاتی ثبت، بروزرسانی یا حذف می‌شوند، تغییرات باید به صورت همزمان در تمامی بخش‌های دیگر اعمال شوند.اکنون با توجه به محدوده سیستم، ویژگی‌‌های کارکردی و غیرکارکردی (کیفی و محدودیت‌ها) گفته شده، باید معماری‌های مختلفی را بررسی کرده و تصمیمات معمارانه و کلانی بگیریم و با استفاده از این تصمیم‌ها، بین آن‌ها trade off انجام دهیم. در ادامه معماری و تصمیمات اتخاذ شده به صورت کلی مرور می‌کنیم. جزئیات و سند کامل معماری در مخزن گیت‌هاب وجود دارد:برای مستند کردن جزئیات معماری، از قالب نمودار‌های مدل C4 و جداولی استفاده کردیم (روش 4+1).نمودار System Context:این نمودار سیستم را در بالاترین سطح انتزاع نشان می‌دهد و تعاملات آن با سیستم‌های خارجی، کاربران و محیط را به تصویر می‌کشد. نمودار مورد کاربری:نمودار Container Diagram:این نمودار ساختار داخلی سیستم را به تفکیک containerها (مخازن) مانند برنامه‌های وب، برنامه‌های موبایل، پایگاه داده‌ها و … نشان می‌دهد. نمودار Component Diagram:این نمودار اجزای داخلی هر container را به تفکیک مؤلفه‌های منطقی مانند کلاس‌ها، توابع و ماژول‌ها نشان می‌دهد.نمودار Deployment Diagram:این نمودار چگونگی استقرار سیستم در محیط عملیاتی را نشان می‌دهد.نمودار Dynamic Diagram:تعامل اجزای مختلف سیستم در طول زمان را نشان می‌دهد. این نمودار‌ها با استفاده از ابزار structurizr و با زبان structurizr DSL ایجاد شده‌اند. فایل DSL تولید این نمودار‌ها در مخزن گیت‌هاب وجود دارد.استفاده از این زبان برای تولید نمودار‌ها و قرار دادن کد آن در کنار سند معماری باعث می‌شود که در هنگام عوض شدن معماری و به طبع، بروز کردن سند معماری، با اعمال تغییرات در آن کد، بتوانیم کلیه نمودار‌ها را بروز کنیم.4. ابزار‌ها و تکنولوژی استفاده شده:پیاده‌سازی کلاینت گوشی: ANDROID/IOS، Flutterپیاده‌سازی کلاینت وب: Java / Spring MVCپیاده‌سازی کلاینت وب به صورت: PWA، ReactJSپیاده‌سازی بک‌اند اصلی که با باقی قسمت‌ها در ارتباط است: Java/Spring Bootپیاده‌سازی خزشگر سایت‌های استخدامی: Python + Seleniumفراخوانی API‌های سیستم‌های پیامک، ایمیل و تلفن گویا: NodeJSاستفاده به عنوان پایگاه داده NoSQL به دلیل اینکه آگهی‌ها ممکن است ساختارمند نباشند و ساختار خاص خود را داشته باشند: MongoDBبرای Cache کردن request‌ها و کاهش زمان پاسخ‌دهی: Redisسیستم تحلیل‌گر با تکنیک‌های داده‌کاوی و یادگیری ماشین همراه است: Pythonبرای ذخیره‌سازی و مدیریت لاگ‌ها: ELK Stack (Elasticsearch, Logstash, Kibana)برای ذخیره‌سازی اطلاعات اساسی مانند کاربران: PostgreSQL 5. مهمترین تصمیمات معماریباید به این نکته توجه شود که معماری حال حاضر ما، براساس نسل اول مایکروسرویس‌ها است که جداسازی ساده مؤلفه‌ها در آن انجام شده است و محیط توسعه و استقرار در آن، مستقل است. دلیل انتخاب این معماری، این بوده است که با توجه به محدودیت‌هایی که با آن‌ها سر و کار داشتیم (مانند بودجه، تیم، زیرساخت و ...)، اتخاذ یک رویکرد سطح بالاتر مایکروسرویس مثل نسل سوم، برای شروع چنین سیستمی مناسب نبود. از طرفی دیگر، معماری حال حاضر ما، جدای از اینکه برای شرایط فعلی ما مناسب و پاسخ‌گوی نیاز‌های فعلی ما است، در آینده می‌تواند با دشواری‌های کمتری، نسبت به monolithic، به نشل‌های جدیدتر تغییر یابد.استفاده از معماری Microservices: تقسیم بندی منطقی سرویس‌ها برای افزایش قابلیت نگهداری و مقیاس‌پذیری. از معماری modular monolithicبه معماری microserviceکوچ کردیم.مؤلفه Single Page Application: برای بهبود تجربه کاربری با بارگذاری سریع‌تر و کمتر.استفاده از Redis: برای Caching برای کاهش بار بر سرورهای پایگاه داده و بهبود زمان پاسخگویی.استفاده از API Gateway: مدیریت و ایجاد نقطه مرکزی برای routing درخواست‌ها و مسائل مرتبط با امنیت.انتخاب استک فناوری: انتخاب زبان‌های برنامه نویسی مثلاً جاوا اسپرینگ بوت برای API، Node.js برای سرویس اعلان.انتخاب تکنولوژی وب برای کاربران ادمین و مشتریان برای برنامه وب (ReactJS)انتخاب Flutter برای کلاینت موبایل.استفاده از درگاه API: استفاده از درگاه API برای ارتباط کلاینت‌ها با بک‌اند و دیتابیس‌ها.انتخاب دیتابیس و مدل‌سازی داده: تصمیم‌گیری برای استفاده از PostgreSQL برای داده‌های رابطی و MongoDB برای ذخیره سازی اسناد، پیروی از ACIDیکپارچه‌سازی با سیستم پرداخت: تصمیم‌گیری برای ادغام درگاه‌های پرداخت شخص ثالث (ZarinPal’s APIs).سیستم‌های اعلان و ارتباط: انتخاب سرویس‌ اطلاع‌رسانی (Node.js) که بتواند چندین کانال ارتباطی (پیام کوتاه، ایمیل، push notification و تلفن گویا) را پشتیبانی کند.نظارت و ثبت وقایع: ادغام یک استک ثبت و نظارت مانند Elasticsearch برای ذخیره‌سازی وقایع، Logstash  برای پردازش وقایع و Kibana برای گرافیکی کردن عمل نظارت بر عملکرد سیستم.تدابیر امنیتی: تعیین استراتژی‌های احراز هویت و مجوز برای امن کردن دسترسی به APIها و استفاده از توکن JWT برای احرازهویت در کلاینت‌ها. ذخیره توکن در Cookie و ایجاد SSL برای امنیت بیشتر. استفاده از Access Token با ماندگاری ۵ دقیقه و Refresh Tokenبا ماندگاری ۱ روز برای اوج امنیت.بازیابی پس از فاجعه و پشتیبان‌گیری: برنامه‌ریزی برای پشتیبان‌گیری‌های منظم، استفاده از RAID10 برای از دست نرفتن Integrity.استراتژی استقرار: استفاده از Docker و Kubernetes برای مدیریت استقرار Container‌های مختلفمان (اصطلاح C4).توسعه برنامه کاربردی موبایل با flutter: انتخاب استفاده از flutter برای ساخت کلاینت موبایل و build گرفتن دو نسخه IOS و ANDROID.6. ریسک‌ها و بدهی‌های فنی (Risks and Technical Debts)ریسک‌ها:تغییرات مداوم در منابع آگهی: ممکن است از منابع خارجی که آگهی‌ها را تامین می‌کنند، داده‌های غیرقابل پیش‌بینی دریافت شود که می‌تواند روی دقت جستجو و فیلترها تاثیر بگذارد.پیچیدگی مدیریت میکروسرویس‌ها: با افزایش تعداد میکروسرویس‌ها، مدیریت و هماهنگی بین آن‌ها می‌تواند پیچیده شود.مسائل مربوط به امنیت داده‌ها: اطلاعات حساس کاربران و آگهی‌ها نیاز به حفاظت دقیق دارند و هر گونه نقص در امنیت می‌تواند به مشکلات جدی منجر شود.بدهی‌های فنی:نیاز به توسعه‌ی مداوم واسط‌های API: در صورتی که API‌ها با تغییرات مکرر در منابع داده به‌روز نشوند، ممکن است دچار کندی یا از کار افتادن شوند.بستگی به زیرساخت‌های خارجی: استفاده از سرویس‌های کلود و بسترهای مدیریت شده ممکن است سیستم را به این سرویس‌ها وابسته کند.مدیریت حالت‌های خطا و بازیابی: برخورد با حالت‌های خطا و اطمینان از بازیابی سریع سیستم در زمان بروز مشکلات می‌تواند به تدریج به بدهی فنی تبدیل شود.سخن پایانی:این پروژه که ما انتخابش کردیم، یک پروژه تقریبا عملی بود و معماری آن از صفر توسط خودمان طراحی و مستند شد و برخلاف پروژه‌های پیشنهادی دیگر (که بیشتر جنبه بررسی معماری یک سیستم یا نرم‌ افزار معروف را داشتند)، این پروژه بیشتر شبیه به کار‌های صنعتی معماری نرم‌افزار بوده و حاصل آن، یک سند معماری مطابق با آموخته‌های درس معماری نرم‌افزار بوده است. طراحی معماری این سیستم، با توجه به نیازمندی‌های کارکردی و محدودیت‌های سیستم تعریف شده، انجام شده است و بسیاری از ابزار‌ها، تاکتیک‌ها و الگو‌های معماری که در ابتدای طراحی در نظر داشتیم، مناسب نبودند و لذا، استفاده نشدند.</description>
                <category>آرمین مظفری</category>
                <author>آرمین مظفری</author>
                <pubDate>Fri, 02 Feb 2024 23:50:42 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه ۵ ویدیوی مرتبط با معماری نرم‌افزار</title>
                <link>https://virgool.io/@arminm4/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DB%B5-%D9%88%DB%8C%D8%AF%DB%8C%D9%88%DB%8C-%D9%85%D8%B1%D8%AA%D8%A8%D8%B7-%D8%A8%D8%A7-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D9%86%D8%B1%D9%85-%D8%A7%D9%81%D8%B2%D8%A7%D8%B1-w0vtsvj2spby</link>
                <description>عنوان ویدیو:Cracking the Case: How to Migrate from Monoliths to Microservicesسخنران:Stephanie Baum – مهندس نرم‌افزار در Lightstepلینک ویدیو:https://www.youtube.com/watch?v=KGYYTDVKqKwخلاصه:در یک اجلاس معماری برنامه کاربردی، جلسه‌ای با تمرکز بر گذار از سیستم‌های یک‌پارچه (مونولیت) به میکروسرویس‌ها ارائه شد که توسط استفانی بام، مهندس نرم‌افزار در لایت‌استپ، ارائه می‌شد. استفانی با پیشینه‌ای غنی در زمینه مهندسی فول‌استک و تجربه کمک به شرکت‌های بزرگ فورچون در مهاجرت به میکروسرویس‌ها، تجربیات ارزشمندی را به این موضوع اضافه می‌کند. جلسه با عنوان “شکافندگی پرونده: چگونه از مونولیت‌ها به میکروسرویس‌ها مهاجرت کنیم”، به چالش‌های فنی و تصمیم‌گیری مرتبط با این تحول اشاره داشت، از جمله انتخاب صحیح پشته فناوری و ارزیابی مزایا و معایب تقسیم یک مونولیت به معماری مبتنی بر خدمات.استفانی مفهوم اهداف سطح خدمات (SLO) و اهمیت تعریف آن‌ها از پیش را برای هدایت فرآیند مهاجرت بدون ایجاد اختلال در تجربه کاربران توضیح داد. او دیدگاه‌هایی در مورد مدیریت عملیات نظیر مدیریت پیکربندی، محفظه‌سازی، و ادغام و توزیع مستمر(CI/CD) ارائه داد تا اطمینان حاصل کند که این راه‌اندازی‌ها قابل تکرار و مقیاس‌پذیر می‌باشند. جلسه هم‌چنین شامل ملاحظات استراتژیک در مورد انتخاب زبان‌های برنامه‌نویسی و تصمیم‌گیری برای استفاده از معماری‌های بدون سرور در مقابل میکروسرویس‌های سنتی بود، بر اساس آشنایی تیم و پیچیدگی منطق کسب‌وکار.“اثر میکروسرویس” قسمت عمده‌ای از ارائه استفانی بود، جایی که او در مورد پیچیدگی‌های ناشی از افزایش تعداد خدمات و هماهنگی آن‌ها صحبت کرد. این افزایش، نقاط شکست جدیدی ایجاد کرده و پیگیری منطق معاملاتی در سراسر سیستم را پیچیده می‌کند. او پیشنهاد داد که ابزارهای مشاهده‌پذیری مانند آنچه توسط لایت‌استپ ارائه می‌شود که قابلیت ردیابی را ادغام می‌کنند، برای مدیریت این پیچیدگی ضروری است و اطمینان حاصل می‌کند که تیم‌ها می‌توانند مالکیت و مسئولیت واضحی برای خدمات خود حفظ کنند.در پایان، استفانی بر استفاده از ابزارهای نظارت بر کارایی برنامه(APM) برای کاهش پیچیدگی کد اضافی طی مهاجرت و شناسایی احتمالی گلوگاه‌ها در مونولیت و میکروسرویس جدید تأکید کرد. استفاده از APM به توسعه‌دهندگان اجازه می‌دهد تا کارایی کد و تعاملات با سرویس‌های خارجی را در زمان واقعی پایش کنند، زیرساختی برای یک مهاجرت روان فراهم می‌آورد. او بر اهمیت SLOها برای فراهم کردن شفافیت در مورد سلامت سرویس‌ها در طی و پس از مهاجرت تأکید کرد. استفانی جلسه را با تشویق حاضرین برای کشف منابع مانند ماسکوت تعاملی LightStep و وبلاگ برای تجربه عملی و یادگیری بیشتر در مورد مشاهده‌پذیری مدرن به پایان رساند.عنوان ویدیو:What Software Architecture Should Look Like • Dave Farley • GOTO 2022سخنران:Dave Farley – نویسنده کتاب “Continuous Delivery”لینک ویدیو:https://www.youtube.com/watch?v=Eg_dapdKCHUخلاصه:معماری نرم‌افزار، طبق تعریف ویکی‌پدیا، به عنوان ساختارهای کاربردی یک سیستم نرم‌افزاری توصیف شده است، اما این تعریف بسیاری پرسش‌ها را بی‌جواب می‌گذارد و نشان از پیچیدگی مفهوم معماری دارد که به سختی می‌توان به طور مستقیم تعریف کرد. دیو فارلی، مدافع رویکرد مهندسی به توسعه نرم‌افزار، این مفهوم را در کتاب خود به نام “مهندسی نرم‌افزار مدرن” توصیف می‌کند. طی دوران حرفه‌ای خود، که گاهی به عنوان توسعه‌دهنده نرم‌افزار و گاهی به عنوان معمار نرم‌افزار شناخته می‌شد، فارلی دریافته است که نقش شامل طراحی است - صرف نظر از عنوان یا مقیاس - که نشان می‌دهد جزئیات در هر سطحی در طراحی سیستم‌های اطلاعاتی حیاتی است.فارلی تعریف محبوب گریدی بوچ از معماری نرم‌افزار را، که تصمیمات مهم طراحی را که هزینه تغییر را مشخص می‌کند، نقد می‌کند. او بر این باور است که دیدگاه بوچ بیش از حد پیش‌بینی‌کننده برای رشته‌ای است که به انعطاف‌پذیری و نوآوری نیاز دارد و به همین دلیل به یک فرآیند تکاملی علاقه‌مند است. او از تمثیل “نقشه گردشگری” به عنوان یک راهنما برای تکامل طراحی سیستم‌ها از طریق اشتباهات تکراری و عمیق‌تر شدن درک استفاده می‌کند.بر اساس تعاریف رالف جانسون، فارلی پیشنهاد می‌کند که معماری برگه ویش‌لیست توسعه‌دهندگان است - تصمیمات حیاتی که آنها امیدوار بوده‌اند از ابتدا درست انجام شده باشد، و درک مشترک کارشناسان توسعه‌دهندگان از طراحی سیستم در هر نقطه زمانی. او تاکید می‌کند که معماری باید امکان تنظیم و تکامل را فراهم کند چون ناممکن است که همه چیزها از ابتدا درست باشد. برای فارلی، معماری موفقیت‌آمیز در مدیریت پیچیدگی‌ها و ایجاد فضایی برای یادگیری از خطاها نهفته است بلکه ترس از اشتباه را کاهش می‌دهد.در نهایت، فارلی معماری نرم‌افزار را به عنوان مجموعه‌ای از محدودیت‌ها می‌بیند که هدایت و محافظت از فرآیند توسعه را در بر دارد و با ایجاد پتانسیل برای تغییر تطبیق می‌دهد. او تشویق به مشارکت همه توسعه‌دهندگان در بحث‌های معماری را می‌کند، بازتاب طبیعت تکراری طراحی نرم‌افزار و به رسمیت شناختن اینکه حتی تغییرات کوچک می‌توانند تأثیر قابل توجهی بر سیستم داشته باشند. در نهایت، معماری خوب فقط حوزه انتزاعی یا نقشه اولیه نیست؛ بلکه یک گفتگوی مستمر است که از طریق تصمیمات روزانه توسعه‌دهندگان نرم‌افزار جریان دارد و اطمینان حاصل می‌کند که حتی با پیچیدگی و ناپایداری نرم‌افزار، پیشرفت ممکن است، اشتباهات قابل اصلاح است و معماری می‌تواند برای برآوردن نیازهای هر سیستم تکامل یابد.عنوان ویدیو:Software Architecture Principles From 5 Leading Expertsسخنران:Dave Farley – نویسنده کتاب “Continuous Delivery”لینک ویدیو:https://www.youtube.com/watch?v=SYtkbv8LNv0خلاصه:ویدیو به جنبه‌ای که اغلب در حوزه توسعه نرم‌افزار نادیده گرفته می‌شود، یعنی طراحی نرم‌افزار، می‌پردازد. سخنران، دیو فارلی، تأکید می‌کند که توسعه نرم‌افزار خیلی بیشتر از صرف ترجمه دستورالعمل‌های زبان انسانی به کد است. او توجه می‌دهد که طراحی نرم‌افزار بخش حیاتی این فرایند است، با این حال، کمبود گفتگوهای عمیق در مورد آن در جامعه حرفه‌ای به طور قابل توجهی مشاهده می‌شود. فارلی نشان می‌دهد که دوران حرفه‌ای او بیشتر بر روی طراحی سیستم‌های نرم‌افزاری متمرکز بوده است، و به جنبه‌های متنوعی مانند مدولاریتی، انسجام، و جدایی دغدغه‌ها اشاره می‌کند.فارلی نسبت به گرایش صنعت به بحث بر سر انواع پارادایم‌های برنامه‌نویسی و ابزارها، به جای تمرکز بر اصول اساسی طراحی نرم‌افزار، ابراز نگرانی می‌کند. او اشاره می‌کند که این کمبود توجه به طراحی ممکن است از دشواری در بیان و آموزش اصول مؤثر طراحی نرم‌افزار ناشی شود. او موازنه‌ای بین طراحی نرم‌افزار و نویسندگی ایجاد می‌کند و نشان می‌دهد که هر دو نیاز به ساختار صحیح و همچنین انتقال فکر منظم و معنی‌دار دارند.در تحلیل خود، فارلی بر اهمیت خوانایی و توانایی تغییر کد به عنوان دو اصل بنیادین طراحی خوب نرم‌افزار تأکید دارد. او ادعا می‌کند که این اصول باید در تمام سطوح طراحی سیستم، از خطوط کد فردی گرفته تا معماری سیستم‌های بزرگ، اعمال شوند. هدف، بر طبق فارلی، خلق نرم‌افزاری است که قابل فهم و ساده برای تغییر باشد، تضمین می‌کند که کیفیت فنی سیستم براساس قابلیت سازگاری با تغییر تعریف شود.به سمت پایان ویدیو، فارلی به جوانب عملی طراحی نرم‌افزار می‌پردازد. او درباره استفاده از مدل‌های وایت‌برد برای تصویرسازی و انتقال به تصویر کشیدن مؤثر معماری سیستم بحث می‌کند، که درک و تغییر سیستم توسط اعضای تیم را ساده‌تر می‌کند. او بر اهمیت داشتن درک مشترک از طراحی سیستم در درون یک تیم تأکید دارد که به باور او برای حفظ یک سیستم خوب طراحی شده که با گذشت زمان قابل ناوبری و آداپته است، حیاتی است.عنوان ویدیو:The Evolution of Reddit.com&#x27;s Architectureسخنران:Neil Williamsمحل برگزاری:QCon San Francisco 2017لینک ویدیو:https://www.youtube.com/watch?v=nUcO7n4hek4خلاصه:ارائه ویدیویی، دیدگاه جامعی از معماری ردیت و چالش‌های عملیاتی آن ارائه می‌دهد. در ابتدا، سخنران ردیت را به عنوان یک پلتفرم آنلاین بزرگ معرفی می‌کند و به پایگاه کاربری وسیع و حجم بالای ترافیک آن اشاره می‌نماید. سپس معماری اصلی ردیت توضیح داده شده، با تمرکز بر روی برنامه پایتون مونولیتیک اصلی آن (R2) و انتقال تدریجی به برنامه‌های کاربردی جدید مدرن با استفاده از Node.js. این برنامه‌های کاربردی به عنوان مشتریان API عمل می‌کنند و با دروازه API ردیت و سرویس‌های پشتیبانی ارتباط برقرار می‌کنند که بسیاری از آن‌ها برای بهبود مدولاریته از R2 مونولیتیک جدا شده‌اند.در ادامه سخنرانی، سخنران به پیچیدگی‌های معماری مونولیتیک ردیت می‌پردازد. او توضیح می‌دهد که چگونه زیرساخت‌های ردیت برای کنترل انواع درخواست‌ها و فعالیت‌های کاربران طراحی شده‌اند، به عنوان مثال رأی دادن یا پست کردن که به صورت ناهمزمان پردازش می‌شوند. این قسمت همچنین پوشش می‌دهد فناوری‌های پشتیبانی مانند Memcache، Postgres و Cassandra و نقش‌های آن‌ها در کنترل داده‌ها و ذخیره‌سازی در ردیت.بخش قابل توجهی از ارائه به بحث در مورد چالش‌ها و راه‌حل‌های مرتبط با سیستم‌های لیست‌بندی و صف ردیت اختصاص داده شده است. سخنران پیچیدگی‌های مدیریت محتوای پویا مانند رأی‌ها و نظرات را توضیح می‌دهد، به ویژه در شرایط ترافیک بالا. مسائلی مانند تجمع در صف و تداخل قفل بحث شده‌اند و استراتژی‌هایی مانند تقسیم‌بندی صف و استفاده از کش و داده‌های دنرمالایز شده برای بهبود کارایی مد‌نظر قرار گرفته‌اند.در نهایت، سخنرانی با بینش‌هایی پیرامون توانمندسازی سرورها و رویه‌های خودکارسازی مقیاس‌پذیری ردیت به پایان می‌رسد و بر اهمیت نظارت‌پذیری، انتقال‌پذیری و مدیریت هوشمندانه سرویس‌های دارای حالت در مقابل بی‌حالت تاکید می‌کند. سخنران از درس‌های آموخته شده از چالش‌های مختلف، از جمله مشکلات مربوط به خودکارسازی مقیاس‌بندی و تکثیر پایگاه داده، بحث می‌کند و بر نیاز به چندین لایه حفاظتی و سادگی در طراحی سیستم برای اطمینان از قابلیت اطمینان و نگه‌داری بهتر، تأکید ویژه‌ای می‌کند. ارائه با اشاره به توسعه و رشد مداوم ردیت به پایان می‌رسد.عنوان ویدیو:Software Architecture: A Mature Discipline?سخنران:Philippe Kruchten – استاد مهندسی نرم‌افزار در دانشگاه British Columbia کانادالینک ویدیو:https://www.youtube.com/watch?v=70kyGrjs8rUخلاصه:ویدیو با عنوان “معماری مرورگر وب SDI در یک رشته بالغ”، ویژگی‌های برنده جایزه معماری نرم‌افزار لیندا ال. نورثاپ، فیلیپ کروشتون را نمایش می‌دهد. میزبان، جیمز ایورس، رهبر گروه معماری نرم‌افزار در مؤسسه مهندسی نرم‌افزار دانشگاه کارنگی ملون است. از دهه ۱۹۸۰مؤسسه SEI به طور قابل توجهی در توسعه و بلوغ حوزه معماری نرم‌افزار کمک کرده است و به سازمان‌ها با راه‌حل‌های معماری کمک نموده و به بهبود کلی دانش در این زمینه انجام شده است. روش‌های SEI به طور گسترده شناخته شده و بر بسیاری از حرفه‌ای‌ها و دانشجویان معماری نرم‌افزار در سراسر دنیا تأثیر گذاشته‌اند.فیلیپ کروشتون، استاد افتخاری مهندسی نرم‌افزار در دانشگاه بریتیش کلمبیا، دارای یک حرفه درخشان در هر دو زمینه علمی و صنعتی است. کار او در معماری نرم‌افزار بر طراحی سیستم‌های بزرگ در حوزه‌های مختلف از جمله مخابرات، دفاع، هوا‌فضا و حمل و نقل تأثیر گذاشته است. دخالت او در توسعه نرم‌افزار به وضوح در روند تحلیل متحد رشنال(RUP) که از بدو تأسیس آن رهبری کرده است، خلاصه شده است. روش “چهار به علاوه یک” دیدگاهRUP یک کمک بنیادین به حوزه معماری نرم‌افزار است.در ارائه خود، کروشتون بر روی تکامل معماری نرم‌افزار تأمل می‌کند. او به معنا‌شناسی اصطلاح می‌پردازد و توجه می‌دهد که چگونه تعاریف آن متفاوت بوده است، غالباً بر ساختار، اجزا و اتصال‌دهنده‌ها تأکید می‌کند. کروشتون تأکید می‌کند که نقش معماری نرم‌افزار با گذشت زمان از یک تعریف باریک به عنوان فهم مشترکی از مسیر یک پروژه و حفظ یکپارچگی مفهومی تغییر کرده است. او همچنین در مورد فرآیند معماری بحث می‌کند که از روش‌های بیشتر سنتی به رویکردهای چابک و تکراری تکامل یافته است.در نهایت، کروشتون به آینده معماری نرم‌افزار می‌پردازد و بر اهمیت تحقیق در بهبود این زمینه تأکید می‌کند. او بر نیاز به اکتشاف جنبه‌های اقتصادی، نقش بدهی فنی و جنبه‌های اجتماعی معماری نرم‌افزار اشاره می‌کند. بینش‌های او نشان می‌دهد که در حالی که معماری نرم‌افزار بالغ شده است، هنوز بسیاری برای کشف و درک وجود دارد، به‌خصوص در زمینه شیوه‌های توسعه نرم‌افزار مدرن.این مطلب، بخشی از تمرینهای درس معماری نرم‌افزار در دانشگاه شهیدبهشتی است</description>
                <category>آرمین مظفری</category>
                <author>آرمین مظفری</author>
                <pubDate>Fri, 29 Dec 2023 13:39:36 +0330</pubDate>
            </item>
                    <item>
                <title>چندین موضوع پراکنده مهندسی نرم‌افزار</title>
                <link>https://virgool.io/@arminm4/%DA%86%D9%86%D8%AF%DB%8C%D9%86-%D9%85%D9%88%D8%B6%D9%88%D8%B9-%D9%BE%D8%B1%D8%A7%DA%A9%D9%86%D8%AF%D9%87-%D9%85%D9%87%D9%86%D8%AF%D8%B3%DB%8C-%D9%86%D8%B1%D9%85-%D8%A7%D9%81%D8%B2%D8%A7%D8%B1-qmu94nnzoug3</link>
                <description>بعضی قسمت‌های متن به دلیل وجود کلمات فارسی و انگلیسی در یک سطر، به صورت نامرتب نوشته شده است و کاری برای درست شدن آن نمی‌توانم انجام دهم.یک) Modular Monolithic: ترکیبی از اصول طراحی modular و monolithic و هدف از آن، استفاده از سادگی معماری monolithic و انعطاف‌پذیری (flexibility) و مقیاس‌پذیری (scalability) معماری modular است. این نوع معماری بین معماری monolithic و microservice قرار می‌گیرد و به نوعی، حد وسط آن‌ها است. در این معماری، تمام ارتباطات درون یک process انجام می‌شوند و تنها یک فایل برای deploy‌ وجود دارد؛ اما درون این فایل، جداسازی منطقی (نه فیزیکی) براساس ویژگی (feature) انجام شده است و برنامه به چندین ماژول مستقل و loosely coupled تقسیم شده است که از طریق رابط‌هایی (interface)، با یکدیگر ارتباط دارند. این ماژول‌ها در این معماری، وابستگی بیشتری به یکدیگر نسبت به معماری microservice دارند اما نسبت به معماری monolithic، بسیار مستقل‌تر هستند. از مشکلات معماری monolithic، وابستگی زیاد بخش‌های مختلف آن به یکدیگر (tightly coupled) و سختی توسعه همزمان و مستقل بخش‌های نرم‌افزار و بهره‌وری از متودولوژی Agile است که این مشکلات در معماری Modular Monolithic، به دلیل وابستگی کم بین ماژول‌ها (loosely coupled)، از بین رفته اند. یکی دیگر از مشکلات بزرگ معماری monolithic، نیاز به compile مجدد کل برنامه در صورت تغییر یک تابع کوچک است که این مشکل نیز در modular monolithic با طراحی modular برطرف شده است.دو) AWS: پلتفرم رایانش ابری شرکت آمازون است که خدمات ابری مانند توان پردازشی، فضای ذخیره‌سازی، یادگیری ماشین و ... را به صورت Pay-as-you-go می‌دهد که همین pay-as-you-go، قابلیت autoScale کردن اپلیکیشن را فراهم می‌کند؛ این قابلیت به این صورت است که در زمان مصرف و درخواست‌های بالا، توان پردازشی بیشتری به اپلیکیشن داده می‌شود و در زمان مصرف و درخواست‌های کم، توان پردازشی کاهش یافته تا هزینه‌ها زیاد نشوند. (البته این خدمات به ایرانی‌ها داده نمی‌شود). Amazon EC2 (Elastic Compute Cloud) و AWS Lambda از جمله خدمات پردازشی این پلتفرم هستند که Amazon EC2، اجازه‌ی اجرای سرور‌های مجازی با ظرفیت و قدرت‌های مختلف را به کاربران می‌دهد و سرور‌های آن دارای availability بسیار بالا هستند و AWS Lambda هم پردازش Serverless را ارائه می‌دهد (توضیحات این مفهوم در ادامه متن آمده است). از جمله خدمات ذخیره‌سازی در این پلتفرم می‌توان Amazon S3 (Simple Storage Service) و Amazon EBS (Elastic Block Store) را معرفی کرد که مورد اول بسیار معروف‌تر است و پایداری 99.999999999 دارد و Amazon RDS (Relational Database Service) و Amazon DynamoDB از جمله خدمات دیتابیس این پلتفرم هستند که اولی برای دیتابیس‌های رابطه‌ای و دومی برای دیتابیس‌های NoSQL بکار می‌رود.سه) API-First Approach: این رویکرد به این صورت است که به طراحی، مستندسازی و پیاده‌سازی API‌ها اولویت بالاتری داده می‌شود و این اعمال در ابتدای فرایند توسعه نرم‌افزار، انجام می‌شوند و سپس، باقی کد با توجه به این API‌‌ها نوشته می‌شوند. با این رویکرد، هزینه توسعه برنامه‌ها کاهش می‌یابد (به دلیل استفاده مجدد از API‌ها و عدم نیاز به طراحی مجدد برای اپلیکیشن‌های جدید) و دست توسعه‌دهندگان برای انتخاب روش پیاده‌سازی اپلیکیشن‌هایی که از این API‌ها استفاده کنند، باز است و حتی می‌توانند انتخاب framework و زبان را به تاخیر بیاندازند و در نهایت، برای تمام دستگاه‌ها، پلتفرم‌ها و سیستم‌عامل‌ها برنامه‌ای با تجربه کاربری (UX) مناسب بسازند. این روش همچنین به دلیل داشتن قابلیت تولید اتوماتیک API و آسان بودن اضافه کردن سرویس‌ها و تکنولوژی‌های جدید به برنامه، Time to Market‌ سریع‌تری دارد (سریع‌تر می‌توان آن را عملیاتی و منتشر کرد). در این روش، می‌توان همزمان توسعه بخش frontend و backend را انجام داد؛ دلیل این امر، استفاده از mock api است که در اصل مقادیری است که از API واقعی قرار است گرفته شوند.چهار) NoSQL Databases: دیتابیس‌های NoSQL (Not Only SQL) برای داده‌های بدون ساختار (ساختار آن‌ها را نمی‌شود مانند دیتابیس‌های SQL از قبل مشخص کرد) استفاده می‌شوند و از دیتابیس‌های SQL و رابطه‌ای، بسیار مقیاس‌پذیرتر و منعطف‌تر هستند و استفاده از آن‌ها بسیار آسان‌تر است. این نوع دیتابیس‌ها می‌توانند به صورت document (ذخیره به صورت JSON)، جفت‌های Key-Value‌ای، wide-column (استفاده از ستون‌‌های dynamic و تغییرپذیر) و گراف (بیشتر برای ذخیره اطلاعات درمورد افراد یا مکان‌ها و ارتباط بین آن‌‌ها) بیایند. بعضی از زمان‌هایی که این نوع دیتابیس باید استفاده شود عبارتند از: در توسعه‌های سریع و Agile، زمانی که دیتا با ساختار نامشخص و قابل تغییر داریم، زمانی که حجم زیادی داده داریم و ...؛ مثلاً برای نگهداری اطلاعات یک محصول در دیجی‌کالا، بهتر است از این نوع دیتابیس‌ها استفاده شود؛ چون اطلاعات محصول‌ها، ساختار مشخصی ندارند (که بخواهیم از دیتابیس‌های SQL و جداول رابطه‌ای استفاده کنیم) و ممکن است نیاز به تغییر داشته باشند.پنج) Serverless Architecture: معمولاً از نوع Faas است (Function as a service) و به این صورت است که مدیریت و نگهداری سرور‌ها توسط سرویس‌دهنده ابری (مثلاً AWS) انجام می‌شود و توسعه‌دهندگان دیگر درگیر نگهداری و مدیریت سرور‌ها به طور مستقیم نمی‌شوند و روی کد خود تمرکز می‌کنند و برای مدیریت و ارتباط با سرور‌ها، تابع‌های کوچکی می‌نویسند که هرکدام از این تابع‌ها، با یک رویداد (Event) یا درخواست (Request)، فعال شده و اجرا می‌شوند و عمل مورد نیاز را انجام می‌دهند. این تابع‌ها stateless هستند معمولاً زمان اجرای کوتاهی دارند و تنها برای انجام یک عمل خاص، مثلاً آپلود فایل، اجرا می‌شوند و سپس پایان می‌یابند. یکی از مشکلات این روش cold start‌ است که به تاخیر در راه‌اندازی اولیه و اجرای تابع‌ها در صورتی که مدتی صدا زده نشوند، اشاره دارد. هزینه‌ها در این روش معمولاً به صورت pay-as-you-go است و کاربران با توجه به منابعی که برای اجرای تابع‌ها مصرف کرده‌اند، پول می‌دهند. همچنین این پلتفرم‌ها معمولاً دارای Automatic Scaling‌ هستند و با توجه ترافیک ورودی، منابع و توان پردازشی را مشخص می‌کنند. از نمونه پلتفرم‌های معروف Serverless می‌توان به AWS Lambda اشاره کرد.شش) Domain Driven Design: این روش تاکید بر این موضوع دارد که در ابتدای طراحی و ساخت سیستم‌های نرم‌افزاری، روی درک و سپس مدلسازی دامنه کسب‌وکار (Business Domain) تمرکز کنیم و با استفاده از الگو‌هایی که این روش ارائه می‌دهد، نرم‌افزاری بسازیم که تمام نیازمندی‌های business را برآورده کند. این روش برای کسب‌و‌کار‌هایی که قوانین پیچیده‌ای دارند، کاربرد دارد. برای انجام این روش، حتماً به متخصصان آن کسب‌وکار نیاز داریم و بدون آن‌ها، انجام این روش امکان‌پذیر نیست. یکی از مواردی که این روش به انجام آن تاکید دارد، استفاده از زبانی مشترک بین افراد فنی (توسعه‌دهندگان و مهندسان) و افراد غیرفنی (افراد آن کسب‌وکار) است که باعث می‌شود ارتباط بهتری بین این افراد برقرار شود (با استفاده از در آوردن لغات و اصطلاحات تخصصی کسب‌وکار و قرار دادن آن‌ها در سندی به نام Glossary). از این زبان مشترک در طراحی و پیاده‌سازی و حتی مستند‌سازی بخش‌های مختلف نرم‌افزار استفاده می‌شود.هفت) Hexagonal Architecture: به آن Ports and Adapters هم می‌گویند. این معماری می‌گوید که بهتر است سیستم طوری طراحی شود که منطق کسب‌وکار (Business Logic) از باقی مسائل مانند پایگاه داده، رابط کاربری و ...کاملاً جدا باشد. در این روش منطق کسب‌وکار همان شش ضلعی است و از وجود بقیه component‌ها بی‌خبر است (یعنی اصلاً به آن‌ها وابسته نیست) و این component‌ها در portهای اطرافش با استفاده از Adapter‌ها به آن وصل می‌شوند و مقدار می‌فرستند یا دریافت می‌کنند. Port‌ها در اصل رابط‌هایی (interface) هستند که راه ارتباط با اپلیکیشن (منطق کسب‌وکار) را باز می‌کنند (شکل کلی ارتباط یعنی تابع‌های abstract درون آن است). Adapter‌ها پیاده‌سازی این Interface‌ها هستند که باعث می‌شوند ارتباط بین منطق کسب‌وکار (که اصل اپلیکیشن است) و بخش‌های دیگر برقرار شود. در این معماری دو بخش driving side و driven side داریم که اولی ارتباط با اپلیکیشن را شروع می‌کند (مثلاً ورودی کاربر که به اپلیکیشن داده می‌شود) و دومی رفتاری است که دستورش از طرف اپلیکیشن می‌آید؛ مانند گرفتن اطلاعات کاربر از پایگاه داده. یکی از دلایل نمایش شکل به صورت شش‌ضلعی، مشخص شدن تفاوت این دو بخش است.هشت) Event Sourcing: به این صورت است که به جای ذخیره‌سازی وضعیت (State) سیستم، دنباله‌ای از رویداد‌ها (Event)‌هایی رخ داده‌اند را ذخیره می‌کنیم و وضعیت سیستم را از روی اجرای این رویداد‌ها در می‌آوریم. تمام این رویداد‌ها درون Event log ذخیره می‌شوند و به قدری اطلاعات دارند که بتوان از روی آن‌ها، وضعیت برنامه را بدست آورد. نکته مهم درمورد این رویداد‌ها این است که این رویداد‌ها، غیرقابل تغییر هستند (immutable) اما می‌توان با استفاده از رویداد‌های جدید‌تر، اثر آن‌ها را خنثی کرد. یکی از مزایای event sourcing این است که چون تمام رویداد‌ها و تغییرات روی ‌state‌ها ذخیره می‌شوند و state در تمام لحظات را می‌توان با استفاده از اجرای به ترتیب رویداد‌ها بدست آورد (اصطلاحاً به این عمل Temporal Query می‌گویند)، عمل دیباگ کردن بسیار آسان می‌شود. یکی از مثال‌های معروف برای برنامه‌هایی که از این قابلیت استفاده می‌کنند، برنامه‌های version control مانند Git هستند که دائماً از Temporal Query‌ها استفاده می‌کنند تا وضعیت برنامه را در زمان‌های مختلف بدست آورند.نه) Low code platforms: این‌ها پلتفرم‌هایی هستند که اجازه تولید اپلیکیشن‌ها را با حداقل میزان کد و برنامه‌نویسی می‌دهند و عمل توسعه را سریعتر و آسان‌تر می‌کنند. این پلتفرم‌ها معمولاً یک محیط گرافیکی دارند که قابلیت drag and drop دارد و می‌توان با استفاده از این قابلیت، بخش‌هایی از برنامه را طراحی کرد و ساخت. سطح abstraction در این پلتفرم‌ها بسیار بالا است و توسعه‌دهندگان عملاً با بخش‌های فنی کمتری روبرو هستند و اکثر کار‌ها توسط این پلتفرم انجام می‌شوند که این موضوع باعث می‌شود افراد غیرفنی هم بتوانند از طریق این پلتفرم‌ها برنامه بسازند. از مزایای این پلتفرم‌ها می‌توان به توسعه سریع‌تر برنامه‌ها اشاره کرد که در مواقعی که می‌خواهیم سریع MVP برنامه را بسازیم، بسیار مفید و کاربردی هستند.ده) Business Process Management Systems: ‌ BPM یا همان Business Process Management یعنی تغییر و بهبود فرایند‌های کسب‌و‌کار (Business Process) به شکل سیستماتیک و با یک سری گام‌های مشخص و BPMS‌ها، نرم‌افزار‌هایی هستند که اجازه این کار را می‌دهند؛ یعنی این نرم‌افزار‌ها امکان طراحی و مدلسازی فرایند‌های کسب‌وکار (مثلاً با کشیدن BPMN)، اجرا و پیاده‌سازی مدل طراحی شده، نظارت بر و گزارش‌گیری از مدل‌های اجرا شده و بهینه‌سازی با توجه به گزارش‌ها را می‌دهند و از مزایای آن‌ها می‌توان به سریع‌تر شدن Time to Market (چون مدلسازی‌ها و استخراج فرایند‌ها به صورت خودکار و توسط ابزار انجام می‌شوند) اشاره کرد. همچنین با استفاده از قدرت آنالیز و نظارتی که این نرم‌افزار‌ها به ما می‌دهند، می‌توان بسیار آسان‌تر گلوگاه‌ها (Bottleneck) و مشکلات در فرایند‌ها را پیدا کرد و فرایند‌های دیگری برای رفع آن مشکلات طراحی و پیاده‌سازی کرد.یازده)  Message Queue (such as Kafka and RabbitMQ): به نحوی می‌توان گفت همان مسئله تولید‌کننده – مصرف‌کننده را پیاده‌سازی می‌کنند که تولید‌کننده همان اپلیکیشن‌ Client است و پیامی را تولید می‌کند و در صف قرار می‌دهد و مصرف‌کننده که به بافر (همان صف یا Queue) وصل می‌شود، آن پیام به صورت آسنکرون دریافت و مصرف می‌کند. این عمل باعث می‌شود که بتوان در اپلیکیشن Client، بعد از تولید پیام، جلو رفت و منتظر پاسخ نماند و بعداً با تکنیک‌هایی مانند polling یا همان سرکشی (در زمان‌های مشخص چک کنیم آیا انجام شده است یا نه) و ...، پیشرفت کار را بررسی کنیم. یک روش دیگر نیز این است که در سمت Client، کار را تمام شده نشان دهیم و پشت سر باقی مراحل کار را از Queue بخوانیم و انجام دهیم؛ مثلاً در پست گذاشتن در توییتر، پست به سرعت در صفحه کاربر ارسال می‌شود و پیام موفقیت به او نشان داده می‌شود اما نمایش پست در feed افراد و دوستان او به صورت آسنکرون و با تاخیر انجام می‌شود. برای پیاده‌سازی این صف‌ها از message broker‌هایی (که مسئولیت ارسال، دریافت و ذخیره‌سازی پیام‌ها را دارند) مانند Kafka و RabbitMQ استفاده می‌شود که هرکدام معماری خاص خود را دارند و به نحوی کار را پیش می‌برند؛ مثلاً RabbitMQ دارای Exchange‌هایی است که producer (برنامه Client)، پیام تولیدی خود را به آن‌ها می‌فرستد و آن‌ها پیام‌ها را به صف‌های موردنظر مسیریابی می‌کنند و در نهایت Consumer پیام‌ها را از صف می‌گیرد و مصرف می‌کند. این نرم‌افزار‌‌ها در معماری‌هایی که از Event Sourcing استفاده می‌کنند، بسیار استفاده می‌شوند و می‌توان از آن‌ها برای پیاده‌سازی Load Balancing (تقسیم کار و درخواست‌ها بین چندین مصرف‌کننده و سرور) استفاده کرد. همچنین از MQ در معماری‌های microservice و serverless هم به وفور استفاده می‌شود.دوازده)  Container orchestration (such as Kubernetes): برای خودکار کردن اعمال استقرار (Deployment)، مقیاس‌بندی (Scaling) و مدیریت اپلیکیشن‌هایی که توسط ابزار‌هایی مانند Docker، به اصطلاح Containerized شدند؛ یعنی خود اپلیکیشن و تمام وابستگی‌ها و نیازمندی‌هایش کنار هم قرار گرفته‌اند تا اجرای آن اپلیکیشن در تمام محیط‌ها آسان باشد. وقتی تعداد این container‌ها زیاد می‌شود، به ابزاری برای مدیریت آن‌ها نیاز داریم. مثلاً upgrade کردن تعداد زیادی container با استفاده از این ابزار به راحتی نوشتن در یک فایل است و باقی کار‌‌ها به صورت خودکار و با توجه به تنظیمات قرار داده شده در فایل انجام می‌شوند و ابزار سعی می‌کند به وضعیتی که از آن خواستیم برسد. از دیگر کار‌های این ابزار می‌توان زمانبندی اجرا و توقف container‌ها، تخصیص منابع خودکار، نظارت بر container‌ها و استقرار آن‌ها و upgrade کردن container‌ها اشاره کرد.سیزده)  Log Management Tools (such as ELK): این ابزار‌ها برای مدیریت log‌های تولیدی توسط سیستم بکار می‌روند و اطلاعات مفیدی در مورد کارایی سیستم و مشکلات و گلوگاه‌های آن به ما می‌دهند. با استفاده از این ابزار‌ها، تمام log‌های تولیدی توسط سیستم (در بخش‌‌های مختلف مانند شبکه و ...) در یک مکان جمع‌آوری شده و فرمت آن‌ها یکسان می‌شود (استانداردسازی) و سپس تحلیل می‌شوند تا اطلاعاتی در مورد سیستم بدست آید. بررسی Log‌ها به صورت دستی بسیار کند و پرخطا است و به هیچ وجه Scalable نیست (یعنی با زیاد شدن log‌ها و بزرگ‌تر شدن برنامه، به مشکل می‌خوریم). یکی از مزایای این ابزار‌ها، کاهش MTTR‌ (Mean time to recovery) است و دلیل آن هم این است که با این ابزار، سریع‌تر log‌ها بررسی می‌شوند و مشکلات کشف شده و حل می‌شوند. یکی دیگر از مزایای این ابزار‌ها، کمک به واحد فروش برای تحلیل رفتار مشتری (اگر رفتار مشتری را از قبل log‌ کرده باشیم) است. ELK یا همان ElasticSearch, Logstash, Kibana از معروف‌ترین ابزار‌ها برای مدیریت log‌ها هستند که در آن ElasticSearch‌ مسئولیت ذخیره‌سازی و ایندکس کردن log‌ها را برعهده دارد و همچنین قابلیت جستجو روی log‌ها را به ما می‌دهد؛ Logstash‌ مسئولیت پردازش اطلاعات درون log‌ها و ارسال اطلاعات پردازش شده به ElasticSearch را دارد و Kibana‌ محیطی گرافیکی برای نمایش اطلاعات استخراج شده از log‌ها و جستجو به صورت گرافیکی و نمایش نمودار‌‌ها و ... است که به ElasticSearch وصل می‌شود.چهارده)  Monitoring Tools (such as Prometheus): این ابزار روی وضعیت سیستم نظارت می‌کنند و اعدادی دریافت می‌کنند و پس می‌دهند که نشان‌دهنده وضعیت بخش‌های مختلف سیستم هستند و با توجه به آن‌ها می‌توان وضعیت سخت‌افزار و نرم‌افزار‌های سیستم را بررسی کرد و روی آن‌ها نظارت داشت تا مطمئن شویم که تمام بخش‌ها به خوبی کار می‌کنند و دچار مشکل نشده‌اند. همچنین می‌توان با استفاده از این ابزار کارایی سیستم را بدست آورد، مصرف منابع را بررسی و با توجه به آن برای تخصیص منابع جدید برنامه‌ریزی کرد، گلوگاه‌ها و مشکلات امنیتی را شناسایی کرد و در مورد Availability یا در دسترس بودن سیستم هم نظر داد. این ابزار در صورتی که شرایط خاص از پیش تعریف شده‌ای رخ دهند یا عددی از آستانه‌ای که از پیش تعریف شده است بگذرد، هشدار می‌دهند. از مواردی که عدد به آن‌ها نسبت داده می‌شود و نظارت می‌شوند، می‌توان میانگین زمان پاسخ (Average response time)، مصرف CPU، نرخ رخداد خطا و نرخ درخواست‌های سرور و ... را نام برد و با استفاده از این اطلاعات، می‌توان درمورد Availability یا در دسترس بودن، کارایی، امنیت و ... سیستم نظر داد.پانزده)  Static Code Analysis (such as SonarQube):  لینتر‌ها زیرمجموعه آن‌ها هستند (با هم یکی نیستند؛ البته گاهی به اشتباه به جای یکدیگر بکار می‌روند) و کارشان تحلیل خودکار کد بدون نیاز به اجرای آن است. این ابزار‌‌ها کد را تحلیل و بررسی می‌کنند و دنبال مشکلات، حفره‌های امنیتی (مثلاً SQL Injection اگر توسعه‌دهنده مقدار input‌ها را مستقیم در Query می‌گذارد)، استفاده از تابع‌های مشکل دار و قدیمی و منسوخ‌شده، کثیفی و تکرار کد و مشکلات style و ظاهری کد می‌گردند. درصورتی که این مشکلات برطرف نشوند، می‌توانند در نگهداری کد (اضافه کردن ویژگی‌های جدید) چالش ایجاد کنند و منجر به باگ شوند. این عمل (تحلیل خودکار کد) در حین کد زدن و در مرحله توسعه نرم‌افزار انجام می‌شود. این ابزار‌ها هم ممکن است خیلی مواقع اشتباه کنند و false positive‌ (چیزی که در اصل درست است اما غلط فرض شده است) و false negative (پیدا نکردن مشکلات) داشته باشند؛ به همین دلیل به code review و بررسی انسانی (توسعه‌دهنده) نیاز است. از جمله linter‌های معروف می‌توان به ESLint برای زبان جاوا اسکریپت اشاره کرد.منابع:https://www.techtarget.com/searchapparchitecture/tip/Understanding-the-modular-monolith-and-its-ideal-use-caseshttps://www.fullstacklabs.co/blog/modular-monolithic-vs-microserviceshttps://virgool.io/@egerd/%D8%A8%D8%A7-%D8%AE%D8%AF%D9%85%D8%A7%D8%AA-%D8%AA%D8%AD%D8%AA-%D9%88%D8%A8-%D8%A2%D9%85%D8%A7%D8%B2%D9%88%D9%86-aws-%D8%A2%D8%B4%D9%86%D8%A7-%D8%B4%D9%88%DB%8C%D8%AF-nyfkgoeyymbyhttps://www.techtarget.com/searchaws/definition/Amazon-Web-Serviceshttps://www.karlancer.com/blog/aws/https://www.postman.com/api-first/#:~:text=The%20API%2Dfirst%20approach%20prioritizes,of%20treating%20them%20as%20afterthoughts.https://www.nginx.com/resources/glossary/api-first/https://swagger.io/resources/articles/adopting-an-api-first-approach/https://www.mongodb.com/nosql-explainedhttps://en.wikipedia.org/wiki/NoSQLhttps://en.wikipedia.org/wiki/Serverless_computinghttps://www.cloudflare.com/learning/serverless/what-is-serverless/https://www.datadoghq.com/knowledge-center/serverless-architecture/https://redis.com/glossary/domain-driven-design-ddd/https://en.wikipedia.org/wiki/Domain-driven_designhttps://medium.com/ssense-tech/hexagonal-architecture-there-are-always-two-sides-to-every-story-bc0780ed7d9chttps://www.eventstore.com/event-sourcing#:~:text=What%20is%20Event%20Sourcing%3F,the%20same%20piece%20of%20information.https://martinfowler.com/eaaDev/EventSourcing.htmlhttps://www.ibm.com/topics/low-codehttps://www.techtarget.com/searchcio/definition/Business-process-management-suite-BPMShttps://scribehow.com/library/business-process-management-exampleshttps://medium.com/must-know-computer-science/system-design-message-queues-245612428a22https://phoenixnap.com/blog/what-is-container-orchestrationhttps://sematext.com/guides/log-management/https://www.splunk.com/en_us/data-insider/what-is-it-monitoring.htmlhttps://www.techtarget.com/searchitoperations/definition/IT-monitoringhttps://www.perforce.com/blog/sca/what-static-analysishttps://www.techtarget.com/whatis/definition/static-analysis-static-code-analysis</description>
                <category>آرمین مظفری</category>
                <author>آرمین مظفری</author>
                <pubDate>Fri, 24 Nov 2023 21:58:03 +0330</pubDate>
            </item>
                    <item>
                <title>خوانش فصلهای 15 تا 29 کتاب معماری تمیز</title>
                <link>https://virgool.io/@arminm4/%D8%AE%D9%88%D8%A7%D9%86%D8%B4-%D9%81%D8%B5%D9%84%D9%87%D8%A7%DB%8C-15-%D8%AA%D8%A7-29-%DA%A9%D8%AA%D8%A7%D8%A8-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D8%AA%D9%85%DB%8C%D8%B2-mpmge5yixo33</link>
                <description>فصل پانزدهم در مورد اینکه معماری چیست و معمار نرم‌افزار چه کسی است و هدف از طراحی یک معماری خوب چیست، صحبت می‌کند. دلیل طراحی معماری نرم‌افزار، آسان کردن موارد توسعه (development)، استقرار (deployment)، عملکرد (operation) و نگهداری (maintenance) نرم‌افزار است. یک معماری خوب از طریق تقسیم کردن برنامه به چندین component مجزا، عمل توسعه توسط چند تیم را آسان‌تر می‌کند؛ از طریق کشیدن نمودار‌ها، بررسی ارتباطات بین component‌ها و ساخت استراتژی استقرار، مشکلات عمل استقرار را قبل از وقوع برطرف می‌کند؛ از طریق ایزوله کردن component‌ها با استفاده از اینترفیس‌ها و تجرید، نگهداری و اضافه کردن ویژگی‌های جدید را آسان‌تر می‌کند؛ تنها موردی که نیاز کمتری به معماری خوب دارد و بدون آن هم می‌توانیم به آن برسیم، عملکرد سیستم است. تقریباً تمام مشکلات عملکردی را می‌توانیم با اضافه کردن سخت‌افزار بیشتر، برطرف کنیم. معماری خوب در این مورد می‌تواند با نمایش بهتر عملکرد سیستم به توسعه‌دهندگان، به ما کمک کند. نکته دیگر این فصل این است که بهتر است تصمیم‌گیری در مورد جزئیات و قسمت‌های concrete برنامه را تا جایی که می‌توانیم عقب بندازیم و به جای آن، روی business rule‌ها و policyهای سطح بالا تمرکز کنیم؛ این امر، انعطاف‌پذیری در توسعه را بسیار بالا می‌برد.فصل شانزدهم مطالب گفته شده در فصل قبل را تکرار می‌کند و به آن‌ها اضافه می‌کند. این فصل می‌گوید که اولین چیزی که یک معماری خوب باید از آن پشتیبانی کند، use case است. از آنجایی که معماری تاثیر کمتری روی رفتار و عملکرد سیستم دارد، کاری که یک معماری خوب باید در مورد use case‌ها انجام دهد این است که هدف و قصد از توسعه آن نرم‌افزار را مشخص کند تا توسعه‌دهندگان بتوانند بهتر سیستم را درک کرده و آن را توسعه دهند. یک معماری خوب باید از نیازمندی‌های عملکردی و مقیاس‌پذیری سیستم هم پشتیبانی کند؛ یعنی اگر response time پایین یا throughput بالایی نیاز است، معماری به طریقی باید آن را فراهم کند (مثلاً از طریق پخش بخش‌های پردازشی روی سرور‌های مختلف و اجرای همزمان آن‌ها). معماری خوب همچنین باید از طریق بخش‌بندی سیستم به component‌های جدا و مستقل، کار‌ها و وظایف تیم‌های توسعه را از یکدیگر جدا کند و همچنین با این کار، استقرار (deployment) را هم آسان‌تر کند. یکی از مواردی که بسیار توصیه می‌شود، جداسازی component‌ها در سطوح مختلف مانند سطح کد، سطح استقرار و سطح سرویس است که در صورت تغییر نیازمندی‌ها و use caseها، اعمال تغییرات را آسان‌تر می‌کند. این جداسازی از طریق اعمال دو اصل SRP و CCP، قابل انجام است. این که در کدام سطح باید جداسازی را انجام دهیم (به آن decoupling mode می‌گویند)، یکی از گزینه‌هایی است که باید باز بماند و بعداً با توجه به نیاز‌ها، در مورد آن تصمیم‌گیری شود. این فصل به این نکته هم اشاره دارد که توسعه‌دهندگان باید ترس از duplication (تکرار کد) را کنار بگذارند و سعی نکنند تکرار‌های تصادفی را حذف کنند.فصل هفدهم در مورد اهمیت جدا کردن بخش‌های مختلف نرم‌افزار و کاهش coupling (وابستگی بخش‌ها به یکدیگر) صحبت می‌کند. این فصل همچنین بیان می‌کند که تصمیماتی که در ابتدای پروژه گرفته می‌شوند، بخصوص آن‌هایی که ربطی به نیازمندی‌های کسب‌وکار ندارند، می‌توانند در ادامه کار باعث ایجاد مشکلاتی در توسعه نرم‌افزار شوند. این فصل در ابتدا چند کمپانی رو مثال می‌زند که تصمیمات معمارانه عجولانه‌ای گرفتند و بعداً دچار مشکل شدند و سپس، در مورد FitNesse حرف می‌زند که پروژه عمو باب با پسرش بود و در آن چون مرز‌های بین component‌ها به خوبی مشخص شده بودند، انعطاف‌پذیری در توسعه بالاتر رفته بود و می‌توانستند بسیاری از تصمیم‌ها را به عقب بیاندازند. در کل این فصل پیشنهاد می‌کند که در معماری نرم‌افزارمان، با استفاده از اصولی مانند SRP، DIP و SAP، مرز‌هایی را مشخص کنیم تا وابستگی‌ها حداقل شوند و maintainability راحت‌تر شود.فصل هجدهم در مورد مرز‌های متفاوتی که در معماری یک سیستم نرم‌افزاری بکار می‌روند و ویژگی‌های هر یک از این مرز‌ها صحبت می‌کند. این فصل در انتها هم اشاره می‌کند که بیشتر سیستم‌ها با توجه نیازمندی‌هایشان، ممکن است از ترکیبی از این استراتژی‌ها استفاده می‌کنند. در ابتدا، source-level decoupling mode را داریم که یک مرز ساده است و فضای بحث، درون یک پردازنده و یک فضای آدرس است. در این روش جداسازی منظم تابع‌ها و داده را از یکدیگر داریم. این روش بیشتر در برنامه‌های یکپارچه و monolithic مطرح است و جهت وابستگی‌ها، از سطوح پایین‌تر به سمت سطوح بالاتر است. مفهوم بعدی، وابستگی زمان اجرا یا همان runtime dependency است که صدا زدن سرویس‌های سطح پایین توسط clientهای سطح بالا است و در آن، وابستگی‌ها در جهت مخالف جریان کنترل از مرز عبور می‌کنند. مورد بعدی، deployment-level decoupling mode است که همان dll‌ها، jar فایل‌ها، war فایل‌ها و ... هستند که استراتژی مدیریتشان همانند monolith‌ها است (چون تابع‌های هردو درون یک پردازنده و فضای آدرس هستند). مرز بعدی، local process است که شامل پردازه‌هایی (همان process‌ها) است که در فضای آدرس جداگانه‌ای اجرا می‌شوند اما ممکن است component‌هایی را به اشتراک بگذارند. ارتباط از طریق socket‌ها یا سیستم‌عامل برقرار می‌شود و استراتژی جداسازی بخش‌ها از یکدیگر، مشابه monolith‌ها و binary component‌ها است. قوی‌ترین مرز، مرز سرویس است که در آن سرویس‌ها، پردازه‌هایی هستند که در شبکه دایر و در حال اجرا هستند. در این روش به دلیل بالا بودن تاخیر (چون به صورت فیزیکی از هم جدا هستند و با شبکه به هم وصلند)، ارتباطات کندتر از فراخوانی تابع‌ها است و کد سرویس‌های سطح بالا، نباید اطلاعی از سرویس‌های سطح پایین داشته باشند.فصل نوزدهم در مورد این حرف می‌زند که سیستم‌های نرم‌افزاری در اصل یکسری policy یا سیاست‌ها هستند که ورودی و خروجی‌ها را کنترل می‌کنند. در یک معماری خوب، این سیاست‌ها با توجه به دلیل و زمان تغییرشان، در component‌ها مختلف پخش می‌شوند. معماران نرم‌افزار این component‌ها را تبدیل به گراف جهت‌دار بدون دور (DAG) می‌کنند که در آن‌ها گره‌ها component‌هایی را که در یک سطح هستند نشان می‌دهند و یال‌های جهت‌دار، وابستگی‌های source code یا زمان کامپایل بین component‌ها را نشان می‌دهند. سطح یک component با توجه به میزان فاصله‌اش از ورودی و خروجی‌های سیستم، مشخص می‌شود. نکته بعدی این است که جهت وابستگی‌های source code ممکن است با جهت جریان داده یکسان نباشد که کار درستی است و هدف، وابسته کردن وابستگی‌های source code به سطوح component‌ها است. مطلب دیگر که بیان می‌شود این است که تغییرات در سیاست‌های سطوح پایین‌تر، بیشتر و غیرضروری‌تر است و برای همین بهتر است که اثر آن‌ها روی سیاست‌های سطوح بالاتر را کم کنیم و از آن‌ها به عنوان plugin‌هایی استفاده کنیم که به راحتی و بدون اثرگذاری روی سیاست‌های سطوح بالاتر، قابل تغییرند.فصل بیستم در مورد اهمیت درک و دسته‌بندی business rule‌ها یا همان قوانین کسب و کار، صحبت می‌کند. قوانین کسب و کار، قوانینی هستند که یا پول کسب و کار را زیاد می‌کنند و یا جلوی از دست رفتن پول آن‌ها را می‌گیرند. دو نوع کلی دارند: ۱. قوانین کسب‌و کار حیاتی یا Critical  ۲. قوانین کسب‌وکار Application-Specific یا همان use case‌ها. قوانین کسب‌وکار حیاتی، آن دسته از قوانین هستند که چه در سیستم کامپیوتری پیاده‌سازی شوند یا اینکه به صورت دستی اعمال شوند، باعث سود آن کسب‌وکار می‌شوند. این قوانین به داده‌های حیاتی کسب‌وکار (Critical Business Data) برای عملکردشان نیاز دارند و درون Entity‌ها قرار داده می‌شوند. قوانین کسب و کار Application-Specific، قوانینی هستند که مربوط به استفاده کاربران از سیستم کامپیوتری هستند و محدودیت‌هایی را روی عملکرد آن سیستم می‌گذارند. این قوانین که همان use case‌ها هستند، مشخص می‌کنند که قوانین کسب‌وکار حیاتی که درون Entity‌ها هستند چطور فراخوانی شوند و به نوعی آن‌ها را کنترل می‌کنند. Use case‌ها وابسته به Entity‌ها هستند (که سطحشان بالاتر است) اما Entity‌ها مستقل هستند و اطلاعی از use case‌ها ندارند (استفاده مفید از DIP) که باعث می‌شود بتوانیم از Entity‌ها در جاهای دیگر هم استفاده کنیم اما از use case‌ها نمی‌توانیم؛ Use case‌ها مخصوص همان برنامه‌ای هستند که براش نوشته شده‌اند. داده‌های ورودی و خروجی use case‌ها ساده و از یکدیگر مستقل هستند و reference‌ای به هیچ Entity‌ای ندارند.فصل بیست و یکم در مورد اهمیت ساخت برنامه‌ها به طوری که با use case‌ها مطابقت داشته باشند، صحبت می‌کند. کتاب در ابتدا مثالی از نقشه‌های ساختمان‌‌ها می‌زند و می‌گوید همانطور که نقشه یک کتابخانه، مشخص می‌کند که محصول نهایی یک کتابخانه است، معماری یک سیستم نرم‌افزاری هم باید اهداف و use case‌های آن سیستم نرم‌افزاری را مشخص کند و مبتنی بر use case‌های آن باشد. این فصل همچنین در مورد این حرف می‌زند که framework‌ها، ابزار هستند و نباید به آن‌ها بچسبیم و بگذاریم معماری ما را تعریف کنند. یک معماری خوب، framework‌ها و ابزار توسعه را از use case‌ها جدا می‌کند و تصمیم در مورد آن‌ها را عقب می‌اندازد. مثلا اگر برنامه در حوزه وب است، معماری نباید از آن خبر داشته باشد و اهمیتی به آن یا تغییر آن بدهد. این قضیه انجام unit test‌ روی use case‌ها را نیز آسان‌تر می‌کند (مستقل از framework‌ها و ابزار). در کل، باید use case‌ها را در اولویت قرار داد و در مورد framework‌ها و ابزار، انعطاف‌پذیر بود.فصل بیست و دوم در مورد ویژگی مشترک بین یکسری معماری معروف صحبت می‌کند؛ مانند معماریHexagonal ، DCI و BCE که با وجود تفاوت‌ها، بخش‌های مختلف را از یکدیگر جدا کرده‌اند و لایه‌هایی جداگانه مخصوص قوانین کسب‌و‌کار و رابط‌های کاربری و سیستمی (User interface and system interface) دارند. این فصل علاوه بر اینکه مجدد به این مطلب اشاره دارد که باید به framework‌ها به عنوان یک ابزار نگاه کرد و از آن‌ها مستقل بود، در مورد استقلال از پایگاه داده و رابط کاربری هم حرف می‌زند و از مزایای آن مانند تست‌پذیری مستقل و آسان‌تر قوانین کسب‌و‌کار، صحبت می‌کند. در کل قوانین کسب‌وکار باید از رابط‌‌های خارجی (مانند UI) مستقل و از نحوه ارائه خود به بیرون، بی‌اطلاع باشند. علاوه بر مفاهیم فصل‌های قبل (entity و use case)، در مورد interface adapters‌ها هم صحبت می‌کند که تبدیل فرمت‌های داده‌ای را بین use case‌ها و بخش‌های خارجی مانند پایگاه داده، انجام می‌دهد. این فصل همچنین روی استفاده از dynamic polymorphism و ساختار داده‌های ساده برای ارتباط بین مرز لایه‌های مختلف تاکید دارد. در کل این فصل بر استقلال بخش‌های مختلف سیستم از یکدیگر، برای بالابردن انعطاف‌پذیری و تست‌پذیری سیستم، تاکید دارد.فصل بیست و سوم در مورد الگوی Humble Object حرف می‌زند که به جداسازی رفتار‌هایی که تستشان سخت است از آن‌هایی که تستشان آسان است، کمک می‌کند و تست‌پذیری را بالا می‌برد. این کار از طریق تقسیم رفتار‌های سیستم به دو ماژول یا کلاس انجام می‌شود؛ رفتار‌هایی که تستشان سخت است با یک فرم ساده‌ای درون ماژول humble قرار می‌گیرند و باقی رفتار‌های قابل تست در ماژول دیگر قرار می‌گیرند. این الگو با جداسازی بخش‌های قابل تست و غیرقابل تست برنامه از یکدیگر، درتعیین مرز‌های معماری به ما کمک می‌کند. یکی از مواردی که در آن از الگوی Humble Object استفاده شده است، تقسیم GUI به دو کلاس view و presenter است که در آن، view همان humble و presenter بخش قابل تست است. View وظیفه رندر کردن المان‌ها و نمایش بخش گرافیکی برنامه را برعهده دارد و presenter داده‌ها را از برنامه می‌گیرد و با فرمت مناسب، به view تحویل می‌دهد تا نمایش دهد. این فصل در این مورد نیز حرف می‌زند که به جای واژه ORM، باید از واژه data mapper استفاده کنیم که داده را از جداول دیتابیس‌های رابطه‌ای می‌گیرد و درون ساختمان داده‌های ساده قرار می‌دهد و اینکه متعلق به لایه پایگاه داده است که با استفاده از الگوی Humble Object، مرزی بین آن و gateway interface‌ها که اعمالی که در لایه پایگاه‌داده پیاده‌سازی شده‌اند، از طریق آن‌ها فراخوانی می‌شوند، ایجاد شده است. اصل Humble Object همچنین می‌تواند بین سرویس‌های یک سیستم مرز ایجاد کند و در کل، اصلی کارآمد است که تست‌پذیری سیستم را بالا می‌برد و در تعیین مرز‌های سیستم، نقش مؤثری دارد.فصل بیست و چهارم در مورد مرز‌های معماری در طراحی نرم‌افزار و رویکرد‌های مدیریت آن‌ها حرف می‌زند. مرز‌های معماری برای جداسازی component‌های مختلف سیستم مورد استفاده قرار می‌گیرد اما تنظیم اولیه و نگهداری آن‌ها، هزینه بر و پیچیده است. این مرز‌ها از طریق ساخت اینترفیس‌ها، ساختمان‌داده‌های ورودی و خروجی و مدیریت وابستگی‌ها انجام می‌شود. طراحی مقدماتی یعنی اینکه مرز‌های معماری را قبل از آنکه به آن‌ها نیاز پیدا کنیم، بسازیم که بعضی افراد که از اصل YAGNI یا همان You Aren’t Going to Need It طرفداری می‌کنند، با این موضوع مخالف هستند. یکی از راه‌های کاهش هزینه‌های ایجاد مرز، این است که مرز‌های کامل را مشخص نکنیم و از مرز‌های partial استفاده کنیم که همان طراحی مقدماتی مرز‌های کامل را دارند، اما کامپایل و تبدیل به یک unit می‌شوند که مشکلات مدیریت نسخه را کاهش می‌دهد. استفاده از الگوی facade هم می‌تواند به تعیین مرز‌ها کمک کند. در کل، مرز‌های معماری برای مدیریت پیچیدگی نرم‌افزار ضروری هستند اما پیاده‌سازی آن‌ها می‌تواند فرق کند و از پیاده‌سازی کامل داشته باشیم تا یک پیاده‌سازی ابتدایی که قرار است جایگزین شود.فصل بیست و پنجم می‌گوید که سیستم‌های نرم‌افزاری، معمولاً سه component اساسی دارند: UI، قوانین کسب‌وکار و پایگاه داده. این فصل مثالی از یک بازی می‌زند و در ابتدا مشخص می‌کند چطور می‌توان از طریق جداسازی UI و زبان، بازی را به زبان‌های دیگر هم ترجمه کرد. در ادامه در مورد فواید جداسازی قوانین بازی از فضای ذخیره‌سازی بازی‌ها صحبت می‌کند. در ادامه می‌گوید که مرز‌های معماری فقط نباید UI، game rule‌ها و data storage‌ها باشند و ترجمه‌های زبان، مکانیزم‌های ارتباطی و ... هم می‌توانند مرز‌های معماری باشند. هدف این فصل این است که بگوید مرز‌های معماری در تمام جاهای سیستم پخش هستند و وظیفه معمار نرم‌افزار این است که زمانی که به آن‌ها نیاز شد، آن‌ها را شناسایی، پیاده‌سازی و مدیریت کند.فصل بیست و ششم در مورد Main component حرف می‌زند که کثیف‌ترین component سیستم است و به این موضوع اشاره دارد که این component، پایین‌ترین سطح را دارد، ورودی سیستم از آنجا است و جز سیستم عامل، هیچ component دیگری به آن وابسته نیست. این component وظیفه ساخت و نظارت بر تمام component‌های دیگر سیستم را دارد. این فصل می‌گوید که Main جایی است که وابستگی‌ها باید توسط Dependency Injection framework تزریق شوند. وقتی این تزریق انجام شود، Main این وابستگی‌ها را بدون نیاز به framework، در سیستم پخش می‌کند. Main بیرونی‌ترین دایره معماری تمیز است و شرایط و تنظیمات اولیه را برای سیستم سطح بالا آماده می‌کند و کنترل را به آن می‌دهد. متن همچنین به نکته اشاره می‌کند که داشتن چندین Main plugin که هرکدام تنظیمات خاصی دارند و برای محیط‌های خاصی نوشته شده‌اند (محیط Dev، Test یا Production)، مشکل پیکربندی و تنظیم سیستم را حل می‌کند.فصل بیست و هفتم در مورد محبوبیت معماری‌های مبتنی بر سرویس و micro-service صحبت می‌کند. دلیل این محبوبیت، جدا بودن سرویس‌ها از یکدیگر و همچنین جدا بودن فرایند‌های توسعه و استقرار در این معماری و امکان تخصیص این وظایف به تیم‌های مختلف است. برخلاف تفکر عام، سرویس‌ها معماری را تعریف نمی‌کنند و معماری توسط مرز‌هایی که سیاست‌های سطح بالا را از جزئیات سطح پایین جدا می‌کنند و از dependency rule پیروی می‌کنند، تعریف می‌شود. کتاب همچنین بیان می‌کند که نیاز نیست که تمام سرویس‌ها از نظر معماری قابل توجه و خاص باشند و امکان دارد بعضی از سرویس‌ها، از این نظر خاص نباشند و فقط برای جدا کردن رفتار برنامه بکار بروند. نکته بعدی این است که با اینکه سرویس‌ها ممکن است جدا به نظر بیایند، اما ممکن است بخاطر منابع مشترک درون یک پردازنده یا در یک شبکه، به هم وابسته باشند. در این معماری، اضافه کردن ویژگی جدید که چند سرویس را در بر بگیرد، می‌تواند اذیت‌کننده باشد. یکی از راه حل‌های بیان شده در این فصل، استفاده از کلاس‌ها abstract و طراحی مبتنی بر component است که از OCP هم پیروی می‌کند. برای حل مشکل دربر گرفتن چند سرویس، باید درون آن‌ها component‌هایی در نظر گرفته شود که از dependency rule پیرو‌ی می‌کنند و سپس با استفاده از مرز‌های معماری، این component‌ها باید جدا شوند. در کل، سرویس‌ها معماری سیستم را مشخص نمی‌کنند و معماری سیستم با مرز‌های مشخص شده و وابستگی‌هایی که از آن مرز‌ها عبور می‌کنند، مشخص می‌شود.فصل بیست و هشتم در مورد این می‌گوید که باید انواع مختلف تست (مانند unit test، integration test و ...) را عضوی جدایی ناپذیر از معماری بدانیم و با آن‌ها مثل یکی از component‌های اساسی سیستم (و معادل هم)، رفتار کنیم. تست‌ها، بیرونی‌ترین دایره در معماری سیستم هستند و از Rule Dependency پیروی می‌کنند. تست‌ها به طور مستقل قابل استقرار هستند و معمولا در سیستم‌های تست مستقر (deploy) می‌شوند. تست‌ها component‌های ایزوله‌ای هستند که بیشتر از عمل توسعه پشتیبانی می‌کنند تا از عملکرد سیستم. یکی از چالش‌ها، fragile test‌ها هستند که وقتی اتفاق می‌افتند که تست‌ها بسیار به سیستم متصل و وابسته باشند که باعث می‌شوند یک تغییر کوچک در component‌های سیستم، باعث ناکارآمد شدن تست‌ها شود. برای رفع این مشکل باید وابستگی به عناصری که زیاد تغییر می‌کنند مانند GUI را کم کرده و تست را بیشتر روی business rule‌ها انجام دهیم که تغییرات کمتری دارند. در کل بهتر است که تست‌ها از ساختار برنامه جدا شوند و از testing api‌ها برای کاهش هزینه و مشکلات درگیری با محدودیت‌های امنیتی استفاده شود.فصل بیست و نهم در مورد اهمیت فرق گذاشتن بین نرم‌افزار و firmware در سیستم‌های embedded صحبت می‌کند. خیلی اوقات به اشتباه از firmware در جاهایی استفاده می‌شود که باید از نرم‌افزار استفاده می‌شد که باعث ایجاد وابستگی‌هایی روی سخت‌افزار و سخت شدن تغییرات می‌شود. کتاب روی معماری‌های embedded تمیزتر با استفاده از hardware abstraction layer‌ها (HAL) و operating system abstraction layer‌ها (OSAL) برای جداسازی نرم‌افزار از وابستگی‌های سخت‌افزاری، تاکید دارد که باعث نگهداری (maintainability) و تست‌پذیری بهتر نرم‌افزار می‌شود. عمو باب روی معماری تمیز سیستم‌های embedded تاکید دارد.</description>
                <category>آرمین مظفری</category>
                <author>آرمین مظفری</author>
                <pubDate>Fri, 20 Oct 2023 23:24:03 +0330</pubDate>
            </item>
            </channel>
</rss>