<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های MohammadReza Rahmatzadeh</title>
        <link>https://virgool.io/feed/@mr.rahmatzade371</link>
        <description></description>
        <language>fa</language>
        <pubDate>2026-04-14 23:46:14</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/103839/avatar/PdaRSG.png?height=120&amp;width=120</url>
            <title>MohammadReza Rahmatzadeh</title>
            <link>https://virgool.io/@mr.rahmatzade371</link>
        </image>

                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 40</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-40-wzfwzfwx3kyc</link>
                <description>درس 40: Refactoringحین تکامل یک نرم افزار، پیش میاد که در مورد قسمت هایی از کد تجدید نظر کنیم و تغییراتی بدیم. این امر طبیعیه. کد نیاز به تکامل داره و یک چیز ثابت و ایستا نیست.متاسفانه اصطلاح ساختن یا ساخت و ساز در مورد نرم افزار بعضا بکار میره. معمولا ساختن رو برای ساختمون بکار میبرن و یک همچین پروسه ای داره:-  معمار نقشه های اصلی رو ترسیم میکنه-  پیمانکاران شروع به ساخت میکنن از شناژ و پایه های ساختمان تا دیوارها و لوله و سیمکشی و سنگ و نما و ...-  ساکنین خوشحال سر و کله شون پیدا میشه و در خونه هاشون مستقر میشن.ولی نرم افزار اینجوری نیست. پروسه تولید نرم افزار روح دار تر از ساخت ساختمونه و بیشتر شبیه به باغبانیه. شما طبق یک برنامه اولیه و شرایط موجود یکسری گیاه رو در باغچه تون میکارید. برخی شون رشد میکنن، برخی شون سقط میشن و به کود تبدیل شون میکنید، برای اینکه از حداکثر نور خورشید و یا باد و آب بهره ببرن ممکنه جابجاشون کنید، بعضی رو در تایم مشخص هرس میکنید، و دائما بر سلامت باغچه تون نظارت دارید و در صورت لزوم تنظیم آب و خاک و چیدمانشون رو تغییر میدید.شاید بیزنس من ها و تجار با مفهومی مثل ساخت ساختمون راحت تر باشن، چون همه چیز واضح و مشخصه، یکسری روال و عملیات که طبق یک ترتیب خاصی انجام میشن تا محصول نهایی آماده بشه ولی دنیای نرم افزار بیشتر مثل روال باغبونیه.طبق تعریف مارتین فاولر(نویسنده و سخنران حوزه علوم نرم افزاری):ریفاکتور کردن روش منظمی برای تغییر ساختار کد موجود، به شکلی که ساختار داخلی تغییر بکند، بدون اینکه ساختار خارجی و رفتار اون تغییر بکنه.دو نکته مهم این تعریف:•  این عملیات نظم و جای خاصی داره و شامل هرجایی نمیشه•  رفتار خارجی قرار نیست تغییر بکنه، چون به این معنی نیست که قراره فیچری اضافه بشه.برای اینکه گارانتی کنید رفتار خارجی کد تغییری نکرده باید تست های اتومات خوبی داشته باشید که رفتار کدتونو بررسی کنه.WHEN SHOULD YOU REFACTOR?وقتی ریفاکتور میکنید که چیز جدیدی یاد گرفتید و متوجه شدید روش جدید که از کاری که سال قبل یا ماه قبل یا ده دقیقه پیش انجام دادید، بهتره. وقتی کدی رو واجد شرایط ریفاکتور پیدا میکنید، توی تغییرش درنگ نکنید، چون بهترین وقت همین زمان حاله.یکسری موارد شایع وجود داره که در صورت دیتکت شون بدونید باید ریفاکتور کنید:•  Duplicationکدی رو پیدا کردید که داره اصل DRY رو نقض میکنه و تکرار محسوب میشه•  نقص اصل جداسازی decouplingوقتی کد یا بخش هایی از کد رو پیدا میکنید که اصل جداسازی رو رعایت نکردن و با تغییر یکی شون مابقی خراب یا باگ دار میشه•  دانش قدیمیشما با کدی مواجه میشید که دانش بیزنسی قدیمی رو اعمال کرده بودید•  Performanceکدی یا بخشی رو پیدا کردید که میتونید بهبودی توی پرفورمنسش بدیداین واقعیت هم وجود داره که عمل ریفاکتورینگ، عمل دردناکیه، شما رو متحمل سختی میکنه و همچنین دقت بالایی رو باید بخرج بدید، خیلی از دولوپرها متاسفانه بر این عقیده ان که تا زمانی که کار میکنه چرا بهش دست بزنیم، اما اگر بهبود ندید و اپدیتش نکنید کل سیستم تون زیر سوال میره. قطعا ریفاکتور کردن عوارضی داره. مهمترینش زمانی که باید بزاریده اونم با وجود فشار زمانی روی پروژه هاست اما رسیدگی نکردن بهش میتونه مثل یک توده سرطانی کوچیک باشه که اگر خیلی زود بهش رسیدگی بشه با یک درمان دارویی کوتاه رفع میشه ولی اگر رسیدگی نشه توی بدن پخش میشه و با کلی درد و خطر و حتی شکست باید بهش رسیدگی کنید.واضح است که ریفاکتور کردن فعالیتیه که باید به آرومی، آگاهانه و با دقت انجام بشه. مارتین فاولر نکات ساده زیرو در مورد چگونگی ریفاکتور کردن و آسیب نرسوندن میگه:•  سعی نکنید عمل ریفاکتور کردن رو با افزودن فیچر باهم و در یک زمان انجام بدید•  مطمئن باشید که تست های خوبی دارید قبل از اینکه ریفاکتور کنید.•  قدم های کوچیک بردارید و بعد هر قدم هم تست ها رو اجرا کنید، این از دیباگ کردن های طولانی و مشکلات پیش رو نجاتتون میده.دروس مرتبط: 3, 9, 12, 27, 44, 48منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Thu, 08 Apr 2021 20:27:04 +0430</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 39</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-39-kccvvoeelkte</link>
                <description>درس 39: Algorithm Speedتوی درس 15 در مورد تخمین زدن صحبت کردیم، مثلا تخمین اینکه هر فاز یا کل پروژه چقد طول میکشه تا انجام بشه. نوع دیگه ای از تخمین زدن هم وجود داره که برنامه نویس های عملگرا بصورت روزمره باهاش سر و کار دارن. تخمین اینکه یک روش یا الگوریتم چقدر از منابع سخت افزاری استفاده میکنه. مثلا میزان استفاده از سی پی یو، مموری و ...این مدل تخمین خیلی حیاتیه. بین دو یا چند راه مختلف انجام یک کار، بهتون کمک میکنه که بهینه تر رو انتخاب کنید و همچنین با پیش بینی ای از رشد دیتای سیستم و کاربران و ... به فکر scale سیستم باشید.منظورمون از تخمین سرعت اجرای الگوریتم چیه؟ در خیلی از الگوریتم ها مثل سورت(مرتب سازی)، دیکریپت رشته و ... سرعت اجرا به اندازه داده ورودی بستگی داره، به عنوان مثال فرض کنید برای سورت کردن هر چی آرایه ای که میخایم سورت بکنیم بزرگتر باشه، به همون نسبت طول زمان اجرای عملیات سورت هم طول میکشه. به این مدل افزایش خطی میگیم، ینی به شکل خطی و رابطه مستقیم هر چی ورودی عملیات بیشتر باشه زمان اجرا هم بیشتر میشه. بعضی از الگوریتم ها هم خطی نیستند مثل باینری سرچ(برای پیدا کردن یک ایتم از آرایه، کل آرایه رو پیمایش نمیکنه). بعضی هم ممکنه بدتر از رشد خطی داشته باشن مثلا توی یک بار اجرا 100 میلی ثانیه زمان و حجم مشخصی مموری بگیرن ولی توی ده بار اجرا 5 ثانیه طول بکشن و مموری هم 10 برابر.این معقول نیست که تایم زیادی بزارید و الگوریتم هایی مثل سورت و سرچ رو خودتون پیاده سازی کنید، چون مدلهای مختلفش توی کتابخونه های نوشته شده در دسترس هست. اما وقتی خودتون اقدام میکنید به نوشتن یک loop (حلقه) یا حتی حلقه های تودرتو اینو در نظر داشته باشید که زمان اجرا و مموری تون رو بسنجید و همچنین به اجرای حلقه با تکرار خیلی بالا و محتمل فکر کنید و تست بگیرید.با کمک ابزارهایی مثل پروفایرها میتونید مقدار رم و پردازنده رو در هر استپ الگوریتم تون چک کنید و سعی کنید با حجم دیتای مختلف زیر بار ببرید و نتایج رو بررسی کنید. بعضا ممکنه یک الگوریتم با داده ورودی کم بسیار بهینه باشه ولی در حجم ورودی زیاد به شدت مموری مصرف کنه و سیستم تون رو دان کنه.دروس مرتبط: 15منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Wed, 07 Apr 2021 09:47:33 +0430</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 38</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-38-upqxvn71b5q4</link>
                <description>درس 38: برنامه نویسی توسط تصادف Programming by Coincidenceممکنه تابحال فیلم جنگی قدیمی ای رو دیده باشید که توش سربازی که پشت میدون مین گیر کرده و دقیقا شناسایی هم نکرده منطقه رو میخاد از مسیری عبور کنه، دلو به دریا میزنه و یک مسیرو انتخاب میکنه و بدو بدو اون مسیرو طی میکنه، احتمال داره که موفقیت امیز رد بشه و یا تیکه تیکه بشه.به عنوان برنامه نویس، ماهم با میدون های مینی مواجه میشیم. صدها تله وجود داره که طی روز مارو به دام بندازه. توی برنامه نویسی ما نباید به نتیجه های تصادفی و شانسی دل ببندیم و روشون مانور بدیم.HOW TO PROGRAM BY COINCIDENCEفرض کنید Fred یک چالش برنامه نویسی رو میخاد حل کنه. ی کدی میزنه و اجراش میکنه و ظاهرا کار میکنه. بعد چند هفته کرش میکنه، و بعد از چند ساعت تلاش Fred اصلا نمیدونه چرا این اتفاق افتاده! چون از اول نمیدونست که چجوری کد درست کار میکرد. بعد چند تا تست محدود و موفقیت اتفاقی کد، اونو پابلیش کرد و توی استثنائات گیر افتاد.هر ادم عاقلی میدونه که نباید روی جواب گرفتن اتفاقی حساب کنیم.چند نمونه مثال بزنیم:-  استفاده از کدی که توی سرچ اینترنت پیدا کردیم و چیزی رو که میخاستیم انجام میده، بدون در نظر گرفتن موقعیت و شرایط استفاده از اون کد و استثنائاتش و اصن فهم اون قطعه کد و چگونگی دیتیل اجراش-  استفاده از تایم زون خاص و هاردکد شده، استفاده از متغیرهای وابسته به مسیر فایل سیستم خاص یا فیچرهای خاص سیستم عامل و ...HOW TO PROGRAM DELIBERATELYما میخایم زمان کمتری رو صرف چالش های کد بکنیم و کدی کم خطاتر و استیبل تر بزنیم و چرخه مهندسی نرم افزارمون کم دردسر و روتین تر طی بشه. اینکه کدها رو غیر تصادفی و کاملا عمدی و بهشون مسلط و واقف باشیم خیلی به این داستان کمک میکنه.مواردی که میتونه بهمون کمک کنه:-  بدونید و آگاه باشید به کاری که دارید انجامش میدید و مثه Fred دنبال جواب گرفتن نباشید-  آیا میتونید کدی که نوشتیدو به یک فرد تازه کار به دیتیل توضیح بدید؟ اگر نمیتونید، قطعا مواردی رو ندونسته یا تصادفی توی کد گذاشتید که در هر دو حالت آفت هاشم گریبان گیرتون خاهد بود.-  از تکنولوژی و روش هایی که مسلطید و بلدشین استفاده کنید-  حتما پلن داشته باشید و قبل از کد زدن روش فکر و بالا پایین کنید-  فقط صحت کد رو تست نکنید و با assert ها سعی کنید حالت های مختلف منطق و حداکثر استثنائات رو زیر تست ببرید-  و ...دروس مرتبط: 4, 9, 23, 34, 43منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Wed, 24 Mar 2021 00:22:23 +0430</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 37</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-37-xfi64fgdccke</link>
                <description>فصل 7: While You Are Codingدرس 37: Listen to Your Lizard Brainغرایز ما پاسخ های ساده هستند به چیزهایی که در مغز ناخودآگاه ما وجود داره. برخی ذاتی هستند و برخی هم از طریق تکرار زیاد آموخته میشن. همونطور که شما به عنوان یک برنامه نویس در مورد یکسری چیزها اینطوری هستید، روشهایی که همیشه برای استفاده های خاصی کار میکنن، روشهایی که برعکس کار نمیکنن و جواب نمیدن، علت برخی از خطاها و ... که در طول روز هم خیلی براتون رخ میده. یا بخشی از مغزتون که به صورت غیر ارادی فرمان میده دکمه سیو رو بزنی وقتی میخای متوقف بشی و جواب کسیو بدی.غریزه ها از هر منبعی که باشن در یک چیز مشترکن، اونها هیچ توصیف مشخصی ندارن. غرایز باعث میشن که احساس کنید، فکر نکنید.نکته اینجاست که بتونید وقتی این رفتارها رخ میده، متوجهشون بشید، بعدش دلیلش رو بررسی کنید. بیاید ابتدا به چند موقعیت متداول که مارمولک(Lizard) درونی شما در تلاشه به شما چیزی بگه ، نگاهی بندازیم. بعدش بررسی میکنیم که چطوری می تونید اون مغز غریزی را از محافظش خارج کنید.FEAR OF THE BLANK PAGEاکثرا از یک صفحه خالی، که کرسر به تنهایی توش چشمک میزنه، میترسن. شروع یک پروژه جدید (یا حتی ماژول جدید در یک پروژه) میتونه یک تجربه دلهره اور باشه. بسیاری از ما ترجیح میدیم که تعهد اولیه شروعو به تعویق بندازیم.به نظر ما دو مشکل منجر به این حس میشه که هر دو شونم یک راه حل داره.مشکل اول اینه که مغز لیزاردتون سعی میکنه بهتون چیزی رو بگه، یک چیزی شبیه به شک و تردید. موقعی که برای انجام کاری شک و تردید میکنی یا بی میل هستی ممکنه این حسو تجربه کرده باشی. به این حس توجه کنید، و روش وقت بزارید، احتمالا این شک ها شمارو به منشا و علتش میرسونه ، بزارید غرایزتون به عملکردتون کمک کنه.مشکل دوم، نگرانی از اینه که ممکنه باگ و یا مشکلی رو ایجاد کنید. و تا حدودی منطقی هم هست این احساس. یا این پروژه فراتر از شماست و چشم انداز روشنی از خاتمه اش نمیبینید.FIGHTING YOURSELFبعضی موقعا، کد مثه آبشار از مغز شما به سمت IDE روونه میشه و خیلی شسته رفته و بدون توقف ایده هاتونو پیاده میکنید.بعضی موقعام مثه پیاده روی در گل و لای توی یک سربالایی میمونه، برای برداشتن هر قدم تلاش زیاد و حتی عقب گرد دارید.کد شما سعی میکنه بهتون چیزیو بگه، شاید مسئله سخت تر از اون روشی باشه که انتخاب کردید، یا ساختار و دیزاین پترن اشتباهی انتخاب کردید، یا اصلا شاید صورت مسئله ای که مشغول به حل کردنش هستید اشتباهه و حاصل یک تحلیل یا نیازمندی غلطه، به هر علتی که باشه این مغز Lizard تونه که توی این شرایط سعی داره بهتون سیگنال بده و باید بهش توجه کنید.HOW TO TALK LIZARDنکته اینجاست که باید با غرایز و مغز Lizard ناخودآگاهتون صحبت کنید.در قدم اول، از انجام کاری که مشغولش هستید متوقف بشید. یکم به خودتون زمان بدید تا مغزتون ی سازمان دهی بکنه خودشو، به کد فکر نکنید، به کارهای دیگه مثل تایم نهار، کمی قدم زدن یا صحبت با دوستتون مشغول بشید. بزارید تا ایده ها خودشون به لایه های مغزتون غلبه و ورود کنن، نمیتونید مجبورشون کنید.اگر جواب نداد، مسئله رو بیرونی کنید، مطرح کردنش با یک دوست یا همکار و مشورت کردن راجعش میتونه اثر بخش باشه.اگر بازم جواب نداد، دیگه وقت اقدامه، هرچیزی به ذهنتون میرسه رو عملی کنید و ما اینکارو با نمونه سازی prototyping انجام میدیم.طی این سالها ما به یک روش هک مغزی رسیدیم که به نظر موثر میاد، به خودتون بگید که نیاز به نمونه سازی اولیه پروژه رو دارید، اگر با صفحه خالی روبرو هستید، به دنبال اون جنبه هایی از پروژه باشید که میخاید چیزهای جدیدی رو به کار ببرید مثلا ممکنه روش دیتابایندینگ یک فریمورک جدید باشه، یا نحوه برخورد یک الگوریتم با استثناها و ... شما میخاید یاد بگیرید که چجوری کار میکنن.این کارها رو بکنید:1- روی یک استیکی نوت بنویسید من در حال نمونه سازی هستم و بچسبونید کنج صفحه نمایش2- یادتون باشه نمونه سازی ممکنه با شکست مواجه بشه، یا حتی اگر شکست هم نخوره، ممکنه به درد نخوره و پرتش کنید دور.3- صفحه خالی ادیتورتونو با یک کامنت شروع کنید، توش کاری ک میخاید بکنید یا چیز جدیدی که میخاید یاد بگیرید و ازمایش کنیدو بنویسید4- شروع به کدنویسی کنیداگر شک و تردید سراغتون اومد، به اون استیکی نوت نگاه کنید یا به خودتون فرصت بدید و اون تایم استراحت یا مشورتو انجام بدید.طبق تجربه با انجام این روش، وقتی در حال نمونه سازی هستید، خودتونو تو شرایطی پیدا میکنید که دارید موسیقی که گذاشتیدو زمزمه میکنید و از کد زدن لذت میبرید و شک و تردید و اضطراب شروع رو هم ندارید. در نهایت به جواب میرسید، روش نهایی رو پیدا میکنید، موارد نمونه سازی شده رو کنار میزارید و شروع به زدن کد اصلی میکنید.NOT JUST YOUR CODEبخش زیادی از کار ما سر و کله زدن با کدی هست که دیگران نوشتن و ممکنه روش های دیگه ای رو به کار برده باشن، نه لزوما بدتر فقط متفاوت. خوب شما باید کدشونو بخونید و دیتکت کنید که شاید کار طاقت فرسایی باشه. شاید هم اجرای اون و دیباگش بهتون کمک بکنه تا سریعتر بفهمید روش و یا پترن اعمال شده چجوریه و چیزهای جدیدی ام یاد بگیرید.NOT JUST CODEاینکه حین کد نویسی یاد بگیریم به غرایز و احساس درونی مون توجه کنیم، خیلی مهمه. گاهی اوقات اونا کمک میکنن تا شاید تصویر بزرگتری از یک فاجعه پیش رو، رو متوجه بشیم، فقط متوقف بشید و آنالیز کنید، شاید روی روش اشتباه، پترن نامناسب، نیازمندی غلط و ... هستیم.دروس مرتبط: 13, 22, 46منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Mon, 15 Mar 2021 20:41:45 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 36</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-36-ymr58zjntkum</link>
                <description>درس 36: Blackboardsمعمولا وقتی کارآگاه های جنایی پرونده ای زیر دستشون میاد، از یک تخته سیاه استفاده میکنن و هرآنچه از سوالات، ابهامات، حدس ها، شواهد و ... روش مینویسن یا میچسبونن، این بهشون کمک میکنه تا همه چیزو جلوی چشمشون توی یک دید داشته باشن و وقتی ارتباطی بین دو یا چند چیز ممکنه وجود داشته باشه، اونو روی تخته اعمال میکنن و این پروسه رو در طول پروسه حل اون پرونده انجام میدن.چند تا از نکته های کلیدی و مهم استفاده از این تخته سیاه اینه:- کارآگاه ها میتونن به صورت تیمی روی پرونده کار کنن و حتما نیاز به حضور یک یا چند نفر خاص نیست و همه چیزه پرونده روی تخته واضحه- افراد با سواد و تجربه و حوزه های مختلف میتونن ایده هاشونو به اشتراک بزارن- افراد در شیفت های زمانی مختلف میتونن روی پرونده پیش برناین مدل به نوعی همزمانی رو برامون به ارمغان میاره، هر کارآگاه به صورت مستقل یک پراسس یا ایجنت یا اکتور هست که بخشی از کارو پیش میبره، بعضی هاشون مواردی رو به تخته اضافه میکنن و برخی هم از اون اطلاعات بهره برداری میکنن و اونها رو ترکیب میکنن.تخته سیاه های کامپیوتری معمولا توی هوش مصنوعی به کار میان وقتی که مسئله بزرگ و پیچیده است مثل پردازش صدا یا تصمیم گیری براساس دانش سیستم و ...A BLACKBOARD IN ACTIONفرض کنید در حال نوشتن برنامه ای برای پذیرش و پردازش درخواست های رهن یا وام هستید. قوانین این حوزه کاری بسیار پیچیده و فجیعه، همچنین هر ایالت برای خودش قوانین محلی خودشو وضع میکنه. وام دهنده باید یکسری مواردو ثابت کنه و ارائه بده اما سوالات خاصی رو هم نباید بپرسه.مشکلات زیرو توی این مسئله داریم:- رسپانس ها به هر ترتیبی ممکنه وارد بشن، کوئری که برای یک چک اعتباری یا جستجو با عنوان زده میشه ممکنه یکم طول بکشه در صورتی که برخی فیلدها مثل اسم و ادرس سریعتر در دسترس ان- ثبت داده ها توسط افراد مختلف انجام میشه به صورت توزیع شده و در دفاتر مختلف با تایم زون های مختلف- برخی از ثبت ها بایستی اتومات توسط ساب سیستم های دیگر انجام شود و به صورت async به مرکز برسه- برخی از داده ها ممکن است هنوز به داده های دیگر وابسته باشند. به عنوان مثال ، تا زمانی که مدرک اثبات مالکیت یا بیمه را بدست نیاورید ، نمی توانید جستجوی عنوان را برای یک ماشین شروع کنید- ورود داده های جدید خودش ممکنه منجر به سوالات و ایجاد قوانینی روشون بشه، مثلا چک اعتباری که ثبت شده اگر شرایط خاصی رو داشته باشه باید یکسری اطلاعات تکمیلی دیگه هم براش پرسیده بشهشما میتونید هر ترکیب مختلفی از حالات ممکنه رو با یک سیستم ورک فلو هندل کنید. خیلی از این مدل سیستم ها هم در دسترس است ولی ممکنه پیچیده بشه و همچنین نگهداری و برنامه نویسیشم سخت باشه. وقتی یک قانون عوض میشه باید فرایندتونو ویرایش کنید. در شروع یک تخته سیاه میتونه خیلی موثر باشه که تمام حالتهای ممکنو در یک قالب ببینید و چیزی از قلم نیفته.MESSAGING SYSTEMS CAN BE LIKE BLACKBOARDSخیلی از اپلیکیشن ها از سرویس های جداشده(decouple) و کوچیک ساخته میشه، که این سرویس ها توسط یک سیستم مسیج بروکر باهمدیگه در ارتباط و صحبت میکنن. سیستم های مسیج بروکر مثل Kafka, NATS, RabitMQ و ... کارهای فراتر از ارسال داده از A به B انجام میدن. حتی مدل های Persistance دارن که برای Logging هم قابل استفاده است. همچنین قابلیت دریافت مسیج در مقصد با پترن خاص. قابلیت هایی بهتون میده که ازشون هم به عنوان blackboard system و هم پلتفرمی برای ران کردن actor ها استفاده کنید.(توضیحات تکمیلی مترجم: مسیج بروکرها نرم افزارهایی هستند که بهمون این امکانو میدن که روشون صف هایی رو بسازیم و روی آی پی و پورت و رمز خاص سرویس های مختلفمون میتونن روی صف های مختلف دیتا رو در قالب مسیج بزارن و سرویس های دیگه ام از صف ها مسیج ها رو بردارن. در سیستم های توزیع شده و میکروسرویس ها، بخش اعظم و مهم معماری استفاده از مسیج بروکر خوب هستش. مثلا فرض کنید در یک سیستم فروش اینترنتی، سرویس ثبت سفارشات وقتی سفارشاتو توی دیتابیس خودش ثبت میکنه، اونها رو روی صف خاصی هم میفرسته، از اونور سیستم بک افیس مالی، مسیج های سفارشات رو برمیداره و در دیتابیس بک افیس هم اعمالشون میکنه. در این معماری، سرویس ثبت سفارشات نیازی به معطلی برای ارسال سفارش به سرویس بک افیس رو نداره و صرفا مسیج ها رو روی صف ارسال میکنه و سرویس بک افیس ممکنه در تایمی خاص مسیج ها رو برداره و صدها مثال و کاربرد مختلف. در برخی سیستم ها ممکنه از این صف ها به عنوان دیتابیس استفاده بشه و مد های مختلفی مثل in memory, durable رو ساپورت میکنن و کاربردشون فقط به مسیج ختم نمیشه)اما ساده ام نیست...مدل actor ، blackboard یا میکروسرویس ها، معماری ای رو بهمون میدن که راحت تر بتونیم همزمانی پردازش ها رو پیاده سازی کنیم، اما این فایده با هزینه هایی هم همراهه، این مدل پیاده سازی ها از جنبه هایی سختی داره، خیلی از عملیات ها غیر مستقیم در حال رخ دادنه، دیباگ کردن، مانیتورینگ، فرمت صحبت مسیج های روی مسیج باس و ... باید به خوبی هندل بشه.دروس مرتبط: 28, 29, 33, 35منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Wed, 10 Mar 2021 01:03:49 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 35</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-35-rmdnhehsycow</link>
                <description>درس 35: Actors and Processesاکتورها و پراسس ها روش های جالبی رو برای پیاده سازی concurrency بهمون ارائه میدن، بدون بلایایی که shared memory ها سرمون میاوردن توی همزمانی. قبل از شروع یک تعریف اولیه ازشون بریم و ببینیم که اصلا چی هستن.اکتور: یک پردازشگر مجازی هستش که لوکال state خصوصی خودشو داره. هر اکتور یک mailbox داره، وقتی مسیجی براش میاد و اکتور توی حالت idleهستش، بیدار میشه و مسیج ورودی شو پردازش میکنه. وقتی پردازشش تموم شد، مسیج های بعدی توی mailbox شو پردازش میکنه تا موقعی که خالیش کنه و دوباره بره توی مد sleep.حین پردازش یک مسیج، اکتور میتونه اکتورهای دیگه ای رو بسازه، به اکتورهای دیگه مسیج بده و ...پراسس: مفهوم عام تری از پردازشگر مجازی است که معمولا توسط سیستم عامل ایجاد میشه و پردازش خاصی رو انجام میده، پراسس ها میتونن طبق تعریف خاصی شبیه به اکتورها باشن که منظور ما در اینجا هم همینه.ACTORS CAN ONLY BE CONCURRENTچیزهایی که توی تعریف و ذات اکتورها نمیگنجه:- یک چیز مشخص تحت کنترل وجود نداره. هیچ چیزی اسکژول نشده که توی استپ بعد اجرا بشه، و یا تبدیلگری وجود نداره که داده خامو به خروجی تبدیل کنه.- تنها استیت موجود در سیستم توسط مسیج ها نگهداری میشه، و توی استیت لوکال اکتور ها میره، مسیج ها رو نمیشه پیش بینی کرد مگر زمانی که توسط گیرنده پراسس بشن، و استیت لوکال اکتورها از بیرون در دسترس نیست.- مسیج ها یک طرفه اند، مفهومی مثل reply وجود نداره، اگر بخاید از اکتوری رسپانس بگیرید باید میل باکس خودتونو توی مسیج بزارید تا وقتی اکتور مسیجو پردازش کرد اونو براتون بفرسته.- یک اکتور مسیج ها رو دونه دونه پردازش میکنه تا میل باکسشو خالی کنه، توی هر لحظه بیش از یک مسیج نمیتونه توسط اکتور پردازش بشه.در نهایت، مجموعه ای از اکتورها به صورت همزمان و async کار میکنند و هیچ چیزی رو به اشتراک نمیزارن. اگر به اندازه کافی کور سی پی یو داشته باشید میتونید روی هر کدوم یک اکتور ران کنید وگرنه runtime هایی هستند که برامون context سیستم رو سوییچ میکنن و چندین اکتور رو همزمان و موازی اجرا میکنن.و در هر صورت کدی که توی هر نوع اکتور اجرا میشه، یک کد یکسانه و ما چرا اومدیم سراغ اکتورها، چون به همزمانی برسیم.· بیاید مشابه مثال پای سیب درس قبل رو بزنیم. در اینجا ما سه اکتور درگیر داریم: (مشتری، گارسون و سینی پای سیب)فلوی کلی جریان مسیج ها به این شکل خاهد بود:- مشتری درخواست پای سیب میده به گارسون- گارسون از محل سینی پای سیب استعلام میگیره برای موجود بودن پای سیب درخواستی- اگر به اندازه کافی موجود بود، سینی دار، پای سیب رو ارسال و به گارسون اعلام میکنه- اگر هم موجودی کافی نباشه، به گارسون اطلاع میده و گارسون هم از مشتری عذرخواهی میکنهما این کدو با JSپیاده کردیم و با استفاده از Nact Library که با یک سری wrapper تونستیم به سادگی نوشتنه object ها اکتور بنویسیم به شکلی که key مسیج های دریافتی هست و value فانکشنی که بایستی اجرا بشه. خیلی از اکتور سیستم ها چیزی مشابه این رو ارائه میدن، فقط به زبون و سینتکس های متفاوت.بیاید با مشتری شروع کنیم. یک مشتری میتونه سه مدل مسیج مختلف رو دریافت کنه:- گرسنه بودن (که از مکانی خارج از دامین این مثال میاد مثلا دوستش بهش یاداوری میکنه گرسنه ای)- پای سیب درخواستی موجوده (از سمت سینی دار پای میز ارسال میشه)- متاسفم، پای سیبی نمونده (ارسالی از گارسون)کد اکتور مشتری به این شکله:const customerActor = {  &#x27;hungry for pie&#x27;: (msg, ctx, state) =&gt; {  return dispatch(state.waiter,  { type: &quot;order&quot;, customer: ctx.self, wants: &#x27;pie&#x27; })},&#x27;put on table&#x27;: (msg, ctx, _state) =&gt;  console.log(&#x60;${ctx.self.name} sees &quot;${msg.food}&quot; appear on the table&#x60;), &#x27;no pie left&#x27;: (_msg, ctx, _state) =&gt;  console.log(&#x60;${ctx.self.name} sulks…&#x60;)}کد اکتور گارسون:const waiterActor = {  &quot;order&quot;: (msg, ctx, state) =&gt; {   if (msg.wants == &quot;pie&quot;) {dispatch(state.pieCase,  { type: &quot;get slice&quot;, customer: msg.customer, waiter: ctx.self })}else { console.dir(&#x60;Don&#x27;t know how to order ${msg.wants}&#x60;);   }  },&quot;add to order&quot;: (msg, ctx) =&gt;console.log(&#x60;Waiter adds ${msg.food} to ${msg.customer.name}&#x27;s order&#x60;),&quot;error&quot;: (msg, ctx) =&gt; {dispatch(msg.customer, { type: &#x27;no pie left&#x27;, msg: msg.msg });console.log(&#x60;\nThe waiter apologizes to ${msg.customer.name}: ${msg.msg}&#x60;)}};وقتی اکتوره گارسون یک مسیج مبنی بر order از مشتری دریافت میکنه، چک میکنه که سفارش پای سیبه یا نه و در صورتی که پای سیب باشه ارسالش میکنه به سینی دار (کسی که از سینی مراقبت میکنه و مسئولش هست) پای سیب و رفرنسها هم اگر مشاهده کنید توسط مسیج ها پاس داده میشه.اکتور سینی دار، استیتش یک آرایه از اسلایس های پای سیبه. وقتی مسیج get slice رو دریافت میکنه از گارسون، نگاه میکنه که آیا موجودی براش باقی مونده، اگر آره اسلایس رو برای مشتری می فرسته و به گارسون هم اطلاع میده..const pieCaseActor = {  &#x27;get slice&#x27;: (msg, context, state) =&gt; {  if (state.slices.length == 0) { dispatch(msg.waiter, { type: &#x27;error&#x27;, msg: &quot;no pie left&quot;, customer: msg.customer })return state  }else {  var slice = state.slices.shift() + &quot; pie slice&quot;;dispatch(msg.customer,   { type: &#x27;put on table&#x27;, food: slice });dispatch(msg.waiter,   { type: &#x27;add to order&#x27;, food: slice, customer: msg.customer });return state;  }  }}همونطور که ملاحظه کردید ما یکسری اکتور رو توسط اکتورهای دیگه ایجاد کردیم و بهشون initial state هم دادیم (رفرنس مشتری، سفارش و ...)، همچنین اکتورها میتونن داینامیک ایجاد و استارت بشن.const actorSystem = start(); let pieCase = start_actor(  actorSystem,  &#x27;pie-case&#x27;, pieCaseActor,  { slices: [&quot;apple&quot;, &quot;peach&quot;, &quot;cherry&quot;] }); let waiter = start_actor(  actorSystem,&#x27;waiter&#x27;,waiterActor,  { pieCase: pieCase });let c1 = start_actor(actorSystem, &#x27;customer1&#x27;,customerActor, { waiter: waiter }); let c2 = start_actor(actorSystem, &#x27;customer2&#x27;,customerActor, { waiter: waiter });فرض کنید این کدو توی حالتی که دو تا مشتری گرسنه داریم که مشتری اول سه تا و مشتری دوم دو تا پای سیب درخواست میدن اجرا میکنیم:dispatch(c1, { type: &#x27;hungry for pie&#x27;, waiter: waiter });dispatch(c2, { type: &#x27;hungry for pie&#x27;, waiter: waiter });dispatch(c1, { type: &#x27;hungry for pie&#x27;, waiter: waiter });dispatch(c2, { type: &#x27;hungry for pie&#x27;, waiter: waiter });dispatch(c1, { type: &#x27;hungry for pie&#x27;, waiter: waiter });sleep(500).then(() =&gt; {stop(actorSystem);})وقتی اجراش کنیم، ارتباط و درگیری بین اکتورها رو مشاهده خواهیم کرد و یکی از خروجی های متصور به این شکله:$ node index.js customer1 sees &quot;apple pie slice&quot; appear on the tablecustomer2 sees &quot;peach pie slice&quot; appear on the tableWaiter adds apple pie slice to customer1&#x27;s orderWaiter adds peach pie slice to customer2&#x27;s ordercustomer1 sees &quot;cherry pie slice&quot; appear on the tableWaiter adds cherry pie slice to customer1&#x27;s orderThe waiter apologizes to customer1: no pie leftcustomer1 sulks…The waiter apologizes to customer2: no pie leftcustomer2 sulks…NO EXPLICIT CONCURRENCYتوی اکتور مدل، نیازی نیست ما کدی رو برای هندل کردن همزمانی بزنیم، همچنین shared state ای هم وجود نداره. همچنین نیازی به زیرساخت و یا معماری سخت افزاری خاصی هم وجود نداره چون فریمورک ها اینو روی یک پردازشگر یا چندین پردازشگر لوکال یا توزیع شده میتونن پیاده سازی و اجرا کنن.ERLANG SETS THE STAGEزبون برنامه نویسی و ران تایم Erlang یک مثال خیلی خوب از مدل پیاده سازی اکتور بیس هست، در ارلنگ به اکتورها process میگن هرچند منظور از پراسس به اون شکلی که توی سیستم عامل پیاده میشه نیست، اما دقیقا مثل مکانیزم اکتورها که مثالشو زدیم، میتونیم توی ارلنگ میلیون ها پراسس رو روی یک ماشین ران کنید و دقیقا با مکانیزم مسیج باهم ارتباط برقرار میکنند و نسبت به هم ایزوله هستند. ران تایم ارلنگ مدلی از supervisor رو پیاده سازی کرده که این پراسس ها رو مانیتور و لایف تایم و مدیریت منابع و خطا شونو به عهده داره. همچنین hot-code loading داره، یعنی میتونید کد در حال اجرا رو ریپلیس کنید بدون اینکه پردازش تون رو متوقف کنه. (این رفتار خوراک سیستم هایی هست که همیشه باید انلاین باشن 99.999 درصد باید بالا باشن و به درخواست ها پاسخ بدن.مدل پیاده سازی اکتور در اکثر زبون های برنامه نویسی کتابخونه و تردپارتی داره و به راحتی در دسترسه.)دروس مرتبط: 28, 30, 36منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Sat, 06 Mar 2021 21:37:31 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 34</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-34-rfvtqnqe2cbh</link>
                <description>درس 34: Shared State Is Incorrect Stateفرض کنید توی یک رستوران از گارسون میخاید که براتون یک کیک پای سیب اضافه بیاره، اون به میز وسط سالن نگاه میکنه و میبینه یکی باقی مونده و اونو تارگت میکنه که براتون بیاره، در همین لحظه یک مشتری دیگه ام اونور سالن همین درخواستو از گارسون دیگه ای میکنه، اون گارسون هم میز اصلی رو نگاه میکنه و کیکو تارگت میکنه، توی این شرایط قطعا یکی از مشتریا درخواستش fail میشه.مشکل کجاست؟ Shared Stateمشکل منبع مشترکی بود که هر دو گارسون به اون امید بستن، بدون در نظر گرفتن درخواست های همدیگه و بقیه همکاراشون. بیاید کد مثالی که زدیم و بررسی کنیم.قطعا دو گارسون به صورت همزمان و موازی کارشونو انجام میدن چون 2 تا ادم مختلف و هر کدوم دارن یک بخشی رو سرویس دهی میکنن، و تابعی که معادل رفتارشون توی مثال بالاست به این شکله:if display_case.pie_count &gt; 0  promise_pie_to_customer()  display_case.take_pie()  give_pie_to_customer() endطبق کد، گارسون1 یک استعلام موجودی میگیره و میبینه 1 عدد موجوده و به مشتریش اوکی میده، دقیقا همین کارو گارسون2 هم انجام میده و در نهایت این باعث میشه که اولین گارسونی که به پای سیب برسه موفق و دومی توی استیت خطا گیر کنه.مشکل این نیست که هر دو پراسس میتونن روی یک حافظه مشترک بنویسن، مشکل اینه که هیچ کدوم از دو تا پراسس نمیتونن تضمین کنن که اون دیدی که از حافظه دارن قطعا درسته. طبق کد بالا وقتی یک گارسون استعلام تعداد پای سیبو میگیره، مقدارش رو کپی میکنه توی حافظه scope خودش، اگر مقدار موجودی روی حافظه مشترک و اصلی تغییر بکنه، اون هیچ اطلاعی از اون تغییر نخواهد داشت و موجودی لوکالش نامعتبر میشه. این بخاطر اینه که پروسه fetch و update موجودی پای سیب یک عملیات atomic نیست.(اگر در مورد atomic نمیدونید، توی گوگل بزنید: عملیات atomic یعنی چه؟)خوب حالا چجوری atomic ش کنیم؟Semaphores and Other Forms of Mutual Exclusionسمافور چیزیه که فقط یک نفر میتونه در یک لحظه صاحبش باشه. ما میتونیم یک سمافور بسازیم و اونو برای مدیریت منابع خاص استفاده کنیم، توی مثال بالا میتونیم یک سمافور برای کنترل موجودی پای سیب بسازیم.به کد زیر نگاه کنید، عموما به عملیات گرفتن سمافور P و عملیات آزادسازی اون V میگن، امروزه توی زبونای برنامه نویسی کلمات کلیدی مثل lock/unlock و claim/release و ... استفاده میشه.case_semaphore.lock()if display_case.pie_count &gt; 0  promise_pie_to_customer()  display_case.take_pie()  give_pie_to_customer() endcase_semaphore.unlock()خوب فرض کنید حالا این کدو هر دو گارسون همزمان اجرا کنن، اونی که اول به لاک کردن سمافور میرسه میتونه ادامه کدو اجرا کنه و طبق روال اجرا میشه ولی اونی که دوم میرسه باید wait بمونه تا سمافور ازاد بشه و بتونه کدو اجرا کنه. با این کد میتونیم با خیال راحت به موجودی پای سیب اتکا کنیم و گارسون هم قول الکی به مشتری نمیده.Make the Resource Transactionalطراحی بالا ی مقدار ضعیفه چون مسئولیت کنترل دسترسی سمافورو به کسی که ازش استفاده میکنه میده، بیاید تغییرش بدیم و کنترلش رو مرکزی کنیم. برای این کار باید قسمتی که گارسون میخاد تعدادو چک کنه پشت یک فانکشن میبریم:slice = display_case.get_pie_if_available() if slice  give_pie_to_customer() enddef get_pie_if_available()if @slices.size &gt; 0update_sales_data(:pie)return @slices.shiftelse # incorrect code!falseendendبا این کد ما دسترسی و چک کردن ریسورس موجودی پای سیبو به یک جای مرکزی منتقل کردیم ولی هنوز این تابع میتونه توسط چندین thread کال بشه و نیاز داریم که با سمافور محافظتش کنیم:def get_pie_if_available()  @case_semaphore.lock()  if @slices.size &gt; 0  update_sales_data(:pie)  return @slices.shift  else  false  end  @case_semaphore.unlock() endاما این کد هم میتونه درست نباشه، اگر update_sales_data خطا بخوره، سمافوری که لاک شده هیچ وقت آنلاک نمیشه و باز میمونه و تمام دسترسی های بعدی به پای سیب waitمیمونه. به این شکل هندلش میکنیم:def get_pie_if_available()@case_semaphore.lock()try {  if @slices.size &gt; 0  update_sales_data(:pie)  return @slices.shift  else  false  end }ensure {  @case_semaphore.unlock()} endMULTIPLE RESOURCE TRANSACTIONSحالا فرض کنید که مشتری از گارسون یک بستنی و یک پای سیب بخاد، گارسون باید موجود بودن جفتشو بررسی کنه. فرض کنید کدو به شکل زیر تغییر میدیم:slice = display_case.get_pie_if_available()scoop = freezer.get_ice_cream_if_available() if slice &amp;&amp; scoop  give_order_to_customer() endاین درست کار نمیکنه، فرض کنید اگر درخواستمون واسه پای سیب اوکی باشه ولی بستنی تموم شده باشه، خوب ما نمیتونیم پای سیب و نگه داریم و به دردمونم نمیخوره به تنهایی، با این فرض که مشتری جفتشو باهم میخاسته.کدو به این شکل تغییر میدیم:slice = display_case.get_pie_if_available() if slice  try {  scoop = freezer.get_ice_cream_if_available()  if scoop  try {  give_order_to_customer()  }rescue {  freezer.give_back(scoop)}End}rescue {  display_case.give_back(slice)} endاما بازم این ایده آل نیست. این کد زشتیه. بیزنس لاجیک خیلی سخت و شکننده پیاده شده. قبلا ما این مشکلو با انتقال کد چک کردن موجودی منابع توی خود منابع حل کردیم(همون فانکشن جدایی که براش نوشتیم). خوب اینجا با دو تا منبع سر و کار داریم، حالا کد چک کردن موجودی رو ببریم توی کلاس بستنی یا توی کلاس پای سیب؟ جواب نه هست. توی هیچکدوم نمیبریمش. روش عملگرایانه اش اینه که ببریمش توی یک ماژول جدید، و به شکلی کال بشه که کلاینت درخواست بده: به من یک بستنی و پای سیب بده، و خروجی ساکسید یا فیل باشه. و قطعا این ماژول رو باید به شکل جنریک بنویسیم که همه ایتم های منو و همه ترکیب ها رو فرمولیزه کنه.OTHER KINDS OF EXCLUSIVE ACCESSخیلی از زبون های برنامه نویسی کتابخونه هایی دارن که بهمون کمک میکنه به شکل انحصاری با حافظه های مشترک سر و کله بزنیم، که همین روش سمافور و مانیتورز رو به شکل راحت بهتون میده. بعضی از زبون ها هم یکسری امکانات پیشفرض شون بهتون این امکان رو میده که راحت تر با متغیرها کار بکنید مثل بحث  ownership در زبون برنامه نویسی Rust، که تضمین میکنه هر متغیر در یک لحظه فقط متعلق به یک آبجکته.DOCTOR, IT HURTS…اگر هیچ چیزی از این درس دستگیرت نشد، فقط همین یک مطلبو بگیر: برنامه نویسی پارالل و همزمانی، با منابع داده مشترک کار سختیه و مدیریتش توسط خودتونم کلی چالش داره. اینجاست که اون جوک قدیمی رو جا داره بگیم:دکتر، این آسیب رسوند بهم وقتی اون کارو کردم.دکتر هم میگه: خوب نکن اون کارو.توی درسای بعدی راه هایی رو میگیم که بهمون سود بیشتری از همزمانی میده، البته بدون درد.دروس مرتبط: 10, 38, 28منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Thu, 04 Mar 2021 23:58:06 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 33</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-33-yijbttdfchcu</link>
                <description>Concurrency به این معنیه که دو یا چند تسک، استارت، اجرا و تموم میشن با همپوشانی زمانی بین اونها، یعنی هیچ تسکی بلاک نمیشه تا تسک دیگه اجرا بشه. مثل پیاده سازی async .مفهومی هم به اسم parallelism وجود داره که مربوط به وقتی میشه که واقعا تسک ها به صورت همزمان در حال اجرا هستند. برای اینکه parallelism داشته باشیم، نیاز داریم به سخت افزارهایی که بتونن چند کارو همزمان انجام بدن. CPU های چند هسته ای، یا چند CPU یا چند کامپیوتر متصل به هم.قطعا نرم افزاری که برای دنیای واقعی بخایم بنویسیم باید concurrent باشه، چون تسک هایی که توی سیستم رخ میده، مثل کال کردن یک سرویس خارجی، فچ کردن دیتای دیتابیس، interact کاربر با یوزر اینترفیس، اینها نمیتونه سریال انجام بشه و سیستم قفل بشه بابت انجام هر کدوم از این تسکها، و اگر concurrent پیاده سازی نکنیم، هم کیفیت اجرایی سیستم به شدت پایین میاد هم نمیتونیم از حداکثر توان سخت افزار بهره ببریم و هرز رفتیم.تو این فصل میخایم به concurrency و parallelism بپردازیم.درس 33: شکستن اتصال زمانی Breaking Temporal Couplingزمان معمولا وجه نادیده گرفته شده‌ ایه توی معماری نرم افزار. تنها زمانی که ما درگیرش میشیم، زمان بندی کلی پروژه است که کی تاریخ رسوندن یک فیچره، کی تاریخ لانچ یک ماژوله و ...، این زمان در اینجا مورد بحث ما نیست.در اینجا، ما در مورد نقش زمان توی طراحی هر کدوم از عنصرهای نرم افزار صحبت میکنیم، دو تا جنبه مهم وجود داره: concurrency و ordering (ترتیب و موقعیت نسبی چیزها)ما معمولا از این جنبه ها، به مسئله نگاه و فکر نمیکنیم، عموما برنامه نویس ها وقتی میشینن و به طراحی و معماری یک سیستم فکر میکنند، به شکل خطی فکر میکنند(linear)، اول این اجرا بشه، بعد اون اجرا بشه ، بعد ...اما این مدلی فکر کردن به temporal coupling ختم میشه، وابستگی در زمان (coupling in time).(قبلا گفته شد هر مدلی از coupling بده، چون وابستگی ها توی سیستم باعث میشن که تغییرات شکننده و سخت بشه، و کلا زندگیه سیستمو سخت میکنه، کلا به این کلمه coupling حساس باشین، راجعش زیاد بخونید و راهکارهایی که کمش کنید توی سیستم)مثلا: متود A باید کال بشه قبل از متود B، فقط یک گزارش در یک زمان میتونه در حال اجرا باشه، شما برای ui باید صبر کنید تا بازسازی بشه قبل اینکه باتن کلیک رسپانسش بیاد و ... این مدلی نه انعطاف وجود داره و نه واقع گرایانه است.LOOKING FOR CONCURRENCYتوی خیلی از پروژه ها برای اینکه تحلیل کنیم سیستمو و به مدل برسیم برای طراحی، نیاز داریم تا ورک فلوهای سیستم رو در بیاریم، توی این ورک فلوها مشخص میشه چه کارهایی دقیقا باید همزمان رخ بده و یا ترتیب دقیق اجرا چی باشه. یکی از ابزارهایی که برای این کار استفاده میشه activity diagram ها هستن.یک دیاگرام اکتیویتی از یک سری اکشن ها که به شکل مستطیل نمایش داده میشن و یک سری خطوط که اکشن ها رو بهم وصل میکنه و ترتیب اجرا رو مشخص میکنه، تشکیل داده میشن. همچنین یکسری خطهای synchronization bar وجود داره، که مشخص میکنه وقتی چند تا تسک اجراشون تموم شد، اونوقت تسک بعد از این bar اجرا بشه. این مدل نمودار خیلی بهتون کمک میکنه تا عملیات های پارالل رو دیتکت کنید.به عنوان مثال یک سیستم رباتیک برای ساخت یک شیک بستنی در نظربگیرید، مراحل ساختش به این شکله:1. Open blender2. Open piña colada mix3. Put mix in blender4. Measure 1/2 cup white rum5. Pour in rum6. Add 2 cups of ice7. Close blender8. Liquefy for 1 minute9. Open blender10. Get glasses11. Get pink umbrellas12. Serveقطعا یک بارتندر اگر بخاد مراحلو به همین ترتیب و پشت سر هم اجرا کنه، اخراجه. چون مبرهنه که خیلی از مراحلو میشه همزمان انجام داد و معطل یک چیز نشیم و همزمان که داره یک کاری انجام میشه، یک کاره دیگه رو هم جلو ببریم و ...اکتیویتی دیاگرام این مسئله به این شکله:طبق این دیاگرام و همچنین چیزی که توی واقعیت هم توسط یک بارتندر انسان انجام میشه، تسک هایی مثل 1 2 4 10 و 11 میتونن همزمان اجرا بشن، و بعدش تسک های 3 5 و 6 میتونن بعدش پارالل اجرا بشن.OPPORTUNITIES FOR CONCURRENCYاکتیویتی دیاگرام ها مناطق مستعد برای concurrency رو نشون میدن، اما در مورد اینکه ایا اون نقاط ارزش این مدل پیاده سازی رو دارند یا نه، چیزی رو نشون نمیدن. مثلا توی مثال شیک بستنی، یک بارتندر باید 5 تا دست داشته باشه که بتونه تسک های اولیه رو همزمان انجام بده. اینجاست که پای design میاد وسط، وقتی به تسک ها نگاه میکنیم، و مطلع باشیم از اون فعالیت، در مثال قبل تسک 8 liquify، یک دقیقه طول میکشه، طی اون زمان بارتندر میتونه لیوان و بگیره(تسک10) و چتر صورتی رم جور کنه(تسک11)، تازه شاید برای تسک مشتری دیگه ای هم وقت داشته باشه اون وسط. ما دنبال تسک هایی میگردیم توی دیزاین concurrency که بیشتر طول میکشه اجراشون، مثلا کوئری سنگین دیتابیس، کال کردن سرویس خارجی، منتظر بودن برای ورودی کاربر و .. همه اینا پتانسیل هایی رو ایجاد میکنه که از سی پی یو بهینه تر کار بکشیم و کیفیت بهتری ارائه بدیم.OPPORTUNITIES FOR PARALLELISMاینو همیشه بخاطر بسپارید همزمانی(concurrency) یک مکانیزم نرم افزاریه و موازی سازی(parallelism) یک عملیات سخت افزاری، اگر سی پی یو چند هسته ای دارید یا از چندین سی پی یوی لوکال یا ریموت استفاده میکنید، میتونید کارها رو بشکنید روی کورهای مختلف پردازنده ها تا سرعت انجام کارها رو کاهش بدید.معمولا جاهایی ایده آله که از پاراللیسم بریم که کارهایی که میخایم انجام بدیم از هم مستقلند و به هم وابستگی ندارن و برای هم منتظر نمیشن. پترن عمومیش اینجوری که کارهای بزرگو بشکنید به کارهای کوچیک مستقل، اونها رو به صورت پارالل پردازش کنید و بعد هم خروجی شون رو ترکیب کنید تا به نتیجه مطلوب برسید.DENTIFYING OPPORTUNITIES IS THE EASY PARTمعمولا راحت ترین قسمت کار، شناسایی جاهایی که میتونیم از همزمانی یا موازی سازی استفاده کنیم، و قسمت مهمتر و سخت ترش هم میشه اینکه چجوری این رو به صورت امن پیاده سازی کنیم، که مفصل توی درسهای بعد بررسیش میکنیم.دروس مرتبط: 10, 26, 28, 36منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Mon, 01 Mar 2021 23:03:27 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس32</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B332-mjziec74k5k9</link>
                <description>درس 32: Configurationوقتی کد وابسته است به مقادیری که ممکنه بعد از لایو شدن اپلیکیشن، تغییرشون بدیم، این مقادیرو بیرون از کد نگه دارید. وقتی سیستم شما ممکنه توی محیطهای مختلف و برای مشتریهایی با نیازهای متفاوت لانچ بشه، این مدل متغیرها رو خارج از اپلیکیشن نگه میداریم. با این کار اپلیکیشن پارامترالایز میشه و راحت میتونیم توی محیط های مختلف خیلی راحت آداپت(adapt) و استفادش کنیم.•  Parameterize Your App Using External Configurationمعمولا چیزهایی که ممکنه توی کانفیگوریشن ها بزارید شامل:-  آدرس و اطلاعات لاگین سرویسهای خارجی مثل دیتابیسها، api ها و ...-  تنظیم سطح لاگینگ-  اطلاعات پورت و ای پی و نام کلاستری که اپ ازش استفاده میکنه-  ولیدیشن های مختص محیط اجرا-  برخی از پارامترهای عمومی و کلی برنامه مثل نرخ مالیات در بیزنس و ...-  کلیدهای لایسنسو ...به طور کلی هر چیزی که فکر میکنید ممکنه تغییر بکنه توی شرایط و محیطهای مختلف رو از کد در میاریم و میبریم توی کانفیگ ها.STATIC CONFIGURATIONخیلی از فریمورک ها و اپلیکیشن های کاستوم، کانفیگوریشن ها رو در فایل تکست و دیتابیس نگهداری میکنند.(برخی در فایل و برخی در دیتابیس). عموما برای فایلهای تکست از فرمت های محبوب تر مثل YAML یا JOSN استفاده میشه. اگر تنظیمات مدلی هست که باید توسط مشتری تغییر پیدا کنه، مثل همون نرخ مالیات که مثال زدیم، این مدل تنظیم بهتره توی دیتابیس نگهداری بشه.به هر سبکی که تنظیمات رو نگهداری کنیم، بایستی در لود اولیه برنامه، تنظیمات هم لود بشن و توی رفتار سیستم تاثیرشونو بزارن. ممکنه یک ساختار دیتای گلوبال براشون در نظر بگیرید، اما ما ترجیحمون به این نیست. راه بهتر اینه که تنظیمات رو پشت یک api رپ کنید. این باعث جداسازی(decoupling) کد، از جزئیات کانفیگوریشن میشه.CONFIGURATION-AS-A-SERVICEبا اینکه روش قبل مرسوم و جا افتاده است، در اینجا میخایم روش متفاوتی رو مطرح کنیم. اینکه قطعی و مبرهنه که همچنان ما تنظیمات رو از کد برنامه جدا نگه میداریم، ولی بجای نگهداری توی file ، میخایم ببریمشون پشت یک service api . این روش یکسری مزیت داره:-  اپلیکیشن های مختلف میتونن تنظیمات رو با هم شیر(share) کنن، حتی با اعمال محدودیت و مجوز که باعث بشه هر اپلیکیشنی سطح خاصی از تنظیماتو ببینه-  تغییر دادن مقادیر تنظیمات منعطف تر میشه-  برای مدیریت و تغییر مقادیرشون میتونیم هر مدل UI ای رو طراحی کنیم-  باعث داینامیک شدن تنظیمات میشهاخرین مورد، که میگه باعث داینامیک شدن تنظیمات میشه، در اپلیکیشن هایی که خیلی حساسیت بالایی دارند و همیشه باید up باشند، خیلی کمک میکنه، چون تغییر تنظیمات کاملا جدا شده است و راحت مدیریت میشه و سیستم نیازی به restart برای لود مجدد تنظیمات هم نداره.DON’T WRITE DODO-CODEبدون کانفیگوریشن های خارج از برنامه، کدتون نمیتونه خودشو با شرایط و نیازهای مختلف وفق بده و منعطف نخاهد بود، این خیلی بده. نه؟ قطعا چنین کدی توی دنیای واقعی سرانجامش مرگه. دودو یک پرنده بدون پرواز منقرض شده است که توی شرق ماداگاسکار در اقیانوس هند زندگی میکرده، که طی تغییرات زیستی جهان، نتونست سازگار باشه و به کل منقرض شد. نزارید کد و پروژه تون مثه دودو باشه.دروس مرتبط: 9, 14, 16, 28منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Fri, 26 Feb 2021 11:24:59 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 31</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-31-tqj2xshrhnb9</link>
                <description>درس 31: مالیات وراثت Inheritance Taxآیا با زبونای برنامه نویسی شی گرا کد میزنید؟ آیا از شی گرایی استفاده میکنید؟اگر آره. دست نگه دارید. این احتمالا چیزی نیست که شما میخاید.بریم ببینیم چرا؟یک فلش بک بزنیم به گذشتهشی گرایی اولین بار توی زبون برنامه نویسی Simula 67 در سال 1969 میلادی (1347 شمسی) ایجاد شد. یک راه حل ظریف بود که در مسئله صف بندی ایونت ها با تایپ های مختلف، کارساز شد. و توی این زبان بود که از prefix classes استفاده شد. شما یک چنین چیزی باید مینوشتید:link CLASS car;... implementation of carlink CLASS bicycle;... implementation of bicycleدر اینجا link یک prefix class هستش که قابلیت linked list رو اضافه می کنه. این اجازه میده که ماشین و دوچرخه رو به لیستی اضافه کنید. توی این مکانیزم link یک کلاس پدر هست و هر دو کلاس ماشین و دوچرخه پیاده سازی میکنن link رو و کدش رو به ارث بردن.بعدتر در زبون برنامه نویسی SmallTalk 72 نوع دیگه ای شی گرایی رو داشتیم، که Alan Kay یکی از سازنده هاش توی سایت Quora سال 2019 اینجوری راجبش توضیح داد: ما دنبال راه دیگه ای بودیم، که به صورت آزمایشی روش داینامیک مثل زبون Lisb رو اعمال کردیم.زبونهای C++ و جاوا سبک شی گرایی شون ادامه راهه Simula هست که تفکرش به این شکله که از شی گرایی برای ترکیب کردن تایپ ها استفاده میکنه. و در سبک SmallTalk شی گرایی dynamic organization of behaviors هستش که در زبونهای Ruby و JavaScript این سبک پیگیری شد.در استفاده از شی گرایی، معمولا ما با دو دسته برنامه نویس طرف هستیم: اونهایی که typing رو دوست ندارن یا اونهایی که برعکس دوست دارند.(تایپ به منظور ساختار داده)دسته اول که دوست ندارن از این بابته که مجبور به نوشتن تایپ های جدید یا طولانی نشن و از تایپ های بیس فانکشنالیتی ها رو ارث ببرن. دسته دومم که دوست دارند از این بابت که روابط بین داده ها رو به درستی اعمال کنند مثلا a Car is-a-kind-of Vehicle** متاسفانه هر دو نوع شی گرایی، مشکلاتی به همراه داره.· مشکلات شی گرایی برای share کردن کدشی گرایی وابستگی است(coupling). نه تنها کلاس فرزند وابسته است به کلاس والدش و همچنین والدهای والدش، بلکه کدی که از اون کلاس فرزند استفاده میکنه هم درگیر کل اون مسیر والدها هستش. این مثالو ببینید:class Vehicledef initialize@speed = 0enddef stop@speed = 0enddef move_at(speed)@speed = speedendendclass Car &lt; Vehicledef info&quot;I&#x27;m car driving at #{@speed}&quot;endend# top-level codemy_ride = Car.newmy_ride.move_at(30)وقتی کد top-level اینو کال میکنه move_at متود در کلاس vehicle کال میشه یعنی کلاس والد car. حالا فرض کنید برنامه نویس طبق تسکی کلاس vehicle رو تغییر میده و move_at تبدیل به تابع set_velocity میشه و متغیر @speed هم به @velocity تغییر میکنه. این تغییر باعث خطا توی تمامی کلاینتهایی که از کلاس vehicle استفاده کردن، میشه. اما خوده کلاسش که خطایی نداره و صرفا تغییر کرده.وابستگی زیاد So much coupling.حالت بدترش ارث بری چندگانه است، که یک کلاس از چند کلاس ارث ببره، توی C++ این وجود داره و دردسرهای زیادی هم بوجود میاره، زبونهای شی گرای مدرنتر این رو پیاده سازی نکردند.Don’t Pay Inheritance Tax· راه های جایگزین بهترنددر اینجا سه تکنیک رو برسی میکنیم که باعث میشه دیگه نیازی به استفاده از شی گرایی نداشته باشید.- Interfaces and protocols- Delegation- Mixins and traits· Interfaces and protocolsاکثر زبونای برنامه نویسی شی گرا این امکانو میدن که کلاسها بتونن رفتارشون رو از جاهای مختلفی به ارث ببرند و موظف به پیاده سازی برای اون رفتار بشن، مثلا فرض کنید کلاس car رو که هم رفتار drivable رو پیاده سازی میکنه هم locatable. سینتکس این مثال توی زبون جاوا به شکل زیره:public class Car implements Drivable, Locatable { // Code for class Car. This code must include// the functionality of both Drivable// and Locatable }drivableو locatableهر دو در جاوا اینترفیس هستند، زبونهای دیگه هم اینترفیس رو به شکل های مختلف دارند و در بعضی زبون ها بهش میگن protocols. اینترفیس ها به شکل ذیل نوشته میشن:public interface Drivable {  double getSpeed();  void stop();}public interface Locatable() {  Coordinate getLocation();  boolean locationIsValid();}تعریف اینترفیس ها کد نداره، فقط امضای متود در اینترفیس میاد و مشخص میکنه کلاسی که میخاد این اینترفیس رو ارث ببره باید این متودها رو پیاده سازی کنه.چیزی که اینترفیس ها رو قدرتمند میکنه، اینه که میتونیم ازشون بجای تایپ ها استفاده کنیم، هر کلاسی که اینترفیس خاصی رو پیاده سازی میکنه، با اون تایپ سازگار میشه. اگر ماشین و تلفن هر دو اینترفیس locatable رو پیاده سازی کنن، ما میتونیم هر دوی این ها رو توی یک لیست از locatable نگهداری کنیم.List&lt;Locatable&gt; items = new ArrayList&lt;&gt;();items.add(new Car(...));items.add(new Phone(...));items.add(new Car(...)); // ...و بعد با خیال راحت میتونیم لیستو پراسس کنیم، چون مطمئنیم هر ایتم توابع getLocation و locationIsValid رو پیاده سازی کرده.ترجیح به اینه که polymorphism (چندریختی)  رو با اینترفیس ها پیاده سازی کنید و از ارث بری استفاده نکنید.· Delegationارث بری برنامه نویس ها رو به سمتی میبره که کلاسهایی مینویسن که متودهای زیادی داره، اگر کلاس والد 20 متود داشته باشه، و کلاس فرزند فقط 2 تاشو لازم داشته باشه، ابجکت کلاس فرزند الکی 18 متود اضافی رو یدک میکشه. مثال زیرو در نظر بگیرید:class Account &lt; PersistenceBaseClass endکلاس اکانت الان تمامی فانکشنهای کلاس persistence رو ارث میبره، حالا فرض کنید با delegation این حرکتو بزنیم:class Account  def initialize(. . .)  @repo = Persister.for(self)  end  def save  @repo.save()  endendبا این کار دیگه کل توابع پرسیستنس رو توی کلاس اکانت نمیاریم، اما اصل جداسازی(decoupling) رو نقض کردیم که! اما چیز فراتری وجود داره. با اینکار ما دیگه زیر تعهده persistence api نیستیم و میتونیم api خودمونو هرآنچه دقیقا لازم داریم، راحت پیاده سازی کنیم. شاید بگید خوب به روش اینترفیس هم میشد، اما اینجوری خیالمون راحته که اگر حتی interface هم بای پس شد، زیر چتر persistence نمیریم و کنترل کلاس خودمونو داریم.میتونیم فراتر بریم، آیا لازمه که یک اکانت اطلاعات persist رو خودش نگه داره؟ مگه کارش نگهداری و مدیریت بیزنس رول های یک حساب نیست؟class Account  # nothing but account stuffendclass AccountRecord  # wraps an account with the ability  # to be fetched and stored endبا این مکانیزم حالا واقن جداسازی(decoupling) رو داریم، اما برامون هزینه هم داشت. کد بیشتری باید بنویسیم،  و بعضیاشونم تکراری اند، مثلا این یک نیازه که همه کلاسهای رکوردمون یک تابع find داشته باشن.خوشبختانه مشکل اینجارو هم mixins و traits برامون حل میکنن.· Mixins, Traits, Categories, Protocol Extensions, …به عنوان یک صنعت، ما هم عاشق اینکاریم که برای هر چیزی اسم تولید کنیم، هرچند که به یک چیز نامهای مختلف بدیم. هر چی بیشتر بهتر. افتاد؟ ?در مورد mixins ها همینطوره. ایده اونها خیلی ساده است: ما میخایم آبجکتها و کلاس ها رو گسترش بدیم و بهشون فانکشنالیتی اضافه کنیم، بدون ارث بری.در نتیجه یک سری فانکشن دسته بندی شده می نویسیم، به هر دسته یک اسم میدیم، و بعد یک کلاس رو با اون دسته فانکشن اکستند میکنیم.(اینکه اکثر این جملات رو فینگیلیش مینویسم چون اگر ترجمه معادل این کلمات به درد میخورد که ترجمه های جعفرنژاد قمی یا سالخورده حقیقی هم به درد میخورد? . و اصولا کسی که با برنامه نویسی اشنا هست بهتر میفهمه داستانو با همین کلمات پرکاربرد تخصصی. بگذریم)توی این حالت شما کلاسهایی میسازید که ترکیبی از امکانات خودشون و mixins ها رو دارند. ممکنه اسم و نحوه پیاده سازی این فیچر توی زبونهای مختلف فرق بکنه.  نکته مهم اینه که از mixins نمیشه آبجکت ساخت بلکه فقط کارشون و ذاتشون اضافه کردن قابلیت هاست به کلاسها و آبجکت های دیگه.برای مثال برگردیم به همون مثال account، در اونجا AccountRecord باید هم از account مطلع میبود هم از persistence framework و نیاز داشت تا متودهایی persistence layer رو دلیگیت کنه، اونایی رو ک میخاست برای بیرون خودش استفاده کنه.با mixins ها اینجوریه که به عنوان مثال ما یک mixins مینویسیم که دو سه تا از متودهای استاندارد finder رو پیاده سازی کنه. و بعد به AccountRecord اضافه شون میکنیم به عنوان mixins.mixin CommonFinders {  def find(id) { ... }  def findAll() { ... }end class AccountRecord extends BasicRecord with CommonFinders class OrderRecord extends BasicRecord with CommonFindersمیتونیم پارو فراتر بزاریم و به این فکر کنیم که هر آبجکت بیزنس لاجیکی نیاز به ولیدیشن داره تا از دیتای اشتباه و یا خراب جلوگیری کنه. اما منظورمون از ولیدیشن دقیقا چیه؟اگر یک account رو مثال بزنیم، لایه های مختلفی از ولیدیشن وجود داره که میتونه اعمال بشه:- چک کردن پسورد هش شده اکانت برای اطمینان از لاگین بودن کاربر- ولیدیشن دیتای ورودی یوزر هنگام ایجاد اکانت- ولیدیشن سازگاری نوع داده هایک راه معمول(هرچند که از ضم ما ایده آل هم نیست) اینه که همه ولیدیشن ها رو بیاریم توی یک کلاس. ما فکر میکنیم راه بهترش استفاده از mixins هاست برای ساخت کلاسهایی برای شرایط خاص:class AccountForCustomer extends Account  with AccountValidations,AccountCustomerValidations class AccountForAdmin extends Account  with AccountValidations,AccountAdminValidationsدر اینجا، هر دو کلاس فرزند، ولیدیشن های عمومی آبجکت account رو با خودشون دارند و به صورت اتوماتیک بهشون اپلای میشه.- از mixins ها برای انتشار فانکشنالیتی استفاده میکنیم.خوب ما سه روش جایگزین برای ارث بری سنتی رو گفتیم، شما باید بسنجید که کدوم روش در کجا به کارتون میاد و حداکثر کارایی و تمیزی رو بهتون میده، همچین اینو مدنظرتون داشته باشید که نگاه 0 و 1 نداشته باشید و یک روش رو کلا کنار نزارید و همیشه بالا پایین کنید تمام راه های ممکن رو.دروس مرتبط: 8, 10, 28منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Wed, 24 Feb 2021 00:43:24 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 30</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-30-wxy1agoaobqe</link>
                <description>درس 30: Transforming Programmingتمام برنامه ها تبدیل اطلاعاتو انجام میدن، پردازش و تبدیل ورودی ها به خروجیها، اما به ندرت وقتی به طراحی فکر میکنیم به این بعد سیستم نگاه میکنیم و اکثرا تمرکزمون روی کلاسها، ماژولها، ساختار داده، الگوریتم، زبان برنامه نویسی و فریمورک هاست.ما عقیدمون اینه که اگر یک قدم به عقب برگردید و به این فکر کنید که سیستم قراره چه ورودی و خروجیهایی داشته باشه، خیلی مسیرو واضح تر میکنه، خیلی از نگرانی هایی که داشتیمو روشن و یا حل میکنه، خطایایی راحت تر و همچنین وابستگی رو هم کاهش میده.فرض کنید به یک برنامه نویس یونیکس در سال 1970 میگید که برنامه ای بنویسه که لیست 5 تا فایله بزرگ یک مسیر فولدری رو بهتون خروجی بده، شما فکر میکنید که یک ادیتور باز میکنه و شروع میکنه به زدن کد C، اما در واقعیت اون توی ترمینال ی همچین کامندی رو میزنه:$ find . -type f | xargs wc -l | sort -n | tail -5این کامند شامل یکسری تبدیلهاست(transformations).find . -type fلیستی از فایلهای داخل مسیر (.) رو خروجی میدهxargs wc -lورودی رو میخونه و در خروجی تعداد خط و نام فایل رو بهمون میدهsort -nسورت میکنه ورودی رو، با این فرض که هر خط با یک نامبر شروع میشه برا همین دش ان رو به عنوان اپشن بهش دادیمtail -5ورودی رو میخونه و 5 خط اخرش رو توی خروجی نمایش میدهبه عنوان مثال ی همچین خروجی رو بهمون میده:470 ./debug.pml470 ./test_to_build.pml487 ./dbc.pml719 ./domain_languages.pml727 ./dry.pmlبرای گرفتن این خروجی مدنظرصورت مسئله، این سری تبدیل ها انجام شد:directory name → list of files → list with line numbers → sorted list → highest five** برنامه نویسی حول محور کد است و برنامه ها حول محور داده.· تبدیل ها رو پیدا کنید FINDING TRANSFORMATIONSمعمولا ساده ترین راه برای پیدا کردن تبدیلها اینه که به نیازمندیهای سیستم فکر کنیم و ورودی و خروجی هاشون. بعد میتونید به قدمهایی که لازمه برای اینکه از ورودی به خروجی برسید فکر کنید. این یک نگاه از بالا به پایینه.فرض کنید میخاید یک سایت بازی برای مردم درست کنید که توش با انتخاب حروف الفبا کلمه سازی کنند. ورودی تون لیستی از حروف الفباست و خروجی هم لیستی از کلمات دو، سه، چهار و ... حرفی.اره این خروجیای سمت راست عکس کلمه ان، حداقل توی دیکشنری مک اواس ?ما یک دیکشنری از کلمات داریم که با سیگنچر(signature) گروه بندی شدن، در نتیجه هر دو کلمه ای که تمام حروفشون مثل هم باشه سیگنچر یکسان هم خاهند داشت. ساده ترین متود محاسبه سیگنچر هم اینه که که یک لیست سورت شده از حروف هر کلمه رو خروجی بده. ما رشته ورودی رو میگیریم سیگنچرش رو حساب میکنیم، بعد چک میکنیم ایا کلمه ای با این سیگنچر وجود داره یانه.بنابرین ریشه یاب کلمه ها به 4 تبدیل شکسته میشه:به مرحله 1 اگر نگاه کنید، که یک کلمه میگیره و تمام ترکیب های مختلف سه چهار پنج و .. حرفی شو لیست میکنه، این مرحله خودش میشکنه به تبدیل های زیر:خوب به نقطه ای رسیدیم که خیلی راحت میتونیم هر تبدیلو پیاده سازی کنیم:(نمونه کد به زبون Elixir)function-pipelines/anagrams/lib/anagrams.exdefp all_subsets_longer_than_three_characters(word) do word|&gt; String.codepoints()|&gt; Comb.subsets()|&gt; Stream.filter(fn subset -&gt; length(subset) &gt;= 3 end)|&gt; Stream.map(&amp;List.to_string(&amp;1)) endاپراتور |&gt;توی زبون Elixirبرای پایپلاین(pipeline) استفاده میشه. کاری که میکنه اینه که مقدار سمت چپش رو به عنوان اولین پارامتر فانکشن سمت راستش پاس میده، توی اکثر زبونها به شکل های مختلف این پایپ لاین رو داریم ممکنه حتی نحوه و سمت پاس دادنشون هم متفاوت باشه مثلا اپراتور پایپلاین توی زبونهایElm, F#, Swiftمثه همین Elixirهست، توی Clojure -&gt; هست یا توی R به این شکل %&gt;% ، بگذریم...توی زبون Elixir این:&quot;vinyl&quot; |&gt; String.codepoints |&gt; Comb.subsets()از نظر نحوه اجرا و پاس دادن مقادیر به این معنیه:Comb.subsets(String.codepoints(&quot;vinyl&quot;))معمولا جاهایی که از پایپ لاین استفاده میکنید یک تبدیل داده وجود داره.حالا به مرحل 2 ام برنامه نگاه کنید ترکیب کلماتو به سیگنچر تبدیل میکنیم، بازم تبدیل داریم. به این شکل:ادامه کدو بریم:function-pipelines/anagrams/lib/anagrams.exdefp as_unique_signatures(subsets) do subsets|&gt; Stream.map(&amp;Dictionary.signature_of/1) endحالا لیست سیگنچرها رو تبدیل میکنیم، هر سیگنچر یک لیست مپ شده از کلمه های ممکن رو نگهداری میکنه، یا ممکنه حتی nil نگهداری کنه به این معنی که کلمه ای باهاش مچ نمیشه که البته بعدش نالها رو حذف و لیستو فلت میکنیم:function-pipelines/anagrams/lib/anagrams.exdefp find_in_dictionary(signatures) do signatures|&gt; Stream.map(&amp;Dictionary.lookup_by_signature/1) |&gt; Stream.reject(&amp;is_nil/1)|&gt; Stream.concat(&amp;(&amp;1)) endمرحله 4، گروه بندی کردن کلمات براساس طولشون، یک تبدیل ساده است که داریم. و همچنین کانورت لیست مون به مپ به صورتی که کلید این مپ میشه طول رشته و ولیوش میشه خوده کلمه:function-pipelines/anagrams/lib/anagrams.exdefp group_by_length(words) do words|&gt; Enum.sort()|&gt; Enum.group_by(&amp;String.length/1) end** نکته: ممکنه زبون برنامه نویسی که استفاده میکنید پایپ لاین نداشته باشه، اصن مهم نیست، تبدیل داده در برنامه نویسی یک فلسفه است، حالا اگر ابزار پایپ لاین هم در اختیارتون نباشه، کدو مثل زیر مینویسید سه خط دستور جدا:const content = File.read(file_name); const lines = find_matching_lines(content, pattern) const result = truncate_lines(lines)خوب ما همه تبدیل ها رو جدا جدا نوشتیم، وقتشه که همه رو سرجمع کنیم توی یک تابع و بدنه اصلی رو بنویسیم:function-pipelines/anagrams/lib/anagrams.exdef anagrams_in(word) doword|&gt; all_subsets_longer_than_three_characters()|&gt; as_unique_signatures()|&gt; find_in_dictionary()|&gt; group_by_length()endی اجرا بگیریم ازش:iex(1)&gt; Anagrams.anagrams_in &quot;lyvin&quot; %{3 =&gt; [&quot;ivy&quot;, &quot;lin&quot;, &quot;nil&quot;, &quot;yin&quot;],4 =&gt; [&quot;inly&quot;, &quot;liny&quot;, &quot;viny&quot;],5 =&gt; [&quot;vinyl&quot;]}عالیه. به تابع اصلی که نگاه کنید(anagrams_in) یک زنجیره ای از تبدیل ها رو میبینید که طبق براورده شدن خاسته مون پیش میره، هر کدوم ورودی شونو از تبدیل قبل و خروجی شونو به تابع بعدی میدن. خیلی ام خوانا و روتینه.اما یک نکته عمیق تری وجود داره، اگر با برنامه نویسی شی گرا آشنا باشید، نسبت به مخفی کردن دیتاها داخل آبجکت ها عکس العمل نشون میدید، و در نهایت یکسری آبجکت داریم که با آبجکت قبل و بعدشون پچ پچ میکنن و استیت همو تغییر میدن. این وابستگی(coupling) زیادی رو بوجود میاره. برای همینه که تغییر در سیستم های شی گرا خیلی سخت تره.در مدل برنامه نویسی transformationalبجای اینکه داده ها رو توی pool های پخش شده در سیستم نگهداری کنیم، داده ها رو مثل رودخونه جریان میدیم، کد -&gt; دیتا -&gt; کد -&gt; دیتادیتا به یک تابع خاص اختصاص نداره، بلکه توابع ورودی رو به خروجی تبدیل و به تابع بعدی میدن. این تا حد زیادی به کاهش وابستگی کمک میکنه، یک تابع فقط وقتی میتونه استفاده و استفاده مجدد بشه که ورودی و خروجیش با اون مکان استفاده مچ بشه. درسته هنوز حدی از وابستگی وجود داره ولی نسبت به تجربه ای که روی شی گرایی داشتیم، درجه وابستگی خیلی کمتره.· مدیریت خطاها رو چه کنیم؟خوب تبدیلهایی که نوشتیم درست کار کرد توی دنیایی که همه چی ایده ال و روبه راهه، چجوری توی دنیای واقعی ببریمش زیر بار؟ فکر کنید، وقتی زنجیره ای رو تشکیل دادیم، حالا میخایم خطایی رو در چک های منطقی کد پیدا کنیم.راه های مختلفی وجود داره، که همشون بر یک چیز تکیه می کنند: ما هیچ وقت دیتای خام پاس نمیدیم بین تبدیلها. در عوض دیتا رو توی قالب دیتا استراکچرها یا تایپها wrapمیکنیم که خیلی راحت valid بودنشون رو هم چک میکنیم. توی زبون Hasekllاین رپر maybeهست یا توی F# و Scala، optionهست. در اینجا دو راه توی کدنویسی پیش رو داریم، میتونیم چک کردن برای خطاها رو داخل تبدیل ها ببریم یا خارج اونها.- اول یک Representationانتخاب کنیدبرای رپرمون یک representationمیخایم، مثلا میتونیم یک struct برای داده مون بنویسیم یا زبون Elixirیک چیز قشنگ تر داره، اینکه تابع ها میتونن به عنوان خروجی یک tupleشامل{:ok, value}یا{:error, reason}برگردونن. مثلا تابع File.Openمیتونه یکی از این دو رو برگردونه یا خطا میده یام درست انجام میده که اوکی میده. توی نمونه کد ذیل ما از tuple ذکر شده بالا به عنوان رپر برای پاس دادن دیتا در پایپ لاین استفاده میکنیم:iex(1)&gt; File.open(&quot;/etc/passwd&quot;){:ok, #PID&lt;0.109.0&gt;} iex(2)&gt; File.open(&quot;/etc/wombat&quot;){:error, :enoent}- خطا رو داخل هر تبدیل هندل کنیدفرض کنید یک تابع میخایم بنویسیم که توی یک فایل خطوطی که با پترن خاصی مچ میشن رو برگردونه و بعد 20 کاراکتر اول رو ترانکیت کنه، این کد زیرو میزنیم:def find_all(file_name, pattern) doFile.read(file_name)|&gt; find_matching_lines(pattern)|&gt; truncate_lines() endخوب توی این تابع هیچ مدیریت خطایی نکردیم، اگر یک استپ توی پایپ لاین خطا برگردونه، هندلش نکردیم. کد زیر میشه همین تابع با مدیریت خطاها:defp find_matching_lines({:ok, content}, pattern) do content|&gt; String.split(~r/\n/)|&gt; Enum.filter(&amp;String.match?(&amp;1, pattern))|&gt; ok_unless_empty() enddefp find_matching_lines(error, _), do: error # ---------- defp truncate_lines({ :ok, lines }) do lines|&gt; Enum.map(&amp;String.slice(&amp;1, 0, 20))|&gt; ok() enddefp truncate_lines(error), do: error # ---------- defp ok_unless_empty([]), do: error(&quot;nothing found&quot;) defp ok_unless_empty(result), do: ok(result) defp ok(result), do: { :ok, result } defp error(reason), do: { :error, reason }- یا اینکه خطا رو توی پایپ لاین هندل کنیدبرای اینکار نیاز داریم function ها رو به function values تبدیل کنیم.defmodule Grep1 dodef and_then({ :ok, value }, func), do: func.(value)def and_then(anything_else, _func), do: anything_elsedef find_all(file_name, pattern) doFile.read(file_name)|&gt; and_then(&amp;find_matching_lines(&amp;1, pattern))|&gt; and_then(&amp;truncate_lines(&amp;1))enddefp find_matching_lines(content, pattern) docontent|&gt; String.split(~r/\n/)|&gt; Enum.filter(&amp;String.match?(&amp;1, pattern))|&gt; ok_unless_empty()enddefp truncate_lines(lines) dolines|&gt; Enum.map(&amp;String.slice(&amp;1, 0, 20))|&gt; ok()enddefp ok_unless_empty([]), do: error(&quot;nothing found&quot;)defp ok_unless_empty(result), do: ok(result)defp ok(result), do: { :ok, result }defp error(reason), do: { :error, reason }endتابع and_then یک مثال از bind functionهست که یک ولیو رپ شده میگیره، و اونو به خورد یک فانکشن میده، و خروجی یک رپ ولیو دیگه میده.** فکر کردن به کد به شکل سریالی از تبدیلها میتونه رویکرد آزادسازی توی برنامه نویسی بوجود بیاره. مدتی زمان میبره تا بهش عادت کنید، اما اگر استفادش کنید به کد کلین تری میرسید، توابع کوتاه تر، و دیزاین فلت تر.امتحانش کنید.دروس مرتبط: 8, 17, 26, 28, 35منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Sun, 21 Feb 2021 23:00:12 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 29</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-29-cfgynnyqvpbw</link>
                <description>درس 29: Juggling the Real Worldقدیما کامپیوترها منعطف نبودن و مجبور بودیم توی استفاده رفتارمون رو براساس محدودیت هاشون منطبق کنیم، اما امروزه انتظارمون خیلی بیشتر شده، اونها توی زندگیمون آمیخته شدن و اونم دنیای بی نظم ما، هر اتفاقی هر لحظه ممکنه بیفته، حتی مدلی که فکر میکردیم و نیازهای سیستم عوض بشه و ...توی این درس میخایم یکسری موضوعات مرتبط با سیستم های سازگار رو مطرح کنیم.Eventsیک ایونت اماده بودن یک دیتا یا انجام کاری رو نشون میده. همچنین میتونه از بیرون سیستم بیاد، از کلیک کاربر، بالارفتن ارزش یک سهم، یا داخلی باشه مثل آماده شدن نتیجه یک محاسبه، پایان یک جستجو و ... از هرجایی که تولید بشه، اگر ما برنامه رو مدلی بنویسیم که عکس العمل نشون بده به ایونت ها، و اون کاری که انتظار میره انجام بشه براساس اونها، این نرم افزار بهتری توی دنیای واقعی بهمون میده و کاربرا احساس درگیری بیشتری با سیستم می کنن و سیستم هم بهتر از منابع استفاده میکنه.اما چطور یک همچین نرم افزاری بنویسیم؟ بدون استراتژی قطعا گیژ و کد نامطلوب تری خاهیم نوشت.چهار استراتژی که توی این حوزه کمکمون میکنه بررسی میکنیم:- Finite State Machines- The Observer Pattern- Publish/Subscribe- Reactive Programming and Streams· Finite State Machinesاستفاده از FSM خیلی ساده است، برخلاف خیلی از دولوپرها که ازش طفره میرن یا فکر میکنن سخته، یا در مواقعی که با سخت افزار درگیر هستیم کارامد نیست، یا کتابخونه هایی که برای استفاده ازش هست سخت و نامفهومه، اینطور نیست و این تفکرات اشتباس.آناتومی یک FSM عملگرایک استیت ماشین در اصل مشخصات و اطلاعات نحوه هندل کردن ایونت ها رو نگهداری میکنه. شامل یکسری state هست که در لحظه فقط یکی شون استیت فعلی سیستمی رو مشخص میکنه، هر استیت لیست رویدادهایی که بهش مرتبطه رو نگه میداره. و هر کدوم از ایونت ها مشخص میکنن که استیت بعدی سیستم چی باشه.مثلا فرض کنید در یک سیستم ما مسیج هایی رو به صورت multipart از روی وب سوکت دریافت میکنیم. اولین مسیج هدر هست و مسیج بعدی تعداد دیتای مسیج ها و بعد هم بدنه مسیج ها میاد سمتمون. طبق مدل FSM ما از Initial State شروع میکنیم، اگر پیامی از نوع هدر دریافت کردیم، به استیت Reading Message میریم،همچنین اگر وقتی در استیت اولیه هستیم، چیزی غیر از مسیج هدر برامون بیاد به استیت Error میریم. وقتی در استیت Reading Message هستیم، میتونیم بادی مسیج ها رو اکسپت کنیم تا به استیت Done یا Error برسیم.این مدل FSMو خیلی تمیز به صورت دیتا میشه در آورد و جدولی در نظر بگیرید که هر ردیفش یک State رو مشخص میکنه و هر ستون مشخص کننده ایونت هست و داخل سلول مشخص میکنیم که اگر اون ایونت اجرا شد استیت جدید ماشین چی باشه.مدل کاملتر FSM اینجوری میشه که هر جابجایی بین استیت ها به همراه خودش اجرای یک Action رو داشته باشه و کدی اجرا بشه.· The Observer Patternتوی این پترن ما سورسی از ایونت ها داریم که بهش Observable میگیم، همچنین یکسری کلاینت برای اون ایونت ها داریم که بهش Observers میگیم. یک observer علاقه خودش رو برای رجیستر شدن در یک ایونت ثبت میکنه و وقتی اون ایونت رخ میده observable لیستی از تمامی observer هایی که برای اون ایونت رجیستر کردن رو میبینه و فانکشنهایی که پاس داده بودن اجرا میشه. مثلا کد روبی زیرو در نظر بگیرید ماژول Terminate وقتی که اپلیکیشن میخاد بسته بشه کال میشه، اما قبلش به تمام observer هاش اطلاع میده که اپلیکیشن در حال بسته شدنه تا منابع داده تمپشونو روی دیسک اعمال کنند و از این قبیل کارها:event/observer.rbmodule Terminator  CALLBACKS = [] def self.register(callback)  CALLBACKS &lt;&lt; callback enddef self.exit(exit_status)  CALLBACKS.each { |callback| callback.(exit_status) }exit!(exit_status) endend Terminator.register(-&gt; (status) { puts &quot;callback 1 sees #{status}&quot; })Terminator.register(-&gt; (status) { puts &quot;callback 2 sees #{status}&quot; })Terminator.exit(99)$ ruby event/observer.rb callback 1 sees 99callback 2 sees 99چیز بیشتری از این نمیخاد، شما رفرنسی از یک فانکشن رو به لیستی از فاکنشهایی که به یک ایونت رفرنس میشن اضافه میکنید، و وقتی اون ایونت raise میشه تمام اون فانکنشها رو براتون کال میکنه. این پترن سالهای سال بهمون کمک کرده مخصوصا توی سیستم های دارای رابط کاربری، اما یک مشکل هم داره، اینکه وابستگی رو توی سیستم بالا میبره coupling. همچنین بخاطر اینکه کال بک های رفرنس شده به یک ایونت به صورت سینکورنایز کال میشن از نظر پرفورمنسی هم مشکل ساز میشه.این مشکل با استراتژی بعدی حل میشه.· PUBLISH/SUBSCRIBEاین پترن با وجود اینکه امکانات پترن Observer رو تعمیم میده، مشکل پرفورمنسی و وابستگی که گفتیم رو حل کرده. توی این مدل (pubsub) ما یک سری منتشرکننده (publishers) و یکسری مشترک (subscribers) داریم که با کانالها (channels) بهم کانکت هستن. این کانالها معمولا در بدنه کد دیگه ای پیاده سازی میشن و یا اکثرا در کتابخونه های خارج پروژه رفرنس و استفاده میشن یا بخشی از یک ساختار distributed هستن. و پیاده سازی این کانالها کاملا بر شما و کدتون پوشیده است.هر کانالی یک اسم داره، مشترکین به یک یا چند کانال رجیتسر میشن، و منتشرکننده ها ایونت ها رو براشون روی کانال ها مینویسن. برخلاف مدل observer ارتباط بین منتشرکننده و مصرف کننده ایونت توی کد شما پیاده سازی نمیشه و عمدتا async هم هست. هرچند این مدلو میتونید خودتون هم پیاده سازی کنید ولی اکثر سرویس دهنده های ابری دارن این خدماتو میدن و شما میتونید با استفاده ازشون نرم افزار خودتونو به هر جای دنیا وصل کنید و به هر سیستم یا ماژول خارجی، همچنین همه زبونای برنامه نویسی چندین کتابخونه برای این مدل دارند.این پترن به خوبی مشکلات observer و پوشش داد، اما استفاده زیاد سوار کردن کل سیستم روی این پترن هم میتونه مشکلات وپیچیدگی هایی رو به دنبال داشته باشه، مثل دیباگ کردن سخت تر و عدم دبیاگ لحظه ای و ...· REACTIVE PROGRAMMING, STREAMS, AND EVENTSاگر با اکسل کار کرده باشید، با برنامه نویسی ری اکتیو آشنا هستید، اگر سلولی فرمولی داشته باشه که اون فرمول به یک سلول دیگه رفرنس زده، اونوقت تغییر در مقدار سلول دوم، مقدار سلول اول رو دستخوش تغییر میکنه. فریمورک هایی زیادی وجود داره که کمک میکنه این مدل ری اکشن بین داده ها رو پیاده کنیم. توی حوزه بروزرها، فریمورکهایی مثل React , Vue JS جزو همین فریمورکها هستن.درسته که از ایونتها میشه برای تریگر کردن ری اکشن های مختلف در کد استفاده کرد، اما بررسی کردیم ایونت ها سختی های خودشونو دارن، اینجاست که Streams میان وسط. استریم ها بهمون این امکانو میدن که مثل ایونت ها رفتارشونو پیاده کنیم، مواقعی که با کالکشنی از دیتا مواجهیم. خوبی استریم ها هم اینه که دقیقا مثل بقیه کالکشن ها میتونیم مدیریت شون کنیم، فیلتر کردن و ... همچنین async هستن و پرفورمنسمونو خراب نمیکنن.تو سایت http://reactivex.io یکسری تعاریف، داکیومنتها و پیاده سازی ها در این مورد اورده شده. در اینجا یک مثال با RxJs میزنیم که یکی از کتابخونه های جاوا اسکریپت هستش.import * as Observable from &#x27;rxjs&#x27; import { mergeMap } from &#x27;rxjs/operators&#x27; import { ajax } from &#x27;rxjs/ajax&#x27;import { logValues } from &quot;../rxcommon/logger.js&quot; let users = Observable.of(3, 2, 1) let result = users.pipe(  mergeMap((user) =&gt; ajax.getJSON(&#x60;https://reqres.in/api/users/${user}&#x60;))  ) result.subscribe( resp =&gt; logValues(JSON.stringify(resp.data)), err =&gt; console.error(JSON.stringify(err)) )ایونت استریم ها به این صورت تعریف می شوند که عموما observable شون میتونه اونها رو به صورت پارالل اجرا بکنه در صورت رخداد. توی این مثال اطلاعات کاربرا رو از یک apiرایگان گت میکنیم و کدمون قراره یوزرهای با شناسه 1 2 3 رو بگیره. با اجرای این کد سه ریکوئست از سه استریم به صورت همزمان اجرا میشن.ایونت ها همه جا هستندایونتها همه جای سیستم هستن، از کلیک کاربر روی یک باتن بگیرید تا اکسپایر شدن یک تایمر، لاگین شدن کاربر، مچ شدن پترن خاصی در یک فایل در حال خواندن و ... ما باید توی کد به سبکی هندلشون کنیم که کمترین وابستگی رو در بهترین پرفورمنس ایجاد کنیم.دروس مرتبط: 28, 36منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Wed, 17 Feb 2021 21:01:09 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 28</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-28-pbqpktkkgbab</link>
                <description>مقدمه فصل 5: خم شدن یا شکستن Bend, or Breakزندگی ساکن نمیمونه، کد ماهم منفک از این قضیه نیست. اونم با تغییرات فوق سریع حوزه تکنولوژی، یا تغییرات بنیادی در نیازهای پروژه و ... این خیلی مهمه که محصولات و کدامونو به سبکی بنویسیم که منعطف و راحت قابل تغییر باشه وگرنه خیلی راحت از رده خارج میشه.تو درس11 در مورد بازگشت پذیری(Reversibility) ی کلیاتی گفتیم، تو این فصل میخایم روشهایی که کمک میکنه تا کد منعطف و برگشت پذیر بنویسیمو بگیم.درس 28: جداسازی (Decoupling)تو درس 8 جوهره طراحی خوب، راجع به اصولی که منجر میشه به اینکه کدمون منعطف تر و راحت تر باشه در مقابل تغییرات، گفتیم. وابستگی، دشمن تغییراته. بخاطر اینکه چیزای مختلفو بهم وصل میکنه و برای تغییر دادن یک بخش باید قسمت های دیگه هم در نظر داشته باشیم و کار سخت و سخت تر میشه. ممکنه وقتی ی چیزی رو تغییر میدین ی جای دیگه بترکه و ...وقتی میخایم یک چیز محکم بسازیم مثل ستون یا پل، معمولا کامپوننت های درگیر در اون رو خیلی بهم میچسبونن و هر چی وابستگی بیشتری داشته باشن خروجی محکم تری پدیدار میشه. اما توی نرم افزار دقیقا برعکسه داستان، هر چی کامپوننت ها وابستگی شون بهم به حداقل ترین حالت ممکن برسه، و خروجی منعطف تر باشه، برامون مطلوب تر و راحت تر خاهد بود اعمال تغییرات و توسعه ها.منظورمون از جداسازی کد چیه؟ در اینجا میخایم در مورد:•  زنجیره فراخوانی متودها•  خطر ابجکت و متغیرهای گلوبال•  خطرهای کلاسهای زیرین در ارث بریصحبت کنیم. البته که این لیست شاید ی مقدار فانتزی باشه، چون هرجایی که تو دو کد چیزی رو به اشتراک استفاده کنن، اونا وارد وابستگی(coupling) شدن و باید حین کد زدن همیشه شاخکاتونو تیز کنید و حین دیتکت سریعا در طراحی تجدید نظر کنید.•  زنجیره فراخانی متودهاممکنه کدی شبیه به زیرو یا دیده باشید یا خودتون زده باشید:public void applyDiscount(customer, order_id, discount) {  totals = customer      .orders      .find(order_id)      .getTotals();  totals.grandTotal = totals.grandTotal - discount;  totals.discount = discount;}توی این کد رفرنسی از چندین سفارش یک آبجکت مشتری گرفته شده، برای اینکه سفارش خاصی رو پیدا کنیم و از اون مبلغ کلش رو بگیریم، از اون مبلغ کل استفاده کنیم و تخفیفو ازش کم کنیم و مقدار تخفیفم ست کنیم. این قطعه کد داره 5 سطح انتزاعی رو پیمایش میکنه از مشتری تا ابجکت مبلغ کل. قطعا باید کد سطح اول بدونه که مشتری ابجکتی داره که لیست سفارشهاشو نگه میداره، ابجکت سفارش تابعی داره که کار جستجو رو انجام میده، یک سفارش یک مبلغ کل داره که خواندنی و نوشتنیه setter and getter داره. یکسری دانستنی وجود داره که باید بدونیم. بدتر اینکه خیلی راحت نمیشه این کدو توی ادامه پروژه تغییر داد. فرض کنید بیزنس این پروژه تصمیم میگیره که سفارشی نتونه تخفیف بیشتر از 40 درصد داشته باشه. کجای کد اینو هندل کنیم؟ممکنه بگید توی همون تابع applyDiscount، قطعا این قسمتی از جوابه، اما با این مدل کد ما مطمئن نیستیم که این فیلد مبلغ کد سفارش در دیگر قسمت های پروژه کجاها در حال مقداردهی شدنه، و اگر خاطرتون نباشه سراغش هم نمیرید.برای حل این مشکل از یک روش به اسم زیر کمک میگیریم:Tell, Don’t Askاین اصل میگه شما نباید براساس وضعیت داخلی یک آبجکت تصمیم به آپدیتش بگیرید، با این کار مزایای انکپسولیشن رو از بین میبرید و بیزنس پیاده سازی هم پخش میشه. (اون باید خودش خودشو اپدیت کنه ینی فانکشنی داشته باشه براش). در قدم اول برای اعمال تخفیف به این شکل عمل میکنیم:public void applyDiscount(customer, order_id, discount) {  customer  .orders  .find(order_id)  .getTotals()  .applyDiscount(discount);}در اینجا هنوز یک TDA (تل دونت اسک) دیگه داریم، در مورد سفارش های یک مشتری:public void applyDiscount(customer, order_id, discount) {  customer  .findOrder(order_id)  .getTotals()  .applyDiscount(discount);}همین داستان برای یک سفارش و مبلغ کلشم وجود داره در نتیجه:public void applyDiscount(customer, order_id, discount) {  customer  .findOrder(order_id)  .applyDiscount(discount);}اینجا، جاییه که متوقف میشیم. شاید بگید طبق اصل TDA یک فانکشن برای کلاس مشتری مینوشتیم که خودش مستقیم حرکتو بزنه، خوب اگر برده طور بهش نگا کنیم این فانکشن هم جواب میده (نفهمیدم کاربرد این کلمه رو اینجا برده وار slavish یا شایدم چیز دیگه ای توی این جایگاه معنی میشه)این TDA وحی الهی نیست، فقط یک پترنه که بهمون کمک میکنه مشکلاتو شناسایی کنیم، در خیلی از سیستم های یکسری از ابجکت ها افشا شدنشون لازمه مثل مشتری یا سفارش بعضی ها هم ممکنه این مدل طراحی رو بهینه تر پیدا کنند که سفارش های مشتری رو توی مشتری هاید کنن.قانون Demeterممکنه در مورد coupling شنیده باشید که قانون Demeter هم بیان میشه LoD، این قانون اواخر دهه 80 میلادی توسط Ian Holland مطرح شد، به برنامه نویسا کمک میکنه تا توابعشون رو تمیزتر و اصل جداسازی راحت تر پیاده بشه. این قانون میگه هر تابعی که در یک کلاس تعریف میشه باید فقط بتونه:-  متودهای دیگه همون کلاس رو کال کنه-  به پارامترهای خودش دسترسی داشته باشه-  توابع آبجکتی که خودش ساخته رو ببینه-  به متغیرهای گلوبال دسترسی داشته باشه(متغیرهای گلوبال چیز خوبی نیست تو ادامه همین درس بهشون میپردازیم)Don’t Chain Method Callsسعی کنید بیش تر از یک دات &quot;.&quot; نداشته باشید، وقتی میخاید به چیزی دسترسی پیدا کنید مثلا کد زیر خوب نیست:# This is pretty poor styleamount = customer.orders.last().totals().amount;# and so is this…orders = customer.orders;last = orders.last();totals = last.totals();amount = totals.amount;یک استثناء بزرگ وجود داره توی عدم استفاده از دات های پیاپی، اونم برای دسترسی به چیزهایی که خیلی خیلی بعیده تغییر کنند. عموما هرچیزی توی اپلیکیشن شما ممکنه تغییر بکنه، هرچیزی توی کتابخونه های تردپارتی، یا حتی کتابخونه های خوده زبون برنامه نویسی، هرچند کتابخونه ها معمولا استیبل نوشته و اپدیت میشن و ما خیلی خوشحال اینجوری استفاده میکنیم:people.sort_by {|person| person.age }.first(10).map {| person | person.name }در حدی که کد روبی که ما توی ادیشن اول این کتاب نوشتیم 20 سال پیش، همچنان کار میکنه که هیچ، تا وقتی که بریم خونه سالمندانم کار خاهد کرد یحتمل.Chains and pipelinesتوی درس 30 Transforming Programming در مورد توابعی صحبت خاهیم کرد که به صورت پایپ لاین کار میکنن، و دیتا بینشون پاس داده میشه از تابعی به تابع دیگه، این مثل زنجیره ای کال کردن متودهایی که مثال زدیم نیست، هرچند که به صورت کامل از هم دیکاپل نیستند فانکشن ها ولی قطعا از مدل زنجیره ای کمتره وابستگی شون و معمولا فرمت دیتایی که بین شون منتقل میشه یک دسته.•  THE EVILS OF GLOBALIZATIONداده های گلوبال به شکل موزیانه ای وابستگی رو در کدتون میبرن بالا، یک پارامتر همیشه در دسترس برای همه توابعن. چرا میگیم وابستگی کدو زیاد میکنه، در وهله اول فرض کنید نحوه پیاده سازی و مقداردهی متغیرهای گلوبال رو تغییر میدید، حالا ممکنه صدجای برنامه ازشون استفاده کرده باشید، بیفت دنبال دستکاری همه جا.... همچنین باعث میشن که نتونید قطعه های کدو به شکل مستقل تست بکنید(اون کدهایی که از گلوبالا استفاده میکنن).-  گلوبال دیتاها شامل Singleton ها هم میشن، شاید ی عده بگن خوب متغیر گلوبال تعریف نکردم، کلاس نوشتم براش و یک اینستنس سینگلتون ازش ساختم، این کار هم دقیقا گلوبال دیتا ایجاد میکنه. حالا ممکنه یک عده این دیتاها رو پشت توابع اون کلاس سینگلتون و یا پشت اینترفیس ها بپوشونن، باز این بهتره چون باعث میشه به راحتی تغییرات مخرب نتونید روش بدید و صدها جایی که استفاده شده خراب نشه.-  گلوبال دیتا شامل منابع خارجی هم میشه(External Resource)، هر منبع خارجی قابل تغییر مثل دیتابیس، دیتااستور، فایل سیستم، وب ای پی آی و ... گلوبال دیتا هستن و فقط برای بهتر و امن تر کار کردن باهاشون باید رفتارشونو توی کد wrap کنیم  و تحت کنترل داشته باشیم.•  ارث بری وابستگی رو بیشتر میکنه Inheritance adds couplingدر مورد اینکه وقتی یک کلاس استیت و رفتار یک کلاس دیگه رو به ارث میبره، به صورت دیتیل در فصل 31 Inheritance tax صحبت خاهیم کرد. منتهی بازم مسئله حول محور تغییراته، کدهای وابسته رو سخت تر میشه تغییر داد، تغییر یک جا باعث ساید افکت توی جای دیگه بشه که در بدترین حالت توی پروداکشن بزنه بیرون. کدو خجالتی نگه داری، فقط در مورد چیزهایی که میدونه و بهش مربوط میشه عمل کنه، این کمک میکنه به جداسازی در پروژه و تغییر و توسعه رو راحت تر میکنه.دروس مرتبط:  8, 9, 10, 11, 29, 30, 31, 32, 33, 34, 35, 36منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Tue, 16 Feb 2021 23:11:04 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 27</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-27-idzvlplfq3gl</link>
                <description>درس 27: چراغهای جلوتونو پشت سر نزارید (Don’t Outrun Your Headlights) (این یک اصطلاحه به این معنی که انقدر تند نرید که نور چراغ های جلوی ماشین از ماشین عقب بمونن)یک ماشین دو سرنشینو تصور کنید که توی جاده کوهستانی پر پیچ و خم توی یک شب بارونی در حال حرکته، و به سختی پیچ ها رو دیتکت و رد میکنه، یهو سنجاق موی راننده در میره و حواسش پرت اون میشه و میرن توی گاردریل و میفتن تو دره، افسری که برای بازدید حادثه اومده با ناراحتی سرشو تکون میده و میگه: Must have outrun their headlightsآیا این اصطلاح فقط به سرعت اشاره میکنه؟ &quot;نه&quot;. به توانایی راننده در ترمز کردن بموقع و واکنش سریع اون هم اشاره میکنه.توی توسعه نرم افزار ما حوزه دید چراغ های جلومون خیلی محدوده، ما نمیتونیم آینده خیلی دورو متصور باشیم و از ما پوشیده اس، برنامه نویسهای عملگرا در این مورد یکسری قانون دارند:•  Take Small Steps-Alwaysهمیشه، قدم های کوچیک بردارید، و با گرفتن فیدبک ها پیش برید، همچنین نرخ ورود فیدبک های کارتون محدودیت سرعت براتون ایجاد میکنن و باید مدیریتشون کنید.منظور دقیقمون از فیدبک چیه؟ هر چیزی که میتونه کار شما رو تایید یا رد بکنه. مثلا:-  فیدبکهای خروجی تست، سالم بودن اخرین تغییرات کدتون رو بهتون میده-  فیدبکهای دموی محصول برای مشتری، کارآمدن بودن فیچرها و مسیر درست توسعه رو بهتون میده -  و ...خوب حالا که قرار شد قدم های کوچیک برداریم، چه تسک هایی بزرگه؟ هر تسکی که نیاز به فال گویی داشته باشه(از منظر پیش بینی)، دقیقا مثل نور چراغ جلوی ماشین ها که محدودیت برد داره، دید ما هم از آینده همینه، بدتر اونجایی که وارد حدس و گمان بشید و دقیقا مثل فال گویی میشه، توی حالتای زیر ممکنه بیفتید توش:-  تخمین تاریخی روزها و ماه های بعد-  طرح برای نگهداری و توسعه پذیری در آینده-  حدس زدن نیازهای آینده کاربران-  حدس زدن در مورد تکنولوژی های آیندهاما، آیا با وجود این گفته ها ما نباید برای نگهداری آینده سیستممون پلن داشته باشیم؟ قطعا بله، اما تا یک نقطه مشخص، تا جایی که میتونید ببینید. هرچقدر بخاید آینده رو حدس بزنید، ریسک کارتون رو بالا خاهید برد و به اشتباه میفتید، بیشتر از اینکه وقتتون رو تلف کنید برای طراحی کد برای آینده نامعلوم، وقتتون رو مفصل صرف این بکنید که کدی که الان دارید میزنید اصول رو رعایت بکنه و به راحتی قابل جایگزینی باشه، رعایت جداسازی، اصل درای و ... با این حال اگر احساس میکنید که نسبت به چیزی در آینده مطمئن هستید، توی این حالت همیشه شانس وجود داشتن یک قوی سیاه در گوشه ای وجود داره.•  قوهای سیاه Black Swansکتابی به اسم قوهای سیاه نوشته نسیم نیکولاس طالب، به این اشاره میکنه که اکثر وقایع و اتفاقات مهم تاریخ، مواردی بودن که به سختی میشد پیش بینی شون کرد و فراتر از قلمروی انتظارات عادی بودن.زمانی که اولین ادیشن این کتابو مینوشتیم، عنوان هایی مثل این خیلی داغ و سرفصل مجله و اخبار کامپیوتری بود: &quot;چه کسی برنده جنگ GUI دسکتاپ میشه؟ Motif or OpenLook&quot; این سوال اشتباهی بود. شما شاید حتی اسم این دو تکنولوژی رو نشنیده باشید و بروزرها و اپلیکیشن های تحت وب به چشم انداز مسلط شدند.** در اکثر مواقع فردا شبیه امروزه، اما روش حساب نکن.دروس مرتبط: 12, 13, 40, 41, 48, 50منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Mon, 15 Feb 2021 19:37:09 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس26</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B326-xywjl2g1w0hy</link>
                <description>درس 26: How to Balance Resourcesما همه مون وقتی کد میزنیم، منابعو مدیریت میکنیم، از حافظه رم بگیر، ترنزکشنها، تردها، کانکشن های شبکه، فایل سیستمها، تایمرها و هر چیزی از این دست که محدود هستن. در اکثر مواقع هم استفاده از منابع یک پترن قابل پیش بینی رو دنبال میکنه، شما اونو الوکیت(allocate) میکنید، استفاده میکنید از اون ریسورس و در اخر هم اونو دی‌الوکیت(deallocate) میکنید.با این حال خیلی از برنامه نویسا پلن مدونی برای استفاده و سروکله زدن با منابع ندارن، در اینجا ی سری نکته که ممکنه به درد بخوره میاریم:· تمومش کن چیزی که شروعش کردیواین نکته در اکثر شرایط خیلی ساده قابل استفاده است. این نکته به زبون ساده میگه، فانکشن یا ابجکتی که منبعی رو الوکیت کرده، خودش موظف و مسئوله برای دی‌الوکیت کردنش. در اینجا یک مثال به زبون روبی رو بررسی میکنیم، این کد یک فایلو باز میکنه، اطلاعات مشتریا رو ازش میخونه، یک فیلدو اپدیت میکنه و فایلو مینویسه. برای اینکه مثال شفاف تر باشه ما از مدیریت خطاها چشم پوشی کردیم تو این مثال:def read_customer  @customer_file = File.open(@name + &quot;.rec&quot;, &quot;r+&quot;)  @balance = BigDecimal(@customer_file.gets) enddef write_customer  @customer_file.rewind  @customer_file.puts @balance.to_s  @customer_file.close enddef update_customer(transaction_amount)  read_customer  @balance = @balance.add(transaction_amount,2)  write_customer endتو نگاه اول شاید قابل توجیه باشه ی تابع اپدیت کاستومر که به ترتیب میخونه یه رکوردو، اپدیت میکنه بالانسو، و بعدم مینویسدش. اما خیلی فاجعه اس، دقت کنید تابع رید و رایت کاستومر کاملا بهم وابسته شدن، اون یک اینستنس شیر شده رو استفاده میکنن متغیر customer_file، وقتی اول رید کاستومر اجرا میشه اینستنس کاستومر فایل اینیشیال میشه و بعد هم همون اینستنس توی رایت کاستومر استفاده میشه. چرا بده این کد؟ فرض کنید لاجیک برنامه ی تغییر کوچیکی میخاد بکنه جهت اینکه بالانس مشتری فقط در صورتی که مثبت بود اپدیت بشه، اونوقت تابع اپدیت کاستومر به این شکل میشه:def update_customer(transaction_amount)  read_customer  if (transaction_amount &gt;= 0.00)  @balance = @balance.add(transaction_amount,2)  write_customer  endendشاید تستهارو هم رد بکنه، اما وقتی میره تو پروداکشن، هرچند ساعت یک بار میره تو دیوار، با این خطا too many file open، چون کد به شکلیه که ممکنه بعضی از مشتریا اصن واسشون کاستومر رایت کال نشه و فایل بسته نشه و باز بمونه...یک راه حل خیلی بد واسه هندل این شرایط میتونه تغییر اپدیت کاستومر به این شکل باشه:def update_customer(transaction_amount)  read_customer  if (transaction_amount &gt;= 0.00)  @balance += BigDecimal(transaction_amount, 2)  write_customerelse  @customer_file.close # Bad idea!  endendاین کار کثیف، خطا رو هندل کرد، الان در هر صورت فایل بسته میشه، ولی الان سه تا فانکشن بهم وابسته شدن هر سه تاشون دارن با اینستنس customer_file کار میکنن. و با این کار میفتیم تو تله. این مدیریت منابع نیست...** هر تابعی که ریسورسی رو میگیره خودش باید ازادش کنه، کدو به شکل زیر ریفاکتور میکنیم:def read_customer(file)  @balance=BigDecimal(file.gets) enddef write_customer(file)  file.rewind  file.puts @balance.to_s enddef update_customer(transaction_amount)  file=File.open(@name + &quot;.rec&quot;, &quot;r+&quot;) # &gt;--  read_customer(file) # |  @balance = @balance.add(transaction_amount,2) # |write_customer(file)file.close  endحالا تنها فانکشن اپدیت کاستومره که مسئولیت گرفتن و ازاد کردن اینستنس فایلو داره، همچنین در یکسری از زبونای برنامه نویسی با فورس کردن اسکوپ میتونیم طول عمر یک ابجکتو محدود کنیم. (مثه بلاک using() توی سی شارپ)· تخصیص لانه ایما برای حالتایی که به بیش از یک نسخه از منبعی نیازداریم، باید پترن نگهداری منابعمون رو گسترش بدیم چون پیچیدگی بیشتری توی این حالت وجود داره، دوتا ایده در این حالت وجود داره:- منابع رو به ترتیب عکس الوکیت کردنشون، دی الوکیت کنید. با این روش شما خیالتون راحته که ابجکت های یتیم نخاهید داشت.(ابجکتی که به ابجکت دی الوکیت شده رفرنس داره)- وقتی از یک منبع تعدادی رو در جاهای مختلف کدتون لازم دارید، همیشه در یک جهت الوکیشن رو انجام بدید، با اینکار از ددلاک جلوگیری میکنید فرض کنید پراسس 1 منبع یک رو داره و میخاد از 2 هم استفاده کنه و پراسس 2 بالعکس که توی این حالت هر دو پروسه ویت میشنمهم نیست چه جنس از منابع رو الوکیت میکنید از کانکشن شبکه بگیر تا فایل و حافظه و ... پایه ای ترین پترن مدیریت منابع اینه که هر کسی که منبعی رو الوکیت میکنه خودش مسئول و موظف دی الوکیت کردنشه.- استفاده از destructor در زبونهای ابجکت ارینتد این امکانو بهتون میده که اگر منابعی رو توسط ابجکتی الوکیت میکنید اون رو ازاد کنید.- در شرایطی که اکسپشن رخ بده، شما باید گارانتی کنید که منبعی که گرفتید ازاد بشه، فرض کنید در ابتدای تابع منبعو گرفتید و وسطش خطا رخ میده و کد به انتهای تابع برای ازادسازی منبع نرسه، دوتا انتخاب دارید برای هندل این شرایط:1- استفاده از متغیرهای اسکوپ(مثل متغیرهایی که در استک نگهداری میشن در c++ , rust)مثلا کد زیر در زبون راستو در نظر بگیرید:{let mut accounts = File::open(&quot;mydata.txt&quot;);// use &#x27;accounts&#x27; //}// &#x27;accounts&#x27; is now out of scope, and the file is// automatically closed2- استفاده از بلاک فاینالی finally که در ترای کش استفاده میشه و در نهایت این کد اجرا میشه و میتونید توش ازادسازی رو انجام بدید.try // some dodgy stuff catch // exception was raised finally // clean up in either case- حالا یک آنتی پترن توی حالت اکسپشن بررسی کنیم، معمولا میبینیم که تازه کارا اینجوری کد میزنن:beginthing = allocate_resource()process(thing)finallydeallocate(thing)endخوب حالا فرض کن که خطا روی خوده الوکیشن منبع رخ بده ینی اصن منبعی الوکیت نشه، حالا توی فاینالی میخاد چیو دی الوکیت کنه؟!!!!پترن درستش اینجوری میشه:thing = allocate_resource()beginprocess(thing)finallydeallocate(thing)end· چه موقع نمیتونید بالانس کنید مدیریت منابعومعمولا در مواقعی که برنامه از دیتا استراکچرهای داینامیک استفاده میکنه، فرض کنید یک تابع مقداری از حافظه رو الوکیت کرده و اونو ارتباط داده به استراکچر بزرگتری از کد توی این حالت ها، پترن پایه برای مدیریت منابع کارساز نیست.شما نیاز دارید تصمیم بگیرید که کدومشون مسئول ازاد سازی منابع هستن. چه اتفاقی میفته اگر استراکچر بالا سری رو دی الوکیت کنید؟ چند تا گزینه وجود داره:- استراکچر بالاسری مسئول ازادسازی همه منابع خودش و زیر دستی ها هست پس باید به صورت ریکرسیو همه شونو آزاد کنه- استراکچر بالاسری که دی الوکیت شد، ابجکت هایی که بهش رفرنس داشتن به صورت یتیم باقی بمونن- استراکچر بالاسری امتناع کنه از دی الوکیت شدن مادامی که تمام زیر دستی ها دی الوکیت و ازادسازی شون انجام بشهبرای این حالت ها ممکنه نیاز داشته باشید در بعضی از زبونای برنامه نویسی کد بنویسید و یا حتی برای هر مدل از استراکچرها ماژولی کتابخونه ای و اماده بنویسید و ازش استفاده کنید.· مدیریت منابعو چک کنیداز اونجایی که برنامه نویسای عملگرا به هیچ کس اعتماد ندارن، حتی خودشون، ایده خوبی به نظر میرسه که کدهایی برای چک کردن وضعیت ریسورس ها و منابع بزنید. مثلا wrapper هایی برای انواع ریسورس ها بنویسید و در کدتون بررسی کنید وضعیت منابع رو.همچنین از پروفایلرها هم میتونید استفاده کنید و مموری لیک ها (memory leak) رو دیتکت کنید.دروس مرتبط: 24, 30, 33منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Sun, 14 Feb 2021 20:55:00 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 25</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-25-qrekugem15ks</link>
                <description>درس 25: Assertive Programmingاینجوری بنظر میرسه که یک زمزمه درونی وجود داره که هر برنامه نویسی ام در شروع کارش اونو حفظ میکنه، در هر پروسه از تولید نرم افزار از طراحی دیزاین و کد هم وجود داره، حتی برای امور دیگه زندگی هم همینطور.This can never happen… مثلا:-  این اپلیکیشن که نمیخاد خارج از مرزها استفاده بشه پس لوکالیزیشن لازم نداره-  فیلد تعداد هیچ وقت نمیتونه منفی باشه توی ی جای خاص-  پروسه لاگ کردن هیچ وقت خودش خطا نمیخوره و ترمینیت نمیشه** بیاید این مدل خود فریبی ها رو تمرین نکنیم، مخصوصا موقع کدنویسی•  استفاده از Assertion برای جلوگیری از غیر ممکن هاهروقت خودتونو توی شرایطی دیدید که دارید فکر میکنید راجع به اینکه یک چیز غیر ممکنه رخ بده، برای چک کردنش کدی رو بنویسید. یکی از ساده ترین راه ها استفاده از assert هستش که در بسیاری از زبون های برنامه نویسی پیاده سازی شده که معمولا یک شرایط بولین رو براتون چک میکنه.مثلا اگر نتیجه ای نباید نال باشه اینجوری چکش میکنید:assert (result != null);یا برای اطمینان از نتیجه یک الگوریتم استفاده میشه، فرض کنید یک الگوریتم سورت نوشتید و میخاید چکش کنید که درست عمل کرده یا نه:books = my_sort(find(&quot;scifi&quot;))assert(is_sorted?(books))از assert برای ارور هندلینگ استفاده نکنید، assert ها رو فقط برای چیزهایی که هیچ موقع امکان نداره که رخ بده استفاده کنید. مثلا کد زیر توصیه نمیشه:puts(&quot;Enter &#x27;Y&#x27; or &#x27;N&#x27;: &quot;)ans = gets[0] # Grab first character of responseassert((ch == &#x27;Y&#x27;) || (ch == &#x27;N&#x27;)) # Very bad idea!•  ساید افکت های Assertionخیلی بد میشه اگر کدی که برای چک کردن چیزی میزنیم خودش باعث خرابی و خطا بشه، مثلا کد زیرو فرض کنید:while (iter.hasMoreElements()) {assert(iter.nextElement() != null);Object obj = iter.nextElement();// ....}iter.nextElement() این خودش یکی از المنتهای ایتریتورو میگیره و خط بعدشم کد اصلی میخاد یکی بگیره اینجوری نصف کالکشن فقط پردازش میشه. برای اصلاحش کدو به شکل زیر در میاریم:while (iter.hasMoreElements()) {Object obj = iter.nextElement();assert(obj != null);// ....}•  بزارید assert ها توی کد بموننیک سری بدفهمی راجع به استفاده از assert ها وجود داره، مثلا: استفاده ازشون برای کدمون سربار ایجاد میکنه، چون دارن چیزی رو چک میکنن که قرار نیست اتفاق بیفته، اون ها فقط در شرایط وجود باگ در کد تریگر میشن، وقتی کدو تست بکنیم دیگه بهشون نیازی نداریم. و غیرفعالشون کنیم تا کد سریعتر اجرا بشه و اونها فقط ابزار دیباگینگ هستن.در اینجا دو فرض کاملا اشتباه وجود داره:اول اینکه فکر کنیم تست ها قراره همه باگ ها رو شناسایی کنند، در واقعیت و در برنامه های پیچیده حالت هایی رخ میده و باگ هایی میزنه بیرون که شما توی تست کاور نکردید.دوم اینکه این افراد خوش بین فراموش میکنند که برنامه شون در دنیایی خطرناک قراره اجرا بشه، از موشی که قراره کابل شبکه رو گازش بگیره و قطع بکنه بگیر، تا کاربری که روی سیستم بازی میکنه و مموری کم میاد، تا لاگ فایلهایی که انقدر زیاد شدن حجم استوریج سرورو پر کردن و ... تمام این داستانا توی محیط پروداکشن ممکنه اتفاق بیفته. خط اول دفاعی تون باید کدهایی باشه که حالت های خطا رو بررسی میکنن و در خط دوم با assert ها اون حالتهای غیرممکن که احتمال میس شدن دارنو چک میکنید.علی ایحال میتونید اون assert هایی که براتون پر هزینه تموم میشه رو چشم پوشی کنید ولی مدلهایی که در این درس مثال زدیم برای هر اپلیکیشن مشابهی حیاتیه.دروس مرتبط 23, 24, 42, 43منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Sat, 13 Feb 2021 19:41:54 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 24</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-24-l26hotxttlws</link>
                <description>درس 24: برنامه های مرده دروغ نمیگن (Dead Programs Tell No Lies)تاحالا پیش اومده که وقتی ی مشکلی دارید یا ی چیزی تون بهم ریخته، قبل از خودتون دیگران متوجه ش بشن؟ این در مورد کدها هم صدق میکنه مثلا وقتی کد ی نفر دیگه رو میبینی. گاهی اوقات کدی که فکر میکنی درسته، باگش توسط کتابخونه تردپارتی و جایی که زیر بار میره در میاد، شاید ی مقدار نال یا لیست خالی پاس دادیم، یا شایدم ی کلید ضروری از یک هش ست خالیه، یا خطای شبکه، یا حتی خطای فایل سیستمه سیستم عامل، که ما حواسمون به مدیریت خطاش نبوده، یا حتی توی سوییچ کیس مقدار دیفالت نزاشتیم یا همش داره مقدار دیفالت برمیگرده ی جای کار میلنگه. ما میخایم جایی که &quot;غیر ممکن&quot; اتفاق افتاده رو شناسایی کنیم.این خیلی ساده است که بیفتی روی جمله‌ی &quot;این که رخ نمیده&quot;، اکثرا کدی مینویسیم که چک نمیکنه فایلی که باز و استفاده شده، موفقیت امیز کلوز شده یا نه. و ممکنه برای حالت های نرمال و وضعیت های گل و بلبل کد بزنید. اما قبلتر گفتیم ما مدل تدافعی رو میپسندیم، ما دیتای ورودی رو دقیق چک میکنیم تا همون چیزی باشه که باید، دیتایی که حاصل پردازش کدمون بوده رو هم همینطور چک میکنیم، همچنین چک میکنیم که کتابخونه های وابسته دقیقا همون ورژن های مد نظر باشه که لود میشه.همه خطاها به شما اطلاعات کافی رو میدن. ممکنه شما اون سبک &quot;خطایی رخ نمیده رو&quot; انتخاب کنید، قطعا اشتباه میکنید. در عوض برنامه نویس عملگرا (Pragmatic Programmer) همیشه به این فکر میکنن که اگر خطایی رخ بده اتفاق خیلی خیلی بدیه و تمام ابعاد قضیه رو میسنجن.•  CATCH AND RELEASE IS FOR FISHبعضی از برنامه نویسا حال خوبی دارن از اینکه خطاها رو کچ و لاگ و بعدم ریز کنن مثل کد زیر:try do   add_score_to_board(score);rescue InvalidScore   Logger.error(&quot;Can&#x27;t add invalid score. Exiting&quot;);   raiserescue BoardServerDown   Logger.error(&quot;Can&#x27;t add score: board is down. Exiting&quot;);   raiserescue StaleTransaction   Logger.error(&quot;Can&#x27;t add score: stale transaction. Exiting&quot;);   raiseendاما همین کدو یک برنامه عملگرا اینجوری میزنه:add_score_to_board(score);ما این کدو به دو دلیل ترجیح میدیم، اول اینکه کد برنامه تحت شعاع خطایابی قرار نمیگیره و دلیل دوم و مهمتر اینکه، این کد کمتر وابستگی داره به نسبت کد قبل، توی کد قبل یکسری لیست خطاهای خاص کچ شده، فرض کنید اگر خطای جدیدی هم بخاد هندل بشه باید این کد تغییر بکنه و اون خطا هم به لیست کچ هاش اضافه بشه، اما کد دوم هر خطایی بخوره به سطح بالاترش ریزش میکنه.•  CRASH, DON’T TRASHاین خیلی مفیدتره که زودتر خطاها و مشکلاتو دیتکت کنید، زودتر کرش(Crash) کنید، این بهترین اتفاقیه که میتونه براتون بیفته، که اگر نیفته در مقابلش اینه که شما به نوشتن کد مشکل دار ادامه میدید و اونو روی یک دیتابیس حیاتی اجرا میکنید.در زبون های برنامه نویسی Erlang و Elixir این فلسفه بخوبی پیاده شده، در حدی که آرمسترانگ سازنده زبون ارلنگ و نویسنده کتاب برنامه نویسی ارلنگ، توی کتاب میگه برنامه نویسی تدافعی اتلاف وقته، بزار کرش کنه. وقتی کرش کرد با سوپروایزرهای سیستمی مدیریت میشه، سوپروایزرها مسئول اجرای کد و مانیتور وضعیتشن، میتونن اجرا، ریست و حتی ببندن اجرای برنامه رو. اما اگر سوپروایزر خودش خطا بخوره چی؟ سوپروایزر خودش توسط مجموعه درختی از سوپروایزرها منیج میشه.در محیط های برنامه نویسی دیگر، ممکنه این مناسب تر باشه که برنامه بسته بشه اگر خطا خورد، یا خطاها لاگ بشه و یا از تراکنشها استفاده کنید و یا حتی با پراسس های دیگه ارتباط برقرار کنید برای مدیریت خطاها.اما در نهایت اصل پایه اینه که وقتی کد میزنید و به چیزهایی میرسید که فکر میکنید رخ دادنش محاله، و بهش رسیدگی نکنید و مدیریتش نکنید، برنامه شما مضنون خاهد بود و خیلی زود گندی رو به بار میاره.یک برنامه مرده معمولا آسیب کمتری از یک برنامه مشکل دار میزنه.دروس مرتبط:  20, 23, 25, 26, 43منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Thu, 11 Feb 2021 00:09:21 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس 23</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B3-23-xpccyqk6ul49</link>
                <description>درس 23: Design by Contractسر و کله زدن با سیستم های کامپیوتری سخته، سر و کله زدن با مردم سخت تر. ما مدت های مدید توی حوزه روابط و معاملات انسانی ریسرچ کردیم، روش های زیادی هم مطالعه، تست و اجرا شده، تو این درس میخایم یکی از بهترین روش ها که برای حوزه نرم افزار موثر و کاربردیه بیان کنیم و اون هم معامله بر اساس قرارداده.یک قرارداد مسئولیت ها و حق و حقوق طرفین قراردادو مشخص میکنه، همچنین توافق نامه ای همه جانبه است که شرایط شکست در هر یک از مسئولیت ها نیز مشخص میشه توش.قرارداد چه رسمی و چه غیررسمی به ساختار و معاملات کمک میکنه، آیا میتونیم ازش توی کدنویسی بهره ببریم؟ &quot;بله&quot;· DBC (طراحی براساس قرارداد)اولین بار این کانسپت توسط برتنارد میر در کتاب ساخت نرم افزار شی گرا در سال 1997 و با زبون برنامه نویسی ایفل، گفته شد. یک تکنیک ساده و در عین حال قدرتمند که براساس داکیومنت سازی دقیق از امکانات نرم افزار و توافق روی اون، به شکلی که نه کار اضافه تر و نه کمتری طبق قرارداد انجام بشه توسط طرفین اون، و داکیومنت سازی هم قلب این روش دیزاین بای کانترکت هست.هر تابع و فانکشنی که توی نرم افزار نوشته میشه، قبل از شروع و در حین عملیاتش با یکسری اکسپشن هایی در دنیای واقعی مواجهه که برتنارد این مدلی بیان میکنه:- Preconditionچه چیزهایی باید درست باشد تا فانکشن مورد نظر اجرا بشود، یک فانکشن هیچ وقت نباید کال بشه مادامی که پیش شرایطش یا دیتای مورد نیاز به شکل درست آماده باشه.- PostConditionفانکشن مورد نظر چه چیزی رو تضمین میکنه که بعد از اجرا انجام داده باشه.- Class Invariantsیک کلاس برای متغیرهای ثابتش باید تضمین کنه که مقدارشون معتبر و غیر قابل نوشتن باشه یا برای مدلهای مختلف متغیر براساس قوانین اون زبون برنامه نویسی** و به طور کلی قرارداد بین شونو میشه اینجوری بیان کرد، اگر فراخوانی کننده یک فانکشن پیش شرطهای یک فانکشن رو به درستی رعایت و اماده کنه، اون فانکشن تضمین و گارانتی میکنه که پس شرایط و یا همون خروجی و عملیاتهایی که باید رو درست انجام بده و مقادیر متغیرهای کلاس نیز معتبر باشند.بعضی از زبونای برنامه نویسی این کانسپت قراردادو ملموس تر ارائه میدن، مثلا زبون برنامه نویسی Clojure ، در مورد پیش شرط و پس شرطها قابلیت خوش دست و خوبی داره، یک مثال فانکشن واریز در عملیات بانکی رو میزنیم:(defn accept-deposit [account-id amount]{ :pre [ (&gt;   amount 0.00)  (account-open? account-id) ]:post   [ (contains? (account-transactions account-id) %) ] } &quot;Accept a deposit and return the new transaction id&quot;;; Some other processing goes here...;; Return the newly created transaction:همونطور که میبینید دو تا پیش شرط داره یکی مبلغو چک میکنه مثبت باشه، و دومی اینکه حساب فعال و معتبر باشه، در پس شرط هم ارتباط بین شناسه تراکنش و حسابو تضمین میکنه.توی درس10 Orthogonality گفتیم کد خجالتی بزنید(برای دیکاپل کردن و رعایت اصل جداسازی)، توی این درس میخایم بگیم کد تنبل(lazy) بزنید.قبل از افتادن توی انجام کار و قول راجع به نحوه و کیفیت خروجی، به شدت روی ورودی ها و دیتکت مسئله سختگیر باشید. اگر قرارداد شما این مدلی باشه که همه چی قبوله، شمام باید توی خروجی قول جهان هستی رو به عنوان خروجی بدید و کلی ام کد بزنید.فرقی نمیکنه زبون برنامه نویسی که باهاش کار میکنید شی گراست یا فانکشنال، DBC شما رو فورس میکنه تا فکر کنید.· Class invariants and functional programmingاین اسم ثابت های کلاس رو برتنارد بخاطر این استفاده کرد که داشت از زبون برنامه نویسی ایفل که یک زبون شی گراست استفاده میکرد، اما مفهوم فراتر از اونه. این مفهوم به همون استیتها state ها اشاره میکنه، که یک اینستنس کلاس یک سری مقادیرو برای مشخص بودن استیتش نگهداری میکنه، توی زبونای فانکشنالم همینه، state و فانکشنها درگیر هستند.· پیاده سازی DBCبه زبان ساده، بررسی رنج ورودیها، شرطها، قولهایی که یک تابع برای انجامش داده، اگر به این ها فکر نکنید قبل از شروع پیاده سازی، قطعا با شکست های زیادی در پروژه مواجه میشید. و در بدو شروع هرچیزی fail میشید.توی زبونهای برنامه نویسی هم که دی بی سی رو ساپورت نمیکنن مثل اون درجه از ساپورتی که توی Clojure نشونتون دادیم، خوب نگران نباشید، DBC یک دیزاین پترن هست، شما میتونید تمام چک و تیک ها رو کد نویسی کنید یا در تست ها بیارید و به هر نحوی مطمئن بشید از رعایتشون.· Assertionsامکانی رو به شما میده برای چک کردن کامپایلری وضعیت های منطقی کد، آیا با اسرتها میتونید هر اونچه در DBC لازم دارید رو پیاده کنید؟ &quot;نه&quot;، به عنوان مثال زبونای برنامه نویسی از اسرتها در شی گرایی عمقی پشتیبانی نمیکنن، مثلا در ساده ترین حالت فرض کنید شما مشغول نوشتن کلاسی هستید که از کلاس پدری ارث میبره، و یک تابع رو اوررایت میکنید، و اسرت در تابع بیس نوشته شده، تو این شرایط اون اسرت برای تابع کلاس فرزند اجرا نخاهد شد و باید دوباره عین همون رو کپی کنید. اگر از اسرتها برای رعایت قرارداد توابع استفاده میکنید، باید کد رو به شکلی بنویسید که در پیش شرط، مقادیری که انتظار دارید از تابع برگرده رو سیو کنید تا بتونید مقایسه رو انجام بدید.· متغیرهای معناییفرض کنید در یک سیستم بانکی برای ثبت یک تراکنش واریز یا برداشت، این برای سیستم یک قانون مشخص و واضحه که نباید برای یک عملیات بیش از یک تراکنش ثبت بشه و اصطلاحا داپلیکیت وجود نداشته باشه، خوب اینو به عنوان قرارداد در کدتون اعمال میکنید، حالا فرض کنید با شرایط و قوانینی روبرو باشید که وابسته به شرایطن و ثابت نیستن، این مواردو توی فاز شناخت پروژه و داکیومنشن بایستی استخراج و در نظر بگیرید و برای چنین شرایط غیر ثابتی پالیسی و قوانینی پیاده سازی کنید.· قراردادهای پویا و ایجنت های خودمختارتاحالا راجع به قراردادهای ثابت و یا دارای شرایط و ضوابط صحبت کردیم، اما وقتی پای ایجنت های خودمختار وسط میاد داستان فرق میکنه. این مدل ایجنتها در سیستم میتونن هر درخواستی رو میخان رو ریجکت کنن، یا برای انجام چیزی مذاکره و منابعی رو درخواست کنن، با وجود این شرایط باز هم چنین سیستمی قطعا نیاز به قراردادها داره، فرض کنید یک سری کامپوننت و ایجنت که باهم در ارتباط و مذاکره هستن رو در یک سیستم داریم، که برای براورده کردن هدف نرم افزار طبق قراردادهای خاصی با هم ارتباط و رد و بدل دیتا میکنن، توی این حالت خوده نرم افزاره که انتخاب میکنه مسائلو به چه روشی حل بکنه.اما نکتش اینه که اگر ما از مدل DBC توی حالت دستی نتونیم استفاده کنیم، قطعا توی حالت اتومات هم نخاهیم توانست، پس اسبتونو زین کنید برای اینکه توی نرم افزار بعدی که مینویسید، این مدل رو پیاده کنید.دروس مرتبط: 24, 25, 38, 42, 43, 45منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Tue, 09 Feb 2021 23:58:06 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. مقدمه فصل 4</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D9%85%D9%82%D8%AF%D9%85%D9%87-%D9%81%D8%B5%D9%84-4-tayjwkcjq4fk</link>
                <description>فصل 4 : کج خیالی در عملگرایی Pragmatic Paranoia· شما نمیتونید نرم افزار بدون نقص بنویسیداین جمله اذیتت کرد؟ اذیت نشو. اینو به عنوان یکی از بدیهیات زندگی بپذیر. (گوگل شم سالی نیم ساعت میره تو دیوار)این جمله رو جشن بگیر، چون نرم افزار کامل و بدون نقصی وجود نداره. هیچ بشری در طول تاریخ کامپیوتر نرم افزار بدون نقص ننوشته، این بعیده که من و شما بتونیم. پس زمان تو صرف رسیدن به این رویای دست نیافتنی، هدر نکن.با توجه به این جمله ناامید کننده، پس چجوری عملگرایی رو به نتایج مثبت تبدیل کنیم؟ این موضوع این فصل از کتابه.هستن کسایی که خودشونو بهترین راننده روی زمین میدونن، که اون بیرون باید راه همه رو بگیرن، بین خطوط رانندگی کنن، با موبایل تکست بازی کنن، از تابلوهای توقف رد بشن، این مطابق استاندارد زندگی ما نیست، ما به شکلی دفاعی رانندگی میکنیم، همیشه قبل از حادثه بهش فکر میکنیم، تمام تلاشمونو میکنیم تا خودمونو تو گلی گیر نندازیم که ...در کدنویسی هم همینه داستان، ما معمولا با کدهای دیگران سر و کار داریم که در بدترین حالت ممکنه توش استانداردهای خوبی رعایت نشده باشه یا در مقابل ورودیهای خاص درست کار نکنه، برای همینه که مکانیزم دفاعی رو اتخاذ میکنیم، سعی میکنیم تمام حالتها رو در نظر بگیریم، همه چی رو ولیدیت کنیم، از assert ها استفاده کنیم و مقادیر رو بسنجیم، روی ستون های دیتابیس constraint میزاریم و خوشحال هم هستیم راجع از این قبیل کارها.اما برنامه نویسهای عملگرا فراتر از این میرن، اونها هیچ وقت به خودشونم اعتماد نمیکنن، اونا معتقدن هیچ کسی نمیتونه کد بی نقصی بنویسه و خودشونم جزو اون میدونن.منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Tue, 09 Feb 2021 10:09:00 +0330</pubDate>
            </item>
                    <item>
                <title>خلاصه کتاب Pragmatic Programmer. درس22</title>
                <link>https://virgool.io/@mr.rahmatzade371/%D8%AE%D9%84%D8%A7%D8%B5%D9%87-%DA%A9%D8%AA%D8%A7%D8%A8-pragmatic-programmer-%D8%AF%D8%B1%D8%B322-h4hl4rurfrdc</link>
                <description>درس 22: Engineering Daybooksدیوید (یا همون داوود خودمون) مدت کوتاهی برای یک شرکت تولید قطعات کامپیوتری کار میکرد، عموما با مهندسای الکترونیک و مکانیک سر و کار داشت. میگفت اونا همیشه و همه جا یک دفترچه یادداشت همراه شون بود، که عموما یک خودکارم ازش اویزون یا لاش بود، هر موقع صحبت یا جلسه ای داشتن یا حین کار دائما توش ی چیزایی یادداشت میکردن، Dave که براش عجیب بود سوال کرده بود ازشون که داستان چیه، و جالب اینه که اونا برای این کار آموزش دیده بودن و به نوعی جزوی از کارشون بود که همه چیزو یادداشت کنن، هرچیزی که انجام میدن، یاد میگیرن، ایده هایی که ناگهانی به ذهنشون میرسه، پارامترها و عددهایی که وسط کار باهاش سر و کار دارن و به نوعی هر چیزی که فکرشو بکنید یادداشت میکردن. موقعی ام که دفترچه پر میشد، اونو با تاریخ آرشیو میکردن و ی جدید در میاوردن، انگار ی جور مسابقه بین شون بود هر کی دفترچه های بیشتری پر کرده باشه.ما از نوشتن روی کاغذ معمولا برای یادداشت برداری در جلسات، مقادیری که حین دیباگ ممکنه سریع از دستمون در بره، ایده های ناگهانی، تودوها، پلنهای روز کاری، ریمایند و ... استفاده میکنیم.چند تا مزیت داره این کار:-  از حافظه خودمون مورد اطمینان تره-  ایده و فکرهای ناگهانی که وسط کار به ذهنتون میرسه رو سریعا یادداشت و سیو میکنید و به ادامه کارتون میرسید-  میتونید بعدا از آرشیو تون گزارش بگیرید و کارهایی که دقیقا در روزهای مختلف و سالهای قبل انجام دادید، جلسات، حتی لباسی که پوشیدید و... رو به یاد بیاریدبنابرین همیشه یک دفترچه یادداشت داشته باشید، از کاغذ استفاده کنید و نه از فایل و ویکی، نکته های فوق العاده ای در نوشتن و استفاده از کاغذ در مقابل تایپ کردن، وجود داره که علوم دیگه بهش پرداختن، ی ماه امتحانش کنید، و در عمل از فوایدش مستفیص بشید.اگر هم به هیچ دردتون نخورد، حداقل موقعی که بیلیونر یا معروف شدید نوشتن کتاب خاطرات یا بیوگرافی براتون کار راحتی تری خاهد بود.دروس مرتبط: 6, 37منبع کانال تلگرامی: https://t.me/pragmaticprogrammer_fa</description>
                <category>MohammadReza Rahmatzadeh</category>
                <author>MohammadReza Rahmatzadeh</author>
                <pubDate>Mon, 08 Feb 2021 23:06:06 +0330</pubDate>
            </item>
            </channel>
</rss>