<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های راهبردهای خلاق آرمان</title>
        <link>https://virgool.io/feed/@armansolutions</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-06-16 22:28:56</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1380304/avatar/Tvls5f.png?height=120&amp;width=120</url>
            <title>راهبردهای خلاق آرمان</title>
            <link>https://virgool.io/@armansolutions</link>
        </image>

                    <item>
                <title>دیر رسیدن، فرقی با هرگز نرسیدن ندارد!</title>
                <link>https://virgool.io/@armansolutions/%D8%AF%DB%8C%D8%B1-%D8%B1%D8%B3%DB%8C%D8%AF%D9%86-%D9%81%D8%B1%D9%82%DB%8C-%D8%A8%D8%A7-%D9%87%D8%B1%DA%AF%D8%B2-%D9%86%D8%B1%D8%B3%DB%8C%D8%AF%D9%86-%D9%86%D8%AF%D8%A7%D8%B1%D8%AF-n8tk38ozfsjy</link>
                <description>آیا از کندی پایپ‌لاین‌های خود رنج می‌برید؟ fail شدن پایپ‌لاین‌ها امان شما را بریده‌اند؟ آیا به خاطر ضعیف‌بودن شبکه رانرها یا لود زیاد روی آن‌ها، پایپ‌لاین‌های شما حتی dependencyهای پروژه را نیز نمی‌توانند دانلود کنند؟ اگر پاسختان به این سوالات آری‌ست، احتمالا این مطلب برای شماست!مدتی بود که ما در سینماتیکت، تقریبا از تمامی مشکلات بالا رنج می‌بردیم و کله‌هایمان ملول شده بود! دانلود base image داکرفایل‌ها به مشکل می‌خورد، npm نمی‌توانست dependencyهای پروژه را دانلود کند و اعتراف می‌کرد که مشکل از من است، checksum پیش‌نیاز‌ها در pip اشتباه بود و همه‌ی این‌ها، باعث می‌شدند نه داکر ایمیج‌ها بیلد شوند و نه تست‌ها اجرا. از خود مشکلات هم که بگذریم، گه‌گداری بودن آن‌ها، خبر از مشکل در جایی خارج از داکرفایل‌ها و پایپ‌لاین‌ها می‌داد.حالت‌های مختلفی را تست کردیم. بعضی اوقات چندین و چند بار یک تسک پایپ‌لاین را باید retry می‌کردیم تا با موفقیت اجرا شود. مانیتور سرور رانرها نشان می‌داد آنچنان cpu و memory درگیر نیستند، اما ترافیک زیادی در شبکه‌ی سرورها استفاده می‌شد. مشخصا تمام تقصیرها گردن شبکه بود.راه حل اول برای چنین مشکلی، قطعا افزودن پهنای باند و اختصاص منابع بیشتر به سرورهاست، اما همیشه اولین راه، بهترین راه نیست! حتی بعضا ارزان‌ترین راه هم نیست. پس تصمیم‌ گرفتیم پایپ‌ها را بهتر کنیم.روشن بود که باید تا جای ممکن از دانلود چندباره‌ی پکیج‌ها جلوگیری کنیم. بخشی از پایپ‌ها که بیشتر از سایر قسمت‌ها شبکه را درگیر می‌کنند، همین دانلود و نصب پکیج‌های موردنیاز هر پروژه است. ایده ساده بود: باید پکیج‌ها کش می‌شدند. اما چطور؟ چگونه کش‌ها را آپدیت کنیم؟ چگونه از آن‌ها روی تمامی برنچ‌ها و پایپ‌‌لاین‌های پروژه استفاده کنیم؟همانطور که احتمالا می‌دانید، داکر، ایمیج‌ها را لایه‌لایه بیلد می‌کند. به این صورت که هر خط دستور در داکرفایل و فایل‌های مربوط به دستور، به صورت hash شده نگه‌داری می‌شود تا در صورت امکان، به جای اجرای دوباره‌ی آن دستور، از کش استفاده کند. مثلا اگر در داکرفایل چند فایل را به داخل ایمیج کپی کرده‌اید، اگر فایل‌ها را تغییر ندهید، داکر هر دفعه از اول عمل کپی را انجام نمی‌دهد. بلکه دفعه‌ی اول کپی می‌کند و دفعه‌های بعد (اگر فایل‌ها تغییر نکنند) از کش استفاده می‌کند. حالا چرا از این قابلیّت در پایپ‌لاین‌ها استفاده نکنیم؟به طور کلی، ایده این است که استیجی در داکرفایل به عنوان cache داشته باشیم و آن استیج را به عنوان ایمیج کش بیلد کنیم. در این استیج، می‌توانیم فایل‌های ثابت پروژه را در داکر ایمیج بریزیم یا dependencyها را نصب کنیم. حالا با فرض داشتن این ایمیج کش، زمانی که می‌خواهیم ایمیج اصلی را بسازیم، به داکر می‌گوییم از این ایمیج کش به عنوان مرجع برای همان هش‌ها و لایه‌های کش شده استفاده کن. در این صورت، می‌توان از اجرای قسمت‌هایی که در هر بیلد ثابت هستند و یا کم‌تر از بقیه‌ی قسمت‌ها تغییر می‌کنند جلوگیری کرد. چرا که می‌توان مثلا روزی یک‌بار ایمیج کش را بسازیم و در دفعات بعدی اجرای پایپ‌لاین، آن را از رجیستری و مخزن داکر ایمیج‌ها دریافت و استفاده کرد.حالا به اجرای فرایند توضیح‌داده‌شده در یک پروژه‌ی پایتونی می‌پردازیم. داکرفایل می‌تواند به شکل زیر باشد:همانطور که در داکرفایل پیداست، در استیج اول، یعنی base، پکیج‌های مورد نیاز پروژه نصب شده‌اند. چه پکیج‌های سیستمی و چه پکیج‌های پایتون. در استیج‌های بعدی به کدها پرداخته شده و فایل‌های لازم به داخل داکر ایمیج انتقال داده شده‌اند.با داشتن داکرفایل بالا، می‌توان از استیج base به عنوان یک Cache Image استفاده کرد. اما نحوه‌ی استفاده از آن در پایپ‌لاین‌ چگونه خواهد بود؟بیلد داکر ایمیج پروژه می‌تواند به شکل زیر انجام شود:ابتدا وجود Cache Image را روی رجیستری بررسی می‌کنیم. اگر Image وجود داشته باشد که دریافت می‌شود، در غیر این صورت، باید ساخته شود.در خط بعد، Cache Image ساخته می‌شود. اگر در قسمت قبل Image دریافت شده‌باشد، به خاطر استفاده از همان Image به عنوان منبع کش (--cache-from)، به سرعت انجام می‌شود. اگر هم Image دریافت نشده‌باشد، این‌جا ساخته می‌شود. در دستور سوم، برای ساخت Image اصلی از Cache Image به عنوان مرجع کش استفاده می‌کنیم تا قسمت نصب نیازمندی‌های پروژه، به ازای هر بار ساخت Image اجرا نشود. به این شکل می‌توان تا حد زیادی در ترافیک شبکه و زمان اجرای پایپ‌لاین‌ها صرفه‌جویی کرد.تمام شد؟ تاثیرگذار هم بود؟بعد از اعمال این تغییرات روی پایپ‌لاین‌ها و داکرفایل‌هایمان، باید بررسی می‌کردیم که آیا واقعا این تغییرات تاثیر به سزایی روی عملکرد و سرعت پایپ‌لاین‌ها می‌گذارند یا خیر. اگر از کاهش چشم‌گیر تعداد پایپ‌لاین‌هایی که به خاطر مشکلات شبکه با شکست مواجه شده‌بودند بگذریم، زمان اجرای پایپ‌لاین‌هایی که از کش استفاده می‌کردند، روی پروژه‌های پایتونی تا ۱۰ برابر سریع‌تر شدند!این قصه سر دراز دارد …البته این تنها راه بهبود پایپ‌لاین‌ها نیست. راهکارهای متفاوتی برای این کار وجود دارد. به طور کلی نیز  می‌توان با رعایت اصولی در نوشتن داکرفایل‌ها، هزینه‌ی هر بار ساختن داکر Image را کم‌تر کرد. یکی از این اصول، داشتن یک ساختار به شکل هرم برعکس در دستورات داخل داکرفایل است. به این معنی که دستوراتی که تغییرات اساسی و بزرگی ایجاد می‌کنند و کم‌تر هم تغییر می‌کنند، در ابتدای داکرفایل باشند. اما آن‌هایی که در هر بار بیلد کردن Image احتمال تغییرشان بیشتر است، پایین‌تر.به طور مثال، نصب نیازمندی‌های سیستمی و پکیج‌های مورد نیاز، باید در ابتدای داکرفایل باشند. چرا که dependencyهای پروژه کم‌تر تغییر می‌کنند. اما انتقال کدها به داخل Image، باید در دستورات انتهایی داکرفایل باشد. چرا که تغییر کدها، متداول‌تر است.شاید فرمول و روش یکسانی برای همه‌ی مشکلات پایپ‌لاین‌ها نتوان ارائه کرد، اما مجموعه‌ای از راه‌کار‌ها، مثل روش‌های ذکر شده، وجود دارند که متناسب با پروژه‌ی مدنظر، می‌توان از برخی از آن‌ها استفاده کرد تا زمان پایپ‌لاین‌ها کاهش و اتکاپذیری آن‌ها افزایش پیدا کند. شاید کلید اصلی این کار، در شناخت کافی از ابزارهای مورد استفاده، و همچنین مانیتور کردن باشد. تا ابتدا منبع مشکل پیدا شده و سپس با استفاده از ابزار مناسب، در جهت بهبود و رفع آن، اقدام شود.این مطلب توسط محمدحسین بهمنی در بلاگ راهبردهای خلاق آرمان نوشته شده است.</description>
                <category>راهبردهای خلاق آرمان</category>
                <author>راهبردهای خلاق آرمان</author>
                <pubDate>Thu, 03 Mar 2022 11:54:19 +0330</pubDate>
            </item>
                    <item>
                <title>تجربه پیاده سازی Clean Architecture در صباویژن</title>
                <link>https://virgool.io/@armansolutions/%D8%AA%D8%AC%D8%B1%D8%A8%D9%87-%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-clean-architecture-%D8%AF%D8%B1-%D8%B5%D8%A8%D8%A7%D9%88%DB%8C%DA%98%D9%86-pemsnsgsongf</link>
                <description>اگر مهندس نرم‌افزار هستید، ممکن است خیلی در مورد معماری‌ها مطالعه کرده باشید. می‌توان به معماری Layered به عنوان یکی از محبوب‌ترین معماری‌ها اشاره کرد. معماری‌های زیادی با همین ایده معرّفی شده‌اند. معماری Clean از جمله‌ی همین‌ معماری‌ها است.ما در صباویژن به تازگی معماری کلین را برای سرویس بکند پیاده‌سازی کرده‌ایم. در این نوشته به صورت مختصر از تجربه‌ها، چرایی و چالش‌هایی که برایمان وجود داشته نوشته‌ام.چرا به پیاده‌سازی معماری کلین فکر کردیم؟یکی از مهمترین دلایل برای اجرای معماری کلین در پروژه صباویژن آشفتگی و بی‌نظمی منطق‌های نوشته‌ شده‌ است. این آشفتگی به‌‌دلیل تغییرات بسیار زیاد بیزینس و تعدّد پیاده‌سازی‌هایی که وجود‌ داشته، به وجود آمده‌ است.وقتی که توسعه‌دهنده‌ی جدیدی به تیم اضافه می‌شود، مراحل آماده‌سازی وی توسط مدیر تیم انجام می‌شود. امّا چه اندازه با جزئیات می‌توان کل پروژه را برای نیروی جدید توضیح داد؟مطمئناً اگر پروژه ساختار یکپارچه و منظمی نداشته باشد، احتمالاً نیروی جدید با سختی‌های بسیاری روبه‌رو خواهد شد.برای جلوگیری از بی‌نظمی پروژه راه‌های مختلفی وجود دارد: تنظیم سندهایی درون‌تیمی که کل تیم به آن متعهّدند، استفاده از معماری‌های نرم‌افزاری و رعایت کداستایل واحد.این مشکلات فقط مختص به نیروی جدید نیست، بلکه حتّی نیروهای با سابقه نیز گاهی دچار مشکل و پیچیدگی می‌شوند که این برای تیم نرم‌افزاری و شرکت بسیار بد است.به لطف ابزارهای اصلاح‌کننده‌، کد‌استایل پروژه از نظر نظم ظاهری یکپارچه می‌شود. امّا مشکل از جایی شروع می‌شود که برای فهمیدن نحوه‌ی کارکرد منطق یک قسمت از پروژه باید حجم بزرگی از کد را در قسمت‌ها و ماژول‌های مختلف مورد بررسی قرار دهیم. هرچند گاهی اوقات به سختی می‌توان حتّی منطق کد نوشته‌شده را درک کرد. حال هرچه پروژه بیشتر توسعه داده شود پیچیدگی بیشتر خواهد شد. در حقیقت معماری کلین در باطن خودش یکپارچگی و نظم را وارد نرم‌افزار می‌کند.منظور از نظم و یکپارچگی صرفاً ساختاربندی پوشه‌ها و قراردادن ماژول‌ها در جای خود نیست! برای پیاده‌سازی معماری کلین باید Data Flow بین لایه‌های مختلف نرم‌افزار همیشه به‌درستی برقرار باشد. باید لایه‌های درونی‌تر هیچ وابستگی به لایه‌های بیرونی نداشته باشند. باید همیشه لایه‌های بیرونی به لایه‌های درونی وابستگی داشته باشند و بسیاری از موارد دیگری که رعایت‌شان ضروری است.حال اگر موارد اساسی را به درستی و بدون نقص رعایت کردید، نظم و یکپارچگی به طور کامل وارد نرم‌افزارتان خواهد شد. امّا با این حال، نباید از ساختاربندی پوشه‌ها و قوانین نام‌گذاری غافل شد.آیا شما نیاز به معماری کلین دارید؟اگر درحال راه اندازی MVP استارتاپ هستید، همین الان به شما می‌گویم که خیر! اگر محصولی دارید که به بلوغ خودش رسیده و در حال حاضر به فکر قدرت بیشتر در توسعه و یکپارچگی در نرم‌افزارتان هستید، معماری کلین می‌تواند خیلی به شما کمک کند.در کل برای پیاده‌سازی معماری کلین، زمان و هزینه‌های زیادی را باید در نظر داشته باشید. در مراجع، نسخه از پیش تعیین شده‌ای برای پیاده‌سازی وجود ندارد و شما باید طبق نیازمندی‌های پروژه و براساس راهنمایی‌ها و مفاهیم موجود معماری مورد نظر خود را طراحی کنید.توضیحاتی در مورد معماری کلیناگر در مورد معماری‌های Layered مطالعه داشته باشید متوجّه می‌شوید که از لحاظ مفاهیم خیلی به هم شبیه هستند. برای مثال، معماری Hexagonal یا Port Adapter چندسالی قبل از معماری کلین معرفی شدند امّا در باطنشان کاملاً یک چیز را مطرح می‌کنند و آن‌هم رعایت وابستگی‌هاست.حالا منظورمان از رعایت وابستگی‌ها چیست؟معماری کلین سه لایه را معرفی می‌کند که عبارتند از: Use Case ،Presentation ،Entityدر حقیقت هرکدام از این لایه‌ها باید کاملاً از هرچیزی که خارج از آن‌ها وجود دارد ایزوله باشند. لایه‌های درونی نباید هیچ وابستگی‌ای به بیرون داشته باشند، درحالی‌که لایه‌های بیرونی می‌توانند وابستگی به لایه‌های درونی داشته باشند و از آن‌ها استفاده کنند. رعایت این وابستگی‌ها مهم‌ترین عامل برقراری معماری کلین هست. وظیفه هرکدام از لایه‌ها به شرح زیر هست:Entity:درونی‌ترین لایه (نباید هیچ وابستگی‌ای به بیرون داشته باشد) است. در حقیقت این لایه یک موجودیّت (می‌تواند فانکشن یا دیتاکلاس باشد) است که Business Rules را درخود دارد.این لایه از هرگونه تغییر در دنیای بیرون ایزوله است. برفرض مثال، اگر نحوه صفحه‌بندی (Pagination) را بخواهیم تغییر دهیم این لایه نباید تحت تاثیر قرار گیرد.اگر بخواهیم با لایه‌های مختلف یا سرویس‌های خارجی مثل دیتابیس یا سرویس بروکرها حرف بزنیم باید از این لایه برای انتقال داده استفاده کنیم.ورودی آرگومان و خروجی لایه های مختلف از جنس Entity می‎‌باشد و زبان مشترک بین لایه های مختلف می‎‌باشد.Use Case:شامل منطق کسب و کاری‌مان است که یک لایه بیرون‌تر از مدل است. در این لایه مفهومی به نام معرفی خواهد شد که وظیفه آن چیزی شبیه کنترلرها در معماری MVC یا View در معماری MVT است.این لایه وظیفه انتقال داده از entity به بیرون و از لایه‌های بیرون به entity را دارد.Presentation:این لایه بیرونی‌ترین لایه در معماری کلین است و وظیفه ارائه و یا گرفتن داده از کاربر را دارد. در وب سرویس‌ها میتوان آن را به Serializerها تشبیه کرد.نکته‌ای که باید به آن دقت کرد این است که بسته به نیاز شما این تعاریف از لایه‌ها ممکن است که تغییر کند و شما نباید محدود به این تعاریف باشید. تنها باید پایبند به قوانین وابستگی در این لایه‌ها باشید.این‌که می‌گوییم نباید هیچکدام از لایه‌ها از لایه‌های دیگر خبر داشته باشند چه معنی‌ای می‌دهد؟یعنی اگر برفرض مثال در لایه Presentation خواستیم تغییری ایجاد کنیم، نباید این تغییر به لایه‌های داخلی وابسته باشد و باید بتوان به شکل مستقل منطق‌ها را تغییر داد. با این اوصاف ما هیچ وابستگی‌ای به فریمورک یا رابط کاربری یا حتّی دیتابیس و انواع سیستم‌های خارجی مثل Messagin-Queueها و … نداریم.در نتیجه، به‌راحتی می‌توانیم از جنگو به فلسک سوییچ کنیم، یا اگر تصمیم به تغییر RabbitMQ به Apache Kafka داشته باشیم به راحتی بتوانیم این تغییرات را انجام دهیم و فقط اینترفیس‌هایی که با سیستم‌های خارجی در ارتباط هستند را باید تغییر داد.معماری کلین چه مزایایی را به ما اضافه می‌کند؟– مستقل از فریمورک، دیتابیس، رابط کاربری و سیستم‌های خارجیهمانطور که گفتیم بنیادی‌ترین اصل معماری‌های نرم‌افزاری رعایت وابستگی‌هاست.لایه‌های معماری کلین در حقیقت مانند دایره‌هایی متحدالمرکز هستند که هر یک وظیفه‌ای از قسمت‌های مختلف از نرم‌افزار ما را برعهده گرفته‌اند. قانونی برای وابستگی‌ها در معماری وجود دارد که بیان می‌کند که تنها لایه های بیرونی می‌توانند به لایه‌های درونی وابسته باشند. و جهت وابستگی از بیرون به درون است. یعنی لایه‌های درونی نباید هیچ اطلاعاتی از لایه‌های بیرون داشته باشند. نباید فانکشن یا متغیر یا کلاسی از لایه‌های بیرون در لایه‌های درونی صدا زده شود یا فراخوانی شود. اگر این اتفاق بیافتد یعنی شما قانون وابستگی را نقض کرده‌اید و منتظر اتفاقاتی بدی که در ادامه توسعه برایتان خواهد افتاد باشید.بر فرض مثال اگر فریمورکمان جنگو است، نباید در Use Caseها وابستگی به جنگو داشته باشیم! یک روش خیلی ساده که من برای خودم تعریف کردم تا بتوانم رعایت وابستگی را چک کنم این است که اگر بالای هر فایلی که در داخل لایه‌های درونی است (در اینجا Use Case)، ایمپورتی از لایه‌ی بیرونی (در اینجا فریمورک) را ببینید، بدانید که وابستگی‌ها را رعایت نکرده‌اید! مثلاً من نباید با این صحنه مواجه شوم:خب! پس اگر هیچ وابستگی به فریمورکی که استفاده می‌کنیم نداشته باشیم، به راحتی می‌توانیم فریمورک‌مان یا حتّی دیتابیس‌مان را عوض کنیم. حتّی می‌توانیم کد را در محیط cli اجرا کنیم بدون اینکه چیزی را بازنویسی کنیم.در خیلی از پروژه‌های بزرگ این اتفاق می‌افتد که با بزرگ شدن مقیاس بیزینس، بعضی از ابزارها دیگر مناسب مقیاس نیستند و مجبور می‌شویم تا سریع‌ترین راه‌حل و بهترینش (با توجّه به شرایط پروژه) را انتخاب کنیم. اگر در نرم‌افزار ما، مدیریت وابستگی‌ها به درستی رعایت شده باشد پس نباید هیچ نگرانی از تغییر تکنولوژی‌ها داشته باشیم زیرا در کوتاه‌ترین زمان ممکن می‌توان این اتفاق را رقم زد. برای مثال تجربه نتفیلیکس از تغییر Json Api به GraphQL در کمتر از ۲ ساعت میتواند گواه این قدرت باشد. حال دیگر محدود به امکانات فریمورکی که انتخاب می‌کنید نیستید و از فریمورک به عنوان یک ابزار استفاده می‌کنید! برای مثال ما در صباویژن از جنگو به منظور مدیریت کردن ریکویست‌ها، روتینگ و همچنین ORM قدرتمندی که دارد، داخل معماری کلین استفاده می‌کنیم.– هرچیزی قابل تست استبه‌ خاطر عدم وابستگی به دیتابیس، فریمورک، رابط کاربری و سیستم‌های خارجی به راحتی می‌توانیم برای قسمت‌های مختلف نرم افزارمان تست بنویسیم. همیشه تیم نرم‌افزاری‌ای قدرتمندتر و چابک‌تر است که تست‌های قوی‌تر و قابل اطمینان‌تری داشته باشد.برای مثال می‌خواهیم تستی برای درست عمل کردن کد تخفیف و سناریوی درگاه پرداخت بنویسیم. احتمالاً اولین چیزی که به ذهنتان میرسد نوشتن اینتگریشن تست است. امّا ما در معماری کلین به دلیل اینکه از Repository Pattern استفاده می‌کنیم به راحتی می‌توانیم برای سیستم‌های خارجی (دیتابیس، Messaging Queue، سرویس پیامک، API بانک و …) Fake Repository بنویسیم. در حقیقت با Repository Pattern ما خودمان را یک لایه از سرویسی که استفاده می‌کنیم جدا می‌کنیم و Data structure ورودی و خروجی‌مان را تعیین می‌کنیم. حال وقتی که Fake Repository را فراخوانی می‌کنیم می‌توانیم بدون نیاز به سرویس اصلی، کدمان را اجرا و تست کنیم.چالش‌های اصلی ما در پیاده‌سازی معماری کلین– داکیومنت کردن کد و Rest Apiما برای داکیومنت کردن کدها به راحتی از ابزار sphinx استفاده کردیم. امّا برای داکیومنت کردن APIها چالش سخت‌تری پیش رو داشتیم. به دلیل این‌که دیگر از سریالایزرهای جنگو استفاده نمی‌کنیم دیگر نمی‌توانیم از ابزارهای آماده‌ای که برای داکیومنت کردن جنگو وجود دارد استفاده کنیم. پس باید دنبال راه حلی باشیم.ما برای سریالایز کردن و اعتبارسنجی ریکویست و ریسپانس‌ها از کتابخانه‌ای به نام marshmallow استفاده کردیم. این کتابخانه خیلی مشابه سریالایزر جنگو است و مزیّت مضاعفی که دارد این است که کتابخانه‌ی دیگری وجود دارد که می‌تواند از این سریالایزرها، خروجی openapi استخراج کند. خب تقریباً نصف کار انجام شد و حال کافی است اسکریپتی بنویسیم تا با کاوش در درون پوشه‌های مربوط، داکیومنت‌های مورد نیاز را کنار هم بگذارد و خروجی openapi را به طور خودکار بسازد.– مدیریت خطابه دلیل لایه لایه بودن معماری، مدیریت کردن ارورها باید به درستی مهندسی شود. برای مثال اگر اروری در داخلی ترین لایه وجود داشته باشد، باید به درستی و بدون هیچ مشکلی به بیرونی ترین لایه منتقل شود . برای انجام این وظیفه ما از ابزار Result استفاده کردیم. این کتابخانه از الگوی مدیریت ارورها از زبان Rust الهام گرفته است. و برای حفظ یکپارچگی ارورها باید کلاسی تعریف کنیم که تمام ارورها را از آن مشتق بگیریم. برای مثال ما دیتاکلاس DomainError را بعنوان پایه ی ارورهای معماری درنظر گرفته ایم و بقیه ی ارورها را از آن مشتق گرفته ایم.حال با استفاده از کتابخانه ریزالت ما این ارورها را از لایه های داخلی به لایه های بیرونی انتقال میدهیم.فرض کنید موجودیتی به نام Book داریم و برای اعتبارسنجی فیلدهای آن اینگونه نوشته ایم:موجودیت کتاب را با استفاده از تابع create_book_entity ایجاد می‌کنیم.این تابع را فرض کنید وجود دارد و کارش ساختن یک موجودیت از جنس کتاب است. خروجی این تابع از جنس Result است.اگر خروجی بازگردانده شده اروری داشته باشد آن را مدیریت میکنیم و مستقیم آن ارور را به لایه بیرونی تر هدایت میکنیم:حال فرض کنید تمام لایه ها اینگونه ارورها را مدیریت کنند، پس دیگر مشکلی با تعداد لایه‌های زیادی که احتمالاً وجود خواهد داشت نداریم و اگر اروری وجود داشته باشد با آن به‌راحتی برخورد می‌کنیم.– تست نویسیبه خاطر جداسازی از هرگونه سیستم‌های خارجی مثل دیتابیس و … ما امکان این را پیدا می‌کنیم که هرچیزی را بتوانیم تست کنیم، امّا پیاده‌سازی این کار همیشه به همین راحتی نیست. ما در داخل ریپازیتوری‌هایمان از ORM جنگو استفاده می‌کنیم، پیشتر دیدیم که ریپازیتوری پترن یک لایه ما را از سیستم خارجی جدا میکند و به تفکّر و ساختار داده‌ی مورد نظر خودمان با لایه‌های خارجی صحبت کنیم. در بالا من مفهومی به نام Fake Repository را معرفی کردم. یکم میخوام بیشتر در مورد این مفهوم حرف بزنم.در حقیقت اگر در ریپازیتوری نیاز داشته باشیم تا لیست کتاب‌هارا کامل دریافت کنیم این کار هم از طریق ریپازیتوری و هم از طریق فیک ریپازیتوری باید انجام شود و لیستی از کتاب هارا به ما دهد. تنها تفاوت این است که در ریپازیتوری اصلی دیتا از دیتابیس گرفته میشود ولی در فیک ریپازیتوری ما آرایه‌ای داریم که داخلش موجودیت‌هایی از جنس کتاب هست و اگر بخواهیم عمل create را انجام دهیم کافی است به داخل این آرایه یک موجودیت از جنس کتاب، append کنیم.خب تا اینجا خیلی ساده میتوانیم فیک ریپازیتوری خودمان را پیاده سازی کنیم. امّا مشکل زمانی پیدا می‌شود که پروژه به شدّت پیچیده است و کوئری‌های بسیار پیچیده‌ای داخل خود دارد. اگر بخواهیم متناظر هر ریپازیتوری و هر متد یکبار دیگر منطق موردنظر خودمان را با کارکردن با آرایه ها بنویسیم، یک دوباره کاری عظیمی انجام خواهد شد جدا از اینکه احتمال خطا هم خواهیم داشت. پس اینجا دنبال ابزاری دیگر بودیم تا بتوانیم به راحتی متد های orm جنگو را Mock کنیم و به لطف بزرگ بودن کامیونیتی پایتون و جنگو با این ابزار آشنا شدیم. با استفاده از این ابزار به راحتی میتوانیم فیک ریپازیتوری خودمان را مطابق با فیچرهای orm جنگو درست کنیم.اشتباه رایج پیاده‌سازی معماری کلین در زبان‌های Dynamicاگر کمی داخل منابع و مقالات موجود درمورد معماری کلین کاوش کرده باشید، متوجّه میشوید که اکثر منابع در زبان‌های Strong Type مانند جاوا و سی‌شارپ نوشته شده اند. امّا خیلی از دوستان را میبینم که وقتی می‌خواهند معماری را برای زبان‌های dynamic همانند پایتون و PHP پیاده سازی بکنند کاملا با آن مانند زبان‌های static رفتار می‌کنند، که این کاملا برای یک زبان dynamic اشتباه است.برای مثال با حجم انبوهی از interface ها و struct ها در پایتون روبه‌رو می‌شویم که واقعا نیازی به آن نیست. به عقیده من وقتی از زبان dynamic استفاده می‌کنیم پس باید از فلسفه و قدرت پشت زبان‌های dynamic به طور کامل بهره ببریم.جمع‌بندیدر این نوشته سعی کردم چرایی و چالش‌های پیاده سازی معماری کلین را مختصر توضیح دهم. آخرین توصیه من برای پیاده سازی معماری کلین این است که مفاهیم و قوانین پشت معماری را به طور کامل درک کنید. با توجّه به نیاز پروژه ممکن است ساختاری که می‌سازید شبیه مثال‌های داخل منابع و کتاب معماری کلین نباشد، تنها چیزی که مهم است رعایت قوانین وابستگی و استقلال از سیستم‌ها و Data Flow‌هاست.پیاده‌سازی معماری کلین نیاز به هزینه و زمان زیادی دارد. باید در برنامه‌ریزی کارها با دقّت زیادی به این مسئله توجّه کنید.این مطلب توسط محمدابوجعفری در بلاگ راهبردهای خلاق آرمان نوشته شده است.</description>
                <category>راهبردهای خلاق آرمان</category>
                <author>راهبردهای خلاق آرمان</author>
                <pubDate>Sun, 20 Feb 2022 12:46:22 +0330</pubDate>
            </item>
                    <item>
                <title>چندزبانه‌ کردن وب‌اپلیکیشن‌ها بدون درد و خونریزی</title>
                <link>https://virgool.io/@armansolutions/%DA%86%D9%86%D8%AF%D8%B2%D8%A8%D8%A7%D9%86%D9%87-%DA%A9%D8%B1%D8%AF%D9%86-%D9%88%D8%A8-%D8%A7%D9%BE%D9%84%DB%8C%DA%A9%DB%8C%D8%B4%D9%86-%D9%87%D8%A7-%D8%A8%D8%AF%D9%88%D9%86-%D8%AF%D8%B1%D8%AF-%D9%88-%D8%AE%D9%88%D9%86%D8%B1%DB%8C%D8%B2%DB%8C-uag0fj8vokqm</link>
                <description>بر خلاف چیزی که به نظر می‌رسد توسعه وب‌اپلیکیشن‌هایی که مشتری‌هایی از زبان‌ها و مناطق جغرافیایی مختلف دارد پیچیده است، چراکه بخش‌های زیادی از نرم‌افزار را درگیر می‌کند.علاوه بر تفاوت‌های زبانی، ما از اعداد، جهت نوشتاری و تقویم متفاوتی نسبت به بیشتر دنیا استفاده می‌کنیم که باعث می‌شود این پیچیدگی‌ها دوچندان باشد.در کنار این چالش‌های قابل پیش‌بینی، ما برای چندزبانه کردن نیوزباکس با چالش‌های بیشتری هم روبه‌رو شدیم، چون با کدبیس بسیار بزرگی مواجه بودیم که میراث تیم توسعه دیگری بود.در این نوشته، می‌خواهیم در کنار اشتراک تجربه برخورد با این چالش، در مورد راهکار‌هایی صحبت کنیم که چندزبانه‌ کردن وب‌اپلیکیشن‌ها را توسعه‌پذیر و ساده‌تر کند.چرا شیطان در جزئیات است؟همانطور که اشاره کردیم، از آن‌جایی که کدبیس میراث تیم دیگری بود و دانش کاملاً دقیقی از آن در تیم توسعه وجود نداشت، برای تخمین بررسی اوّلیه‌ای از کد انجام دادیم.با توجّه به وجود کتابخانه i18n در کد و جدا بودن متن‌ها در یک فایل به خصوص، به نظر رسید که بخشی از کار آماده است و کار راحتی پیش‌رو داریم.بنابراین با نگاه به بخش‌های موجود، کار باقی‌مانده را به چهار بخش تقسیم کردیم:۱. پیاده‌سازی تغییر زبان با استفاده از کتابخانه i18n۲. ترجمه متن‌ها برای زبان جدید۳. اصلاح فرمت تاریخ و اعداد۴. دوجهته کردن سایتبه نظر می‌رسید که انجام بخش اوّل و سوم ساده است. با توجّه به این‌که کتابخانه i18n در پروژه وجود داشت، حدس می‌زدیم زمان زیادی لازم نیست.ترجمه متن‌ها هم جز‌ء وظایف تیم فنی نبود.برای بخش آخر هم با یک نگاه کلّی به CSSهای پروژه فکر می‌کردیم که این بخش کار زیادتری دارد ولی تصوّر این را نداشتیم که با چالش زیادی رو‌به‌رو شویم. با توجّه به این ذهنیّت کار را شروع کردیم امّا داستان به همین سادگی که فکر می‌کردیم پیش نرفت.تخمین ما برای این قسمت دو روز کاری بود که در عمل حدود دو هفته طول کشید!علاوه بر صرف زمان زیادتر، بخش‌های زیادی از کد تغییر کرد. تغییرات بسیار زیاد باعث بهم‌ریختگی و ایجاد باگ‌های جدید شد که پیدا کردن و رفع آن‌ها نیز زمان‌بر بود. این بدترین بخش کار بود ولی مشکل فقط به همین‌جا ختم نمی‌شد.متوجّه شدیم حتّی ترجمه متن‌ها هم که کار تیم ما نبود، به خوبی پیش نمی‌رود. باید چندین هزار جمله و عبارت ترجمه می‌شد. ویرایش ترجمه‌ها در یک فایل چندهزار خطی قابل تقسیم به نفرات بیشتری نبود و برای پیشگیری از دوگانگی‌ها کل کار به یک نفر سپرده شده بود.بخش‌های مختلف چندزبانه کردنبه شکل کلّی، چندزبانه کردن یک وب‌اپلیکیشن را می‌توانیم به سه بخش «سازمان‌دهی متن‌ها»، «قالب‌بندی اعداد، تاریخ و نوشته‌ها» و «استایل» تقسیم‌بندی کنیم. در ادامه به بررسی هر بخش و نکاتی که اگر در پروژه رعایت شده بود می‌توانستیم سریع‌تر و بهتر کار را به اتمام برسانیم می‌پردازیم.۱. سازمان‌دهی متن‌هابرای سازماندهی متن‌ها در زبان‌های مختلف، ابزارها و کتابخانه‌های زیادی وجود دارد که کارهای مربوط به چندزبانه‌سازی را انجام می‌دهد. با توجّه به چهارچوب توسعه‌ای که پروژه شما از آن استفاده می‌کند، می‌توانید ابزار مناسب را انتخاب کنید.البته این ابزارها علاوه بر سازمان‌دهی متن‌ها، کارهای دیگری مرتبط با چندزبانه کردن انجام می‌دهند که معمولاً این کارها توسط شئ intl زبان جاوااسکریت قابل پیاده‌سازی است (در عنوان بعدی توضیح داده شده است).چند فایل به جای یک فایلدر پروژه‌های بزرگ بهتر است که فایل متن‌ها را به چند فایل بشکنید. اساس این تقسیم‌بندی می‌تواند بر مبنای بخش‌های مختلف منطق کسب و کار، یا بر اساس کامپوننت‌های اصلی، یا به هر شکلی که ترجیح می‌دهید باشد.این جداسازی علاوه بر این که باعث می‌شود که در یک فایل با چندین هزار خط دنبال چیزها نگردید، کمک می‌کند هنگام توسعه یا پیاده‌سازی زبان جدید بتوانید فرایند ترجمه را به شکل موازی به چندین نفر بسپارید.جلوگیری از استفاده از متن بدون نشانه‌گذاری در کامپوننت‌هابودن متن‌هایی در بخش‌هایی از کد که با استفاده از کتابخانه‌های سازمان‌دهی متن مشخص نشده باشند، بعداً شما را دچار دردسر خواهد کرد و باید زمان زیادی را دنبال این متن‌ها بگردید.حین توسعه می‌توان با فرایند مرور دقیق Merge Request‌ها یا با استفاده از linter‌هایی (مثل eslint-plugin-i18next) به شکل خودکار جلوی اضافه شدن متن بدون نشانه‌گذاری را گرفت.راه‌کارهای ترجمه پیوستهاگر تعداد جمله‌ها و متن‌های شما زیاد است، یا قرار است ترجمه‌ها توسط مترجمین حرفه‌ای یا مشارکت‌ کننده‌های داوطلب تغییرات زیادی داشته باشند، می‌توانید ابزارهای ترجمه پیوسته‌ای مثل Mojito را در اختیار آن‌ها قرار دهید.۲. قالب‌بندی تاریخ، اعداد، و نوشته‌هابرای انجام این کار می‌توانید از شئ intl استفاده کنید که به شکل پیش‌فرض در خود جاوااسکریپت وجود دارد و نیاز به ابزارهای شخص ثالث را رفع می‌کند. این شئ constructorهای زیادی دارد که در اینجا به دو مورد پرکاربرد آن اشاره می‌کنیم. سایر امکانات آن را می‌توانید از مستندات MDN مشاهده کنید.Intl.NumberFormatپرکاربردترین کانستراکتور intl که می‌توانید برای قالب‌بندی اعداد، واحدها و قیمت استفاده کنید. مثلاً:let amount = 3500;

console.log(new Intl.NumberFormat(&#039;fa&#039;).format(amount));
// →۳٬۵۰۰ if in fa locale

new Intl.NumberFormat(&#039;en-US&#039;, {style: &#039;percent&#039;}).format(amount);
// → &#039;350,000%&#039;

new Intl.NumberFormat(&#039;fa&#039;, {
  style: &#039;currency&#039;,
  currency: &#039;IRR&#039;,
  currencySign: &#039;accounting&#039;,
  signDisplay: &#039;always&#039;
}).format(3500)
// &amp;quot‎+‎ریال ۳٬۵۰۰&amp;quotIntl.DateTimeFormatاز این Constructor برای قالب‌بندی تاریخ استفاده می‌شود که با توجّه به زبان و گزینه‌هایی که در ورودی می‌گیرد تاریخ و زمان را نمایش می‌دهد.const date = new Date();

// قالب بندی پیش‌فرض در زبان فارسی
console.log(new Intl.DateTimeFormat(&#039;fa&#039;).format(date));
// Expected output: &amp;quot۱۴۰۰/۹/۱۱&amp;quotبرای قالب‌بندی تاریخ و زمان کتابخانه Moment.js هم ابزارهای خوبی را فراهم کرده است. پروژه ما از ابتدا با moment.js پیاده شده بود، بنابراین برای حفظ سرعت توسعه تغییری در این قسمت ایجاد نکردیم.در تصویر زیر پشتیبانی مرورگرهای مختلف از intl را مشاهده می‌کنید. اگر نگران نسخه‌های خیلی قدیمی نباشید، پشیبانی تقریباٌ کاملی از مرورگرها داریم.پشتیبانی مرورگرهای مختلف از Internationalization API ۳. استایل‌هادر فرایند چندزبانه کردن، CSS‌ها بیشترین جزئیات را در بین بخش‌های مختلف دارد و علی رغم اهمیّت آن، معمولاً توجّه زیادی به آن نمی‌شود. طبق تجربه‌ای که ما داشتیم اگر یکسری از نکات در کد مد نظر قرار می‌گرفت، فرایند توسعه خیلی سریع‌تر پیش می‌رفت. جدا از سرعت توسعه، اصلاح CSS‌ها مخصوصاً وقتی که با یک پروژه بزرگ سر و کار داشته باشیم کاری خسته‌کننده و فرسایشی است.در ادامه به نکاتی اشاره خواهیم کرد که بهتر است در توسعه وب‌اپلکیشن رعایت شوند تا چندزبانه کردن بدون درد باشد.استفاده از Logical Properties و Logical Values در CSSLogical Properties و Logical Values این امکان را فراهم می‌کند که به جای استفاده از جهت‌های فیزیکی در طراحی layout، از جهت‌های منطقی استفاده کنیم. به عنوان مثال فرض کنید یک پاراگراف داریم که می‌خواهیم محتوای آن در خلاف جهتِ طبیعی آن زبان باشد، یعنی برای انگلیسی در سمت راست و برای فارسی در سمت چپ قرار گیرد. (در زبان انگلیسی direction: ltr و در فارسی از direction: rtl استفاده کرده ایم)، پس باید چنین کاری انجام دهیم:&lt;article&gt;
  &lt;p class=&amp;quotopposite&amp;quot&gt;
    Lorem ipsum dolor sit amis ..
  &lt;/p&gt;
&lt;/article&gt;و در فایل CSS :.opposite {
  text-align: right;
}برای نسخه RTL باید استایل این کلاس را به این شکل بازنویسی کنیم:html[dir=&amp;quotrtl&amp;quot] .opposite {
  text-align : left;
}این کار باعث می‌شود که مجبور باشیم برای نسخه‌های RTL و LTR دو استایل متفاوت تعریف کنیم.برای حل این مشکل Logical Properties و Logical Values ساخته شده‌اند و می‌توانیم به جای استفاده از جهت‌ها، از مقادیر منطقی استفاده کنیم.به زبان ساده در المان‌های LTR مقدار left به معنی آغاز یا start آن المان است در حالی که در المان RTL، مقدار right به معنی start است.بنابراین به جای هر آنچه قبلا نوشته بودیم می‌توانیم از Logical Values استفاده کنیم:.opposite {
   text-align: end
}چیزی که در بالا دیدیم کاربرد Logical Values یا مقادیر منطقی بود.حالا ببینیم Logical Propertyها چه چیزی است. ویژگی‌های منطقی، ویژگی‌های جدیدی هستند که با همین ایده استفاده از جهت‌های منطقی پیاده‌سازی شده‌اند و بر اساس جهت چینش المان‌ها کار می‌کنند. برای مثال margin را ببینیم.قبلا برای اینکه یک فضای خالی در شروع یک المان ایجاد کنیم، در حالت LTR:p {
    margin-left: 20px
}و حالا در نسخه RTL به margin‌ای در جهت مخالف نیاز داریم، به علاوه اینکه باید مقدار margin-left را هم reset کنیم.p {
  margin-left: 0;
  margin-right: 20px;
}ولی با استفاده از Logical Propertyها می‌توانیم به سادگی پیاده‌سازی را به این شکل تغییر دهیم:p {
  margin-inline-start: 20px;
}وقتی قسمت -inline-start به margin اضافه می‌شود این margin به ابتدای المان در جهت افقی اعمال می‌شود که در RTL معادل margin-right و در LTR معادل margin-left است.به همین شکل برای جهت مخالف هم می‌توانیم از پسوند inline-end- استفاده کنیم. همچنین برای جهت های بالا و پایین هم پسوند‌های block-start- و block-end- را داریم که می‌توانیم به propertyهای جهت‌دار اضافه کنیم.Logical Properties PADDING و MARGINهای منطقیحالا که با Logical Propertyها آشنا شدیم می‌دانیم که به جای padding-left و padding-right بهتر است از padding-inline-start و padding-inline-end و به جای margin-right و margin-left از margin-inline-start و margin-inline-end استفاده کنیم.وقتی اپ شما راست‌چین است یعنی المان‌ها از راست به چپ چیده می شوند پس margin-inline-start به معنی margin-right است و در صورت چپ‌چین شدن که المان‌ها از چپ به راست چیده می‌شوند margin-inline-star به معنی margin-left است و دیگر نیازی نیست این استایل‌ها را برای جهت‌‌های مختلف بازنویسی کنید. در جدول زیر Propertyها و Logical Propertyهای مترادف آنها را برای margin می‌بینید:Propertyهای margin و معادل منطقی آن‌ها و برای padding هم به شکل مشابه داریم:Propertyهای padding و معادل منطقی آن‌ها همچنین می‌توانیم با استفاده از کلمه کلیدی logical به شکل کوتاه‌شده از این مقادیر استفاده کنیم:selector {
  margin: logical 10px 20px 30px 40px;
}LOGICAL POSITIONING PROPERTIESبالاتر دیدیم که نام propertyها با پسوندهایی معنی‌دار اصلاح می‌شوند ولی در position‌ها نام propertyها کامل تغییر می‌کند:`selector {
  position: absolute;
  inset-block-start: 0;  /* فاصله از بالا */
  inset-block-end: 0;    /* فاصله از پایین */
  inset-inline-start: 0; /* فاصله از چپ در چپ‌چین و فاصله از راست در راست‌چین */
  inset-inline-end: 0;   /* فاصله از راست در چپ‌چین و فاصله از چپ در راست‌چین  */
}به شکل ساده، برای حالت کوتاه شده هم می‌توانیم از inset استفاده کنیم:selector {
  position: absolute;
  inset: logical 10px 20px 30px 40px;
}که این کد معادل مقادیر زیر است:selector {
  position: absolute;
  inset-block-start: 10px;
  inset-inline-start: 20px;
  inset-block-end: 30px;
  inset-inline-end: 40px;
}LOGICAL BORDER PROPERTIESویژگی border هم با استفاده از پسوندهای -inline-start و -block-start به ویژگی‌های منطقی تبدیل می‌شوند:FLOATاگر هنوز برای چیدن افقی المان‌ها از float استفاده می‌کنید بهتر است فراموشش کنید. سعی کنید flex را جایگزین کنید تا دیگر مجبور نباشید برای جهت‌های مختلف استایل‌ها را بازنویسی کنید.پشتیبانی مرورگرها از LOGICAL PROPERTIESهمان‌طور که در شکل می‌بینید مرورگر IE از ویژگی‌های منطقی پشتیبانی نمی‌کند. مرورگر Chrome در نسخه‌های ۴ تا ۶۸ با پیشوند -webkit-، و مرورگر Firefox در نسخه‌های ۳ تا ۴۰ با پیشوند-moz- از برخی از Logical Propertyها پشتبانی می‌کنند (برای جزئیات بیشتر سایت caniuse را ببینید.). در Chrome از نسخه ۸۹ و در Firefox از نسخه ۴۱ به شکل کامل پشتیبانی می‌شود.ساده امّا نجات‌بخشمواردی که اشاره کردیم، کارهای ساده‌ای هستند که اگر از ابتدا مورد توجه قرار بگیرند توسعه‌پذیری را به طور چشم‌گیری بهبود می‌بخشند. بنابراین اگر قصد پیاده‌سازی یک اپلیکیشن چندزبانه را دارید یا در چشم‌انداز پروژه چندزبانه شدن وجود دارد از ابتدا این موارد را در نظر بگیرید.در این نوشته، سعی کردیم براساس تجربه تبدیل یک پروژه فرانت‌اند فارسی به یک پروژه چندزبانه، به مواردی که به نظرمان مهم‌تر آمد بپردازیم. تجربه شما در این زمینه چیست؟ آیا موارد دیگری هم به ذهن شما می‌رسد که در حین تجربه‌های مشابه با آن‌ها برخورد کرده باشید؟ اگر تجربه مشابهی دارید یا نکات دیگری به ذهنتان می‌رسد خوشحال می‌شویم که دیدگاه خود را به اشتراک بگذارید.این مطلب توسط زهرا کبیری در بلاگ راهبردهای خلاق آرمان نوشته شده است.</description>
                <category>راهبردهای خلاق آرمان</category>
                <author>راهبردهای خلاق آرمان</author>
                <pubDate>Sun, 13 Feb 2022 15:21:16 +0330</pubDate>
            </item>
                    <item>
                <title>درد و دل سرویس‌ها را چه کسی گوش می‌کند؟</title>
                <link>https://virgool.io/@armansolutions/%D8%AF%D8%B1%D8%AF-%D9%88-%D8%AF%D9%84-%D8%B3%D8%B1%D9%88%DB%8C%D8%B3-%D9%87%D8%A7-%D8%B1%D8%A7-%DA%86%D9%87-%DA%A9%D8%B3%DB%8C-%DA%AF%D9%88%D8%B4-%D9%85%DB%8C-%DA%A9%D9%86%D8%AF-aqwz9mwu4i11</link>
                <description>اگر شما ارائه‌دهنده‌ی سرویسی باشید، احتمالاً مانیتورینگ به گوش‌تان خورده‌است. در ارائه‌ی یک سرویس، مثل یک سایت، فقط توسعه‌ی محصول و بالابردن آن روی سرورها نیست که اهمیت دارد، بلکه مراقبت از آن و همچنین بررسی عملکرد و یافتن ایرادات آن نیز بسیار مهم است. تا در صورت بروز مشکل، حتما اقدامات لازم انجام شود.پارامترهایی که باید بررسی شوند، آن‌قدر زیادند که مراقبت از همه‌ی آن‌ها کاری سخت و حتی غیرممکن  است.  پس نیاز به فرایند‌هایی خودکار برای انجام این‌کارها داریم. فرایند‌هایی که به آن‌ها «مانیتورینگ» گفته می‌شود. در این نوشته قصد داریم به مفاهیم کلی مانیتورینگ بپردازیم و سپس یک سناریوی ساده مانیتورینگ را با استفاده‌ از ابزارهای مطرح، مثل پرومتئوس، گرافانا و … پیاده کنیم.مفاهیم و اجزا اصلی مانیتورینگدر مانیتورینگ ابتدایی‌ترین گام، دریافت داده‌ها از ابزارها و سرویس‌هایی‌ست که می‌خواهیم بر آن‌ها نظارت کنیم. این داده‌ها می‌توانند میزان RAM  پر شده‌ی سرورها، درصد CPU اشغال شده‌ی سرور، تعداد کوئری‌های موفق ۱۰ دقیقه‌ی گذشته‌ی دیتابیس، میزان رم مصرفی هر کدام از سرویس‌ها (اعم از بک‌اند، دیتابیس، کش و …..)، یا میانگین زمان مورد نیاز برای پاسخگویی بک‌اند به درخواست‌ها باشد.به این داده‌ها که به روش‌ها و با ابزارهای متفاوتی (بسته به نوع سرویسی که می‌خواهیم داده‌های آن را دریافت کنیم) قابل دریافت هستند، سنجه (metric) گفته می‌شود. متریک‌ها به صورت key-value هستند. کلید نشان‌دهنده‌ی این است که این داده چه چیزی را نشان می‌دهد و مقدار نشان‌دهنده‌ی عدد مربوط به متغیّر در لحظه‌ی دریافت داده‌ها است.همانطور که پیش‌تر اشاره شد، گرفتن داده‌ها برای سرویس‌های مختلف اندکی متفاوت است.روال کلی این است که با استفاده از سرویس‌هایی، داده‌های موردنیاز را دریافت کنیم و سپس در یک جا تجمیع کنیم. به این سرویس‌ها که وظیفه‌ی دریافت متریک‌ها از Backend, Database و ….. را دارند، اکسپورتر (exporter) گفته می‌شود. به طور مثال، خروجی یک اکسپورتر به شکل زیر خواهد بود:خط‌هایی که قبل از آن‌ها علامت # آمده‌است، کامنت‌هایی هستند که توضیحاتی در مورد متریک می‌دهند.برای ابزارهای پرکاربرد مثل دیتابیس‌ها، سرویس‌های کش و حتی فریم‌ورک‌های بک‌اندی، اکسپورترهای آماده وجود دارند. فهرستی از این اکسپورترها از طریق این لینک قابل مشاهده و دسترسی هستند.بعد از این که برای سرویس‌های مختلف، با استفاده از اکسپورتر مخصوص آن‌ها، متریک‌ها ساخته شدند، باید همه‌‌ی آن‌ها در جایی تجمیع شوند. Prometheus وظیفه‌ی این کار را بر عهده دارد.پرومتئوسپرومتئوس(Prometheus)  یک جعبه ابزار متن‌باز نظارت و هشدار است که در ابتدا در SoundCloud ساخته شد. پرومتئوس با استفاده از یک کانفیگ‌فایل، آدرس اکسپورترها را می‌فهمد و از آن‌ها متریک‌ها را دریافت می‌کند. همچنین پرومتئوس با استفاده از یک زبان به نام PromQuery، امکان اعمال فرمول روی متریک‌ها را می‌دهد. مثلا می‌توان یک متریک را در متریک دیگری ضرب کرد، از یک متریک در یک بازه‌ی زمانی میانگین گرفت و یا مشتق یک متریک (روی یک بازه‌ی زمانی) را محاسبه کرد. در نهایت، با استفاده از این تغییرات، می‌توان به مقادیری رسید که قرار است آن‌ها را مانیتور کنیم. یک نمونه از فایل کانفیگ پرومتئوس در پایین قابل مشاهده است:در این فایل کانفیگ، یک مسیر به عنوان مسیر فایل‌های rule تعریف شده‌است. این فایل‌ها، برای تعریف alertها هستند. به این مسئله جلوتر می‌پردازیم. بعد از آن، یک node_exporter تعریف شده و آدرس آن در قسمت targets مشخص شده‌است. توجه‌کنید که عموما اکسپورترها روی آدرس /metrics متریک‌ها را می‌دهند. پرومتئوس به طور پیش‌فرض به این آدرس درخواست ارسال می‌کند. در قسمت بعد فایل کانفیگ هم یک alertmanager مشخص شده که وظیفه‌ی مدیریت و ارسال الرت‌ها در کانال‌های مختلف را بر عهده دارد.پرومتئوس همچنین یک پنل مدیریتی ساده را ارائه می‌کند که می‌توان برخی اطلاعات جزئی را در آن مشاهده کرد. البته قابلیت رسم نمودار  به طور ساده را نیز دارد که معمولا به خاطر سادگی و دلایل دیگر، برای این کار از پرومتئوس استفاده نمی‌شود. مگر برای تست‌های کوچک روی محیط‌های غیر پروداکشن. در پنل مدیریتی پرومتئوس، می‌توان اکسپورترهایی که پرومتئوس از آن‌ها متریک می‌گیرد را مشاهده کرد:همانطور که در تصویر مشخص است، اکسپورتر دوم (cadvisor)، در دسترس نیست و به هر دلیلی، پرومتئوس قادر به دریافت متریک‌ها از آن نیست.حالا که همه‌ی متریک‌ها در یک جا تجمیع شده‌اند، می‌توانیم روی آن‌ها کارهای متفاوتی انجام دهیم. دو مورد که در این نوشته می‌خواهیم به آن‌ها بپردازیم رسم نمودار و ایجاد الرت و ارسال آن‌ها در کانال‌های مختلف است.رسم نمودار، گرافانا بیدار شو!همانطور که پیش‌تر اشاره شد، پرومتئوس هم امکان ساخت گراف را دارد، اما امکانات آن کافی نیستند. این‌جاست که گرافانا به میدان می‌آید. گرافانا ابزاری‌ست که با یک پنل گرافیکی که کار با آن هم چندان سخت نیست، امکان ساخت انواع و اقسام چارت‌ها را به ما می‌دهد. البته قابلیت‌های آن در این خلاصه نمی‌شوند، اما سایر امکانات آن در حوصله‌ی این نوشته نیست.ساخت نمودار در گرافانا ساده‌است. ابتدا در بخش تنظیمات، آدرس پرومتئوس را به گرافانا می‌دهیم، سپس یک داشبورد می‌سازیم و نهایتا هر بلایی که می‌خواهیم سر متریک‌ها می‌آوریم تا نمودارهای مختلفی تولید کنیم. در گرافانا هم داشبوردهای آماده مختلفی توسط اشخاص مختلف ساخته شده و در دسترس عموم قرار گرفته‌است. به این صورت شما می‌توانید با import کردن یکی از این داشبوردها و اعمال تغییرات مورد نظر خود روی آن‌، به داشبورد ایده‌آل خود برسید. تصویر یک داشبورد که برای مانیتور یک بک‌اند جنگویی ایجاد شده در زیر قابل مشاهده‌است:الرتینگ، همیشه خبردار باش!یکی از اصول و اهداف مهم مانیتورینگ، این است که همیشه قبل از وقوع فاجعه، از آن خبردار شویم و اقدامات لازم را انجام دهیم. به طور مثال، اگر قرار است با روند فعلی، هفته‌ی دیگر دیسک یکی از سرورها پر شود، یک هفته زودتر خبردار شویم تا اقدامات لازم را انجام دهیم. یا قبل از این که رم سرور کاملا پر شود و عملا از کار بی‌افتد، متوجه بروز مشکل شویم و یا سرویسی که مموری لیک دارد را پیدا کنیم. همه‌ی این‌ها و دلایل متعدد دیگر، لزوم یک سیستم الرتینگ مناسب را نشان می‌دهند.پرومتئوس با استفاده از زبان مخصوص خود، یعنی PromeQuery، امکان اعمال فرمول‌هایی روی متریک‌ها را می‌دهد. پس می‌توان با استفاده از این فرمول‌ها، مقادیری را پیش‌بینی و روند تغییر یک متریک را بررسی کرد.در قسمت پایین، می‌توان ایجاد یک الرت را مشاهده کرد. در این الرت، تعداد کانکشن‌هایی که به دیتابیس Postgresزده شده‌است را بررسی کرده‌ایم. اگر این تعداد از ۸۰ درصد مقدار حداکثر کانکشن‌های ممکن برای پوستگرس بیشتر باشد، یک الرت تولید و یا اصطلاحا fire می‌شود.الرت‌های فایر شده، به الرت‌منیجر سپرده می‌شوند تا در مورد آن‌ها تصمیم‌گیری شود. الرت‌منیجر، وظیفه‌ی ارسال، گروه‌بندی و روتینگ الرت‌ها را بر عهده دارد.یک نمونه از کانفیگ الرت‌منیجر:این الرت‌منیجر، الرت‌ها را برای آدرس که مشخص شده، یعنی پورت ۸۲۸۲ روی لوکال‌هاست ارسال می‌کند. می‌توان وب‌هوک‌های مختلفی برای الرت‌منیجر مشخص کرد. به طور مثال، این وب‌هوک می‌تواند مربوط به یک بات تلگرام باشد که الرت‌ها را روی تلگرام برای شما ارسال می‌کند. یک نمونه از الرت‌های ارسالی روی تلگرام:این الرت نشان می‌دهد که سرویس cadvisor در دسترس نیست. (همانطور که در تصویر اول از تارگت‌های پرومتئوس مشاهده کردیم).فرمت پیامی که ارسال می‌شود نیز قابل تنظیم است. یکی از بات‌های تلگرام که برای اتصال به الرت‌منیجر قابل استفاده‌اند، از صفحه‌ی گیت‌هاب این بات تلگرام (alertmanager bot) قابل دسترسی‌ست. البته می‌توان الرت‌ها را روی کانال‌های متفاوتی فرستاد. فقط به یک وب‌هوک نیاز است که در تنظیمات الرت‌منیجر قرار داده‌شود. دیسکورد، اسلک و ابزارهای مشابه، همگی امکان ایجاد یک وب‌هوک برای ارسال پیام روی آن‌ها را دارند.پیش‌تر گفتیم که گرافانا نیز امکان ایجاد الرت را به ما می‌دهد. الرت‌ها در گرافانا به طور گرافیکی قابل ساخت هستند که در مواقعی می‌توان از این قابلیت‌ آن‌ها نیز استفاده کرد.این مطلب توسط محمدحسین بهمنی در بلاگ راهبردهای خلاق آرمان نوشته شده است.</description>
                <category>راهبردهای خلاق آرمان</category>
                <author>راهبردهای خلاق آرمان</author>
                <pubDate>Sat, 12 Feb 2022 14:21:37 +0330</pubDate>
            </item>
                    <item>
                <title>ما در مهم‌ترین روز سینمای ایران از دسترس خارج شدیم</title>
                <link>https://virgool.io/@armansolutions/%D9%85%D8%A7-%D8%AF%D8%B1-%D9%85%D9%87%D9%85-%D8%AA%D8%B1%DB%8C%D9%86-%D8%B1%D9%88%D8%B2-%D8%B3%DB%8C%D9%86%D9%85%D8%A7%DB%8C-%D8%A7%DB%8C%D8%B1%D8%A7%D9%86-%D8%A7%D8%B2-%D8%AF%D8%B3%D8%AA%D8%B1%D8%B3-%D8%AE%D8%A7%D8%B1%D8%AC-%D8%B4%D8%AF%DB%8C%D9%85-hrluqzn8mnxj</link>
                <description>جشنواره‌ی فجر مهم‌ترین رویداد سینمای داخلی است. آن هم نه فقط برای فیلم‌بین‌ها و فیلم‌سازها، بلکه برای سینماها و بلیت‌فروش‌ها هم رویداد بسیار مهمی است.جشنواه‌ی فجر سال ۱۳۹۹ از بسیاری از جهات عجیب‌ترین جشنواره‌ی فجری بود که در این سال‌ها برگزار شد. از نامشخّص بودن وضعیّت برگزاری آن تا دو هفته مانده به زمان جشنواره تا فروش تمام الکترونیکی بلیت‌های آن. فروشی که در چندساعت اوّل عملاً در کار نبود، چون تمام بلیت فروش‌ها از دسترس خارج شدند.این چندساعت عدم دسترس را بگذارید کنار تعطیلی تقریباً یک‌ساله‌ی سینماها و نیاز شدید تمام بخش‌های سینما به جریان نقدینگی‌ای که جشنواره‌ی فجر قراربود ایجاد کند. اینطوری شاید متوجّه اهمّیّت این خاموشی چندساعته بشوید.در این نوشته می‌خواهیم دلیل فنّی از دسترس خارج‌شدن سینماتیکت را، به عنوان بزرگ‌ترین فروشنده‌ی بلیت، با هم ببینیم.جشنواره‌ای متفاوتاین جشنواره‌ی فجر با بقیه‌ی جشنواره‌ها فرقی مهم داشت. به خاطر شرایط کرونایی قرارشد که بلیت‌فروشی تنها به صورت اینترنتی انجام شود.مسئله این بود که تمام پایانه‌های فروش امسال برای اوّلین بار باید از طریق APIهای «سمفا»،‌ سامانه‌ی مدیریت فروش سازمان سینمایی، بلیت‌فروشی می‌کردند. و خب این سازمان هم به همه اطمینان داده بود که ما بررسی‌های لازم را انجام داده‌ایم و مطمئن هستیم که باری که هنگام شروع بلیت‌فروشی عمومی به روی سایت‌ها می‌آید برای ما مشکلی ایجاد نمی‌کند.در این جشنواره قرار بر این شد که دو روز زودتر از بلیت‌فروشی عمومی، بلیت‌فروشی برای افرادی که از طرف خود جشنواره‌ی فجر و سازمان‌های دیگر کد تخفیف دریافت کرده‌اند شروع شود و پس از آن فروش عمومی آغاز شود.فروش افراد خاص در آن دو روز انجام شد و به جز یک سری مشکلات کوچک در اعتبارسنجی کدها توسّط سمفا، مشکل دیگری وجود نداشت.پنج دقیقه پیش از فاجعهساعت ۱۳:۵۵ روز شنبه ۱۱ بهمن ۱۳۹۹. تنها پنج دقیقه تا شروع فروش عمومی جشنواره‌ی فجر باقی مانده بود. هر دقیقه به تعداد افراد آنلاین روی سینماتیکت هزارنفر افزوده می‌شد. همه‌چیز خوب پیش می‌رفت و تمام مانیتورها وضعیّت سرورها را خوب نمایش می‌دادند.نه مشکلی در سرعت بارگذاری سایت وجود داشت و نه مشکلی در کارکردهای مختلف آن. همه خوشحال و منتظر ساعاتی پرفروش بودند.ساعت ۱۴: و اینک آخرالزمانساعت به ۱۴ رسید و بلیت‌فروشی عمومی شروع شد. برای یکی دو دقیقه‌ی اوّل همه‌چیز خوب بود. تا اینکه پیام‌های پر از نگرانی تیم‌های بازاریابی و مدیریت شروع شد: سایت باز نمی‌شود.تا بررسی سایت را شروع کردیم خبر آمد که دو سامانه‌ی فروش دیگر هم از دسترس خارج شده‌اند. این خودش قوّت قلب بود.چیزی که عجیب بود این بود که هنوز وضعیّتی که در سیستم مانیتورینگ از سرورها می‌دیدیم عادی بود. یعنی منطقاً نباید هیچ مشکلی وجود می‌داشت.حالا که رقبا هم غیر قابل دسترس بودند و فشار و استرس کم‌تر شده بود، یک بار دیگر پیام‌های خطا را بررسی کردیم.قضیه عجیب‌تر شد. پیام‌های خطای رنج ۵۰۰ مستقیماً از طرف Nginx صادر می‌شدند. اصلاً درخواست‌ها به سرورهای ما نمی‌رسید.از آن‌جایی که تمام Nginxها در پاسخ تمامی درخواست‌ها خطای ۵۰۳ برمی‌گرداندند، تمامی عملکردهای سایت از کار افتاده بودند و افراد با ورود به سینماتیکت تنها یک صفحه‌ی خالی را مشاهده می‌کردند. چون که وب‌اپلیکیشن ما امکان دریافت هیچ داده‌ای را از سرورها نداشت.خبر جدیدی از تیم‌های دیگر به ما رسید: سایت‌های دیگر سامانه‌های فروش باز می‌شدند. ولی همچنان امکان فروش نداشتند.اوضاع دوباره برای تیم‌های فنّی و زیرساخت پرفشار شده بود. چون تمامی وبسایت ما غیرقابل استفاده بود. برخلاف دیگران که تنها بخش خریدشان از کار افتاده بود.ما برای حدود ۵۰ دقیقه هیچ فروشی نداشتیم.چرا Nginx دیگر پاسخگو نیست؟اینکه هیچ سامانه‌ی فروشی امکان خرید نداشت ما را تقریباً متقاعد کرد که مشکل به خاطر پایین‌آمدن سرویس‌های سمفا است.چیزی که با بررسی لاگ‌ها تأیید شد. امّا سؤال اصلی این بود که چرا تمام سایت از دسترس خارج شده؟با کمی بررسی بیشتر علّت مشخّص شد.تمام سرورهای ما، و در نتیجه تمام Nginxها، برای گرفتن پلان سانس‌ها، لیست سانس‌ها، رزرو صندلی‌ها و تکمیل سفارشات به سمفا درخواست ارسال می‌کنند.حالا که هیچ‌کدام از APIهای سمفا پاسخ نمی‌دهند، سوکت‌های ما به سرورهای سمفا باز می‌مانند و از آن‌جایی که تعداد درخواست‌ها بسیار زیاد است، تمام سوکت‌های تمام Nginxها پر شده اند.در نتیجه به صورت خودکار هنگامی که یک درخواست به یک Nginx می‌رسد، خود آن Nginx به صورت خودکار با یک خطای ۵۰۳ آب پاکی را روی دستان فرستنده می‌ریزد.چرا دیگر امکان ساخت سوکت جدید وجود نداشت؟اول از همه ببنیم که سوکت چیست. سوکت درگاهی است که ارسال و دریافت داده‌ها از طریق آن انجام می‌شود. در واقع، سوکت یک ساختار نرم‌افزاری است که به یک پردازه تعلق دارد. در سیستم‌عامل‌های لینوکسی، مثل سیستم‌عاملی که ما روی ماشین‌هایمان از آن استفاده می‌کنیم، هر سوکت در واقع یک file descriptor است. همان‌طور که می‌دانید، ما هم تعداد محدودی file descriptor را می‌توانیم به صورت هم‌زمان استفاده کنیم.برای تغییر این محدودیّت‌ها باید محدودیّت سخت تعداد فایل‌های باز را در سطح سیستم‌عامل تغییر بدهیم. پس از آن محدودیّت نرم آن را هم می‌توان از طریق سیستم‌عامل یا خود تنظیمات Nginx تغییر داد.اگر می‌خواهید از میزان این محدودیّت روی سیستم‌عامل خودتان با خبر شوید، می‌توانید از دستور ulimit استفاده کنید.مثلاً محدودیّت‌های پیش‌فرض ابونتو این است:با اینکه ما محدودیّت تعداد سوکت‌ها را با توجّه به نیازمان به صورتی منطقی تنظیم کرده بودیم، ولی از آن‌جایی که زمان زیادی طول می‌کشید تا اتّصال‌های TCP/IP باز، بسته شوند، تمام ماشین‌ها به سقف ظرفیّت تعریف‌شده رسیده بوند.یعنی هنگامی که درخواست جدیدی به Nginx می‌رسید، از آن‌جایی که دیگر هیچ file descriptor آزادی وجود نداشت، پذیرش درخواست هم امکان‌پذیر نبود و به صورت خودکار یک پیام ۵۰۳ به فرستنده‌ی درخواست داده می‌شد.تلاش اوّل برای رفع موقّت خطااوّلین راه حل برای رفع موقّت مشکل، کاهش زمان timeout درخواست‌هایی بود که به سمفا ارسال می‌کردیم.هم‌زمان با بررسی‌های تیم زیرساخت، تیم فنّی میزان timeout را ۳ثانیه کاهش داد. دلیل انتخاب این عدد این بود که باتوجّه به تأخیر پاسخگویی سمفا، بعید بود که با گذاشتن محدودیّتی کم‌تر از ۳ ثانیه هیچ‌کدام از درخواست‌ها هیچ پاسخی دریافت کنند.امید ما این بود که با کاهش این عدد، کمی وضعیّت سرویس‌دهی بهتر شود.بالأخره ساعت ۱۴:۵۸ ما اوّلین پاسخ‌ها را از APIهای سمفا گرفتیم. هرچند هنوز حجم درخواست‌هایی که منتظر پاسخ می‌ماندند بسیار زیاد بود. ولی شروع‌شدن فروش کمی از فشارها، چه از روی سرورها و چه از دوش تیم‌های فنّی، کم کرد.مسئله این بود که قراردادن timeout هم به تنهایی باعث رفع مشکل نشد و هنوز برای اکثر افراد سایت غیرقابل دسترس یا بسیار کند بود.بررسی راه حل های ممکناز آن‌جایی که هنوز کاربران زیادی دچار مشکل بودند، ما شروع به بررسی راه حل هایی کردیم که در دسترس‌مان بودند.اوّلین راه حل افزودن ماشین‌های جدید بود. مسئله این بود که آماده‌کردن ماشین جدید و اتّصالش به بخش‌های دیگر کار زمان‌بری بود.از طرفی مهم‌ترین ساعات مهم‌ترین رویداد سینمایی کشور در حال تلف‌شدن بودند و اکثر کاربران امکان خرید بلیت را نداشتند. بلیت‌هایی که پول آن‌ها برای سینماهایی که یک سال تعطیل بودند و سامانه‌های فروشی که اکثر سال چیزی نفروخته بودند حیاتی بود.راه حل دیگری که مطرح‌شد، نجات‌دادن بخش‌هایی از سینماتیکت بود که با سمفا ارتباطی نداشتند.ما به این نتیجه رسیدیم که بهترین کار این است که فعلاً تمام کاربران بدون مشکل بتوانند وارد سایت بشوند و تنها در صفحات خرید منتظر دریافت پاسخ از سمفا بمانند. اینطوری هم از نارضایتی آن‌ها کاسته می‌شد و هم احتمال اینکه منتظر عادی شدن شرایط سمفا بمانند افزایش می‌یافت. اینطوری کاربر کم‌تری از دست می‌رفت.ساعت ۱۷: حالا من را می‌بینیما دوباره به یک راه حل موقّت روی آوردیم. با تغییر تنظیمات HAProxy، درخواست‌هایی که به سمفا می‌رفتند را به دو ماشین محدود کردیم.اینطوری فشار سوکت‌های بازمانده را از باقی ماشین‌ها کم کردیم. حالا، در ساعت ۱۷، وبسایت سینماتیکت بدون مشکل برای تمام کاربران بالا بود.هرچند هنوز تعداد زیادی از کاربران موقع خرید دچار مشکل می‌شدند.ساعت ۱۹: وضعیّت سفیددو ساعت پس از راه حل موقّت ما، بالأخره تعداد درخواست‌ها آن‌قدری کم شد که سمفا به اکثر درخواست‌ها پاسخ درست می‌داد.حالا هم سایت پایدار بود و هم کاربران امکان خرید داشتند. هرچند اکثر آدم‌هایی که قصد خرید داشتند تا این موقع شب دیگر ناامید شده بودند.حالا ساعت‌ها پس از شروع بلیت‌فروشی عمومی، تازه شرایط فروش قابل قبول شده بود و فشارها هم از تیم‌های فنّی برداشته شد.حالا می‌شد یک نفس راحت کشید و در آرامش یک لیوان چای نوشید. وضعیّت سفید شده بود.تمام اشتباهات مادرست است. ما زیر فشار کم نیاورده بودیم و این سمفا بود که از دسترس خارج شده بود. ولی عدم امکان دسترسی به وبسایت ما به خاطر از دسترس خارج شدن یک سرویس خارجی اشتباه ما بود.اگر بخواهیم به صورت کلّی نگاه کنیم، ما دو اشتباه بزرگ داشتیم:مثبت‌اندیشی ساده‌انگارانهما تمام مدّت با یک مثبت‌اندیشی توأم با ساده‌انگاری با سرویس‌های شخص ثالث برخورد کردیم. همواره فرض ما در پیاده‌سازی بر این بوده که این سرویس‌ها در دسترس خواهند بود و اکثر اوقات پاسخ ما را می‌دهند.هرچند به خاطر فشار بازنویسی سینماتیکت برای ماه‌های ابتدایی نسخه‌ی جدید این مثبت‌اندیشی عاقلانه به نظر می‌رسید. ولی باید تا پیش از شروع جشنواره فجر بخش‌هایی از نرم‌افزار را که با این دید جلو رفته بودند تغییر می‌دادیم.درسی که از این موضوع گرفتیم این بود که همواره بنا را بر نادرستی سرویس‌های شخص ثالث بگذاریم. حتّی اگر deadline آن‌قدر نزدیک بود که نمی‌شد برای آن بدبینی چاره‌ای اندیشید.عدم پیاده‌سازی مکانیسم‌های جلوگیری از فاجعهدرست است که اینجا هم می‌توان همان بهانه‌ی فشار deadlineها را آورد، ولی ما به اشتباه اولویت پیاده‌سازی مکانیسم‌های جلوگیری از فاجعه را از کارهای دیگر پایین‌تر درنظر گرفته بودیم.درسی که ما گرفتیم این بود که مکانیسم جلوگیری از فاجعه درست به اندازه‌ی خود ویژگی‌ای که در حال پیاده‌سازی آن هستیم اهمّیّت دارد.در این مورد خاص، کافی بود که ما از الگوی مدارشکن (CircuitBreaker) استفاده می‌کردیم.این الگو به زبان ساده و به شکل خلاصه می‌گوید: اگر به یک مقصد خاص چندبار درخواست زدید و پاسخی نگرفتید یا پاسخی که گرفتید معتبر نبود، برای مدّتی به جای فرستادن درخواست جدید به همان مقصد، پیام خطا را به کسی که آن API را فراخوانی کرده برگردانید.اینطوری زیرساخت شما اسیر عملکرد نادرست شخص دیگری نمی‌شود و نرم‌افزار شما حتّی با وجود از کار افتادن سرویس‌های خارجی به زندگی‌اش ادامه می‌دهد.هنگام ساخت یک نرم‌افزار شما خیلی از چیزهای مهم را درنظر می‌گیرید. مفاهیم بزرگی که همان بزرگ بودن‌شان شما را گول می‌زند تا فکرکنید از باقی چیزها مهم‌تر هستند.اگر در این دام گرفتار شوید، چیزهای کوچکی که خیلی مهم هستند را فراموش می‌کنید. آن وقت می‌بینید سیستمی که تمام مشکلات بزرگ را به راحتی پشت سر می‌گذارد، به خاطر پیش پا افتاده‌ترین موضوعات زمین‌گیر می‌شود.یک ترک ریز در بدنه‌ی یک سد از چاله‌ای بزرگ وسط یک خیابان مهم‌تر است. نباید اجازه بدهیم که بزرگی و کوچکی انتزاعی مفاهیم، ما را از دایره‌ی تأثیر آن‌ها در دنیای واقعی غافل کند.این مطلب توسط محمدرضا علی حسینی در بلاگ راهبردهای خلاق آرمان نوشته شده است.</description>
                <category>راهبردهای خلاق آرمان</category>
                <author>راهبردهای خلاق آرمان</author>
                <pubDate>Wed, 08 Dec 2021 11:41:48 +0330</pubDate>
            </item>
            </channel>
</rss>