<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های حامد مومنی</title>
        <link>https://virgool.io/feed/@2hamed</link>
        <description>من رو در شبکه‌های اجتماعی با شناسه @2hamed پیدا کنید و در گیت‌هاب.</description>
        <language>fa</language>
        <pubDate>2026-06-07 08:40:15</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/3325/avatar/avatar.png?height=120&amp;width=120</url>
            <title>حامد مومنی</title>
            <link>https://virgool.io/@2hamed</link>
        </image>

                    <item>
                <title>توضیح ریاضی شیوع کرونا و اینکه چرا در خانه ماندن حیاتی است</title>
                <link>https://virgool.io/@2hamed/%D8%AA%D9%88%D8%B6%DB%8C%D8%AD-%D8%B1%DB%8C%D8%A7%D8%B6%DB%8C-%D8%B4%DB%8C%D9%88%D8%B9-%DA%A9%D8%B1%D9%88%D9%86%D8%A7-%D9%88-%D8%A7%DB%8C%D9%86%DA%A9%D9%87-%DA%86%D8%B1%D8%A7-%D8%AF%D8%B1-%D8%AE%D8%A7%D9%86%D9%87-%D9%85%D8%A7%D9%86%D8%AF%D9%86-%D8%AD%DB%8C%D8%A7%D8%AA%DB%8C-%D8%A7%D8%B3%D8%AA-cw5idek1cyhz</link>
                <description>این روزها همه ما درگیر شیوع ویروس کرونا هستیم. بسیاری از کسب و کارها تعطیل شده و خیلی از شرکت‌های خصوصی برای جلوگیری از شیوع هر چه بیشتر این ویروس به دورکاری رو آوردن و اکثر نیروهاشون از خانه در حال انجام وظایف هستن.در این نوشته که برداشتی از این ویدیوی یوتیوب هست سعی داریم شیوع ویروس کرونا رو از طریق ریاضی شرح بدیم و در آخر نشون بدیم چرا در خانه ماندن بسیار بسیار مهم است. https://www.youtube.com/watch?v=Kas0tIxDvrg رشد نماییاکثر ماها در ریاضیات دبیرستان و دانشگاه با عبارت رشد نمایی یا Exponential Growth آشنا هستیم. رشد نمایی به تابعی گفته میشه که در هر مرحله ضریبی (بیشتر از ۱) از مرحله قبل خودش هست. در شکل زیر می‌تونید روند افزایشی یک تابع نمایی (خط سبز) رو ببینید و تفاوت اون رو با توابع خطی (خط قرمز) و توانی (خط آبی) مقایسه کنید.همونطور که در تصویر میبیند بعد از گذشت چند مرحله تابع نمایی ناگهان با رشد فزاینده از دو تابع دیگر پیشی می‌گیره و روند افزایشی بسیار سریعی رو میگیره.و اما ربطش با کرونا چیه؟به طوری کلی شیوع بسیاری از ویروس‌ها از یک تابع نمایی پیروی می‌کنه. به این صورت که برای مثال در روز اول شیوع تعداد افراد آلوده فقط یک نفره (N) و این یک نفر شانس این رو داره که E نفر دیگه رو با احتمال p آلوده کنه.فرمول شیوع کرونا با گذر هر روز; تعداد مبتلایان جدید تابعی از مبتلایان روز قبل است.بیاید با هم نگاهی به نرخ شیوع کرونا تو چین بندازیم.فکر می‌کنم توی تصویر شیب نسبتا نمایی رو کاملا واضح میبینیم. تازه این درحالیه که آمار اعلام شده گاها نادرسته و با واقعیت فاصله زیادی داره. این رو هم در نظر بگیرید که به گفته دانشمندان ۸۰ درصد از افراد آلوده به کرونا علائم خفیف دارن یا به کل علائمی ندارن به همین دلیل در هیچ آماری در نظر گرفته نمیشن.با احتساب آمار بالا تعداد افراد مبتلا در هر روز چیزی حدود ۱.۱۵ تا ۱.۲۵ برابر روز قبله.با یه حساب کتاب ساده می‌تونیم متوجه بشیم که اگر کرونا به صورت کنترل نشده به شیوعش ادامه بده می‌تونه تعداد افراد ناقل هر ۱۶ روز یکبار ۱۰ برابر بشه. یعنی پس از گذشت ۶۱ روز جمعیت افراد آلوده به بیش ۱۰۰ میلیون نفر میرسه.اما بیاید یکم در مورد فرمول بالا بیشتر صحبت کنیم.پارامتر E همونطور که گفتیم تعداد افرادی هستن که یک فرد آلوده می‌تونه به صورت بالقوه آلوده کنه و همچنین پارامتر p احتمال آلوده شدن یک فرد هستش. حالا تصور کنید که ما بتونیم E رو کاهش بدیم به این صورت که در جاهای پر رفت و آمد حاضر نشیم یا به طور کل قرنطینه خانگی رو رعایت کنیم.همچنین می‌تونیم با شست مداوم دست‌ها و رعایت مسائل بهداشتی میزان p رو هم کاهش بدیم.تصور کنید که ضریب ۱.۱۵ که بالاتر بهش اشاره کردیم با رعایت این موارد به ۱.۰۵ کاهش پیدا کنه. در این صورت به جای ۱۰۰ میلیون مبتلا در ۶۱ روز ما فقط با ۴۰۰ هزار نفر مبتلا روبرو هستیم.با کمتر کردن میزان افراد آلوده در مقیاس زمان به سیستم سلامتی (بیمارستان‌ها) این فرصت رو میدیم که به طور کامل از پس درمان و مراقب از بیماران بر بیاد، در حالیکه با وضع فعلی ظرفیت بیمارستان‌ها به طور کامل پر شده و هر روز شاهد از دست رفت کادر بیمارستانی هستیم.در این مطلب سعی کردم به صورت علمی اهمیت رعایت بهداشت و همچنین رعایت قرنطینه خانگی رو توضیح بدم. امیدوارم همه ما با رعایت این موارد و همچنین آموزش افراد دیگه بتونیم سهمی در کنترل شیوع این بیماری داشته باشیم.</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Wed, 11 Mar 2020 20:02:25 +0330</pubDate>
            </item>
                    <item>
                <title>پیاده سازی پردازش همزمان ولی کنترل شده با Go</title>
                <link>https://virgool.io/golangpub/%D9%BE%DB%8C%D8%A7%D8%AF%D9%87-%D8%B3%D8%A7%D8%B2%DB%8C-%D9%BE%D8%B1%D8%AF%D8%A7%D8%B2%D8%B4-%D9%87%D9%85%D8%B2%D9%85%D8%A7%D9%86-%D9%88%D9%84%DB%8C-%DA%A9%D9%86%D8%AA%D8%B1%D9%84-%D8%B4%D8%AF%D9%87-%D8%A8%D8%A7-go-fbesi9an417r</link>
                <description>زبان برنامه‌نویسی Go با اینکه نسبت به زبان‌هایی مثل Java, Python, JavaScript و ... خیلی جوان‌تره، اما هنوز هیچی نشده سر و صدای زیادی به پا کرده و برنامه‌نویسان زیادی رو به خودش جذب کرده. یکی از ویژگی‌هایی که باعث شده  Go انقدر محبوب بشه توانایی پیاده‌سازی برنامه نویسی همروند (Concurrent) به ساده ترین شکل ممکنه.اینکار انقدر ساده است که کافیه شما قبل از اجرای هر تابعی کلمه کلیدی go رو قرار بدید تا اون تابع به صورت همروند و داخل یک goroutine جداگانه انجام بشه. ابزار دیگه‌ای که goroutine ها رو خیلی جذاب و ساده می‌کنه بحث channel ها در گو هستش.گوفرها (gopher) به شدت مشغول کارند!خوب اینجا قصد ندارم در مورد goroutine ها و channel ها توضیح اضافه بدم و اگر با این مباحث آشنا نیستید پیشنهاد می‌کنم ابتدا با کمی جستجو اونها رو به خوبی یاد بگیرید تا بتونید از این مبحث استفاده کنید.بحث برنامه نویسی همروند در Go با اینکه بنظر خیلی ساده میاد اما ظرافت‌های خاصی داره که با دونستن‌ اونها شما می‌تونید سناریوهای خیلی جالبی رو پیاده سازی کنید و با ندونستنشون می‌تونید کدی بنویسید که نه تنها بهتر عمل نمی‌کنه بلکه از حالت ساده ترتیبی (Sequential) هم ضعیف تر باشه.در این مطلب قصد دارم توضیح بدم که چطور می‌تونیم برای کارهایی که میشه به صورت همزان انجام داد از حداکثر توان پردازشی CPU استفاده کنیم و در عین حال مراقب باشیم که بیش از حد از منابع سیستم استفاده نشه و به اصطلاح از Starvation جلوگیری کنیم.برای اینکه بتونیم راحت‌تر این مطلب رو درک کنیم، تصور کنید قراره برنامه‌ای بنویسیم که فایل‌های موجود درون یک پوشه رو با استفاده از الگوریتم MD5 هش کنیم و اونها رو درون یک فایل متنی همراه با اسم فایل ذخیره کنیم.مرحله اول: خواندن فایل‌هادر مرحله اول خیلی راحت با استفاده از کد زیر می‌تونیم محتویات یک پوشه رو بخونیم.reading files in a directoryبرای راحتی کار مسیر پوشه‌ای که قراره توش کار کنیم رو از ورودی shell میگیریم.مرحله دوم: پیاده سازی MD5 Hashingبرای راحتی کار تابعی می‌نویسیم که وظیفه hash کردن فایل‌ها رو انجام میده و به پاس دادن مسیر یک فایل هش md5ش رو بر میگردونه. تابع به صورت زیر خواه بود.md5File funcو فقط کافیه به اینصورت تابع مورد نظرمون رو فراخوانی کنیم.Calling md5Fileمرحله سوم: نوشتن روی فایلدر این مرحله ما می‌خوایم که هش های تولید شده رو داخل فایلی که مشخص می‌کنیم بنویسیم. برای اینکار تابع دیگه‌ای با نام writeToFile می‌سازیم با محتویات زیر:writeToFile funcو حالا کافیه که این تابع رو در کد اصلی فراخوانی کنیم.Calling writeToFile to write checksumsتا اینجای کار کد ما تقریبا کامله و اون کاری که قراره انجام بده رو انجام می‌ده. یعنی که اگر اجرا بشه تمام فایلهای داخل مسیر مشخص شده رو میخونه، هش می‌کنه و داخل فایلی که مشخص می‌کنیم ذخیره می‌کنه. اما وقتی داریم یه پوشه با هزاران فایل رو هش می‌کنیم قطعا مدت زمان زیادی رو منتظر خواهیم بود. هر چقدر هم که فایل‌ها سنگین تر باشن مدت زمان هش کردنشون هم بیشتر می‌شه.حالا بیاید این کد رو طوری تغییر بدیم که از تمام ظرفیت پردازنده‌های چند هسته‌ای ماشینمون استفاده کنه و کار رو به مراتب سریعتر انجام بده.شاید در نگاه اول با خودتون بگید خوب حالا همه کدها رو داخل goroutine اجرا می‌کنم و اینطوری خیلی سریعتر تموم میشه. یه چیزی شبیه به این.Let&#039;s run it all inside a goroutineپیشنهاد می‌کنم اینکار رو بکنید و خودتون نتیجه رو ببینید. قطعا مدت زمان کمتری صرف اجرای کد میشه ولی مشکلی که وجود داره اینه که خیلی زودتر از موعد به پایان میرسه. یعنی زمانی که هنوز تعدادی زیادی از فایلها هش نشدن و در فایل خروجی فقط تعداد محدودی از نتایج وجود داره.این حالت به این دلیل اتفاق میوفته که گوروتین اصلی ما منتظر پایان بقیه گوروتین‌ها نمیشه و هر زمان که خودش کارش تموم شه از برنامه خارج می‌شه.این مشکل رو میشه میشه استفاده از sync.WaitGroup برطرف کرد ولی هدف اصلی ما این نیست. مشکل دیگه‌ای که کد بالا داره اینه که اگر تعداد فایلها زیاد بشه با این حالت ما تمامی منابع سیستم رو اشغال می‌کنیم و اصطلاحا ماشین دچار Resource Starvation میشه و این یعنی که هیچ منابعی برای بقیه برنامه‌های در حال اجرای سیستم باقی نمی‌مونه.روش بهتر و درست‌تر اینه که ما همیشه به طور همزمان فقط تعداد محدودی عملیات هش داشته باشیم. مثل همیشه حداکثر ۱۰ تا فایل رو به صورت همزمان هش کنیم. برای اینکار می‌خوایم مفهموم worker رو داخل برنامه‌مون پیاده سازی کنیم. به اینصورت که همزمان تعدادی worker منتظر می‌مونن که ما براشون کار ارسال کنیم و اونها هم انجام بدن.همونطور که حدس زدید منظور از worker اینجا goroutine هایی هستن که روی چنلی که مخصوص ارسال job ها ایجاد شده، گوش وایسادن.مرحله چهارم: ساختن کارگرهابرای ساختن کارگرها ما تابعی می‌نویسیم که به تعداد مشخصی goroutine استارت میزنه و داخلشون روی pipeline که یه channel از نوع receive-only هست یه حلقه for میزنیم.spinupWorkersمرحله پنجم: Fan Out یا تقسیم کارهادر این مرحله باید کارهای رو تقسیم کنیم. به این صورت که با رسیدن به هر فایلی به جای اینکه همونجا محتویات رو باز کنیم و هش کنیم، اون رو با استفاده از pipelineی که ساختیم به یکی از worker های بیکار میرسونیم. به این کار به اصطلاح Fan Out هم گفته میشه. تابع اصلی ما تا به اینجای کار به این صورت خواهد بود.Fan Outخوب حالا که کارها رو تقسیم کردیم باید نتایج رو داخل یک فایل بنویسیم. می‌تونیم توی هر worker به صورت جداگانه نتایج رو داخل فایل خروجی بنویسیم، اما مشکلی که اینجا بوجود میاد اینه که با احتمال خیلی بالا وضعیتی پیش میاد که دو یا بیشتر worker بخوان همزمان نتایج کار خودشون رو داخل فایل بنویسن که به این حالت به اصطلاح race condition گفته میشه که شما باید نهایت تلاشتون رو بکنید که از این حالت جلوگیری بشه. و اما چاره کار...مرحله ششم: کارها رو جمع کن و به نوبت انجام بده (Fan In)توی این مرحله ما به موجودیتی احتیاج داریم که نقش یک کتابدار رو برای ما انجام بده. یعنی هر چیزی که قرار ثبت بشه فقط و فقط از طریق این شخص انجام بشه و خوب چه چیزی بهتر از یک goroutine که این کار رو برامون انجام بده که راه ارتباطی ما هم یه channel دیگه خواهد بود.Fan Inباید یادمون باشه تا worker هامون رو هم به روز کنیم که کاراشون رو تحویل کتابدارمون بدن.Updated workers now send their result to the fanIn channelتابع اصلی تا اینجا به این صورت خواهد بود.اما هنوز مشکلی که اول مطلب بهش اشاره کردیم وجود داره. یعنی هر زمان که گوروتین اصلی کارش تموم بشه بدون توجه با اینکه بقیه گوروتین‌ها هنوز در حال انجام کار هستن، برنامه به پایان می‌رسونه.رفع کردن این مشکل یکم نکته دار و tricky هست که سعی می‌کنم به بهترین نحو ممکن توضیح بدم.مرحله هفتم: صبر کن تا همه کارشون تموم شهبرای حل این مشکل ابتدا باید بفهمیم که تقدم و تأخر هر کدوم از کارهامون به چه صورت هست به این معنی که کدوم باید قبل از اون یکی خاتمه پیدا کنه. خوب طبیعیه که آخرین کاری باید انجام بشه نوشتن داخل فایل هستش. یعنی قبل از اتمام عملیات نوشتن باید همه کارگرها کارهاشون رو تموم کرده باشن و خارج شده باشن.پس کار ما ۳ مرحله خواهد داشت. اول اینکه به worker ها اطلاع بدیم که فایل‌ها تموم شدن و دیگه فایلی برای پردازش نمونده و می‌تونن خارج بشن. برای اینکار کافیه که بعد از مرحله filepath.Walk چنل مربوط به pipeline رو ببندیم. تو کد بالا close(pipeline) دقیقا همین کار رو انجام میده و خوب خاصیت حلقه for با استفاده از range اینه که هر زمان چنل بسته بشه به صورت خودکار از حلقه خارج می‌شه.مرحله ۲ اینه که یجوری چنل fanIn رو ببندیم و اینکار حتما باید بعد از اینکه تمام worker هامون خارج شدن انجام بشه. من می‌خوام اینکار با استفاده از sync.WaitGroup انجام بدم. به این صورت که هر کدوم از worker ها یه دونه به تعداد WaitGroupمون اضافه می‌کنن و هر کدوم بعد از اینکه کارشون تموم شد ازش کم می‌کنن.Workers with the WaitGroupو اما برای اینکه چنل fanIn رو ببندیم باید داخل یه گوروتین دیگه منتظر آزاد شدن WaitGroup باشیم.Wait for WaitGroup to close fanIn و اما تابع اصلی تا به اینجای کار...و در آخر هم باید گوروتین اصلی را تموم شدن کار کتابدار زنده نگه داریم. برای اینکار می‌تونیم از یک چنل کمکی استفاده کنیم. چنل writeDone که یه struct خالی قبول می‌کنه برای اینکار استفاده شده.writeDone channel to signal the main goroutineمرحله هشتم: Make it fasterاگه هنوز با من هستید بهتون تبریک می‌گم. برنامه شما کامله. تقریبا البته!منظورم اینکه اگر برنامه رو اجرا کنید قطعا به صورت همزمان شروع به هش کردن فایلها می‌کنه و پرفورمانس بالاتری نسب با حالت ساده (ترتیبی) خواهید داشت. حتی می‌تونید مطمئن باشید که از وقوع Race Condition جلوگیری کردید و همچنین قطعا برنامه تمام فایلهای شما رو هش و در فایل مورد نظر ذخیره خواهد کرد.اما ایراد کار کجاست؟!مشکل اینجاست که الان سرعت خواندن و هش کردن فایل‌ها چندین برابر شده، اما برنامه ما مجبوره برای اینکه نوشتن فایل با مشکل انجام نشه اون رو به ترتیب بنویسی و عملا برای سرعت اجرا bottleneck به وجود اومده.یکی از کارهایی که میشه اینجا انجام جمع کردن تعدادی از عملیات نوشتن و انجام اونها در یک مرحله است. به این صورت که مثلا هر ۱۰۰۰ تا فایلی که هش شد یکجا نتایجش روی فایل نوشته بشه.کافیه تابع writeToFile مون رو به صورت زیر تغییر بدیم.Batching write operationsو هنگام فراخوانی هم به صورت زیر عمل کنیم.خوب دیگه واقعا تموم شد.بد نیست کمی هم حالت‌های مختلف رو از نظر زمان اجرا با هم مقایسه کنیم.حالت اول: اجرای ترتیبیتو این حالت که همه چی به ترتیب اجرا میشه رو لپتاپ من که ۸ تا هسته داره برای هش کردن تعداد بیش از ۶۴ هزار فایل نتیجه اجرای برنامه با دستور time رو ببینید.real    9m20.475s
user    0m12.216s
sys     0m14.326sحالت دوم: اجرای همروند بدون Batch Writeهمونطور که حدس میزدیم گلوگاه اجرای برنامه ما و بدون نوشتن دسته‌ای عملا بهبودی در عملکرد نداشتیم.real    9m18.087s
user    0m18.455s
sys     0m23.135sحالت سوم: اجرای ترتیبی همراه با Batch Writeجالب اینجاست با پیاده سازی تکنیک ساده‌ای مثل Batch Writing خیلی خیلی زمان اجرامون بهبود پیدا می‌کنه.real    0m4.545s
user    0m3.678s
sys     0m1.176sاز ۹ دقیقه رسیدیم به ۴ ثانیه! :)و حالا...حالت چهارم: اجرای همروند همراه با Batch Writingreal    0m1.610s
user    0m4.372s
sys     0m0.969sزمان اجرا به کمتر ۲ ثانیه کاهش پیدا کرد.نکته مهم: این مورد رو نباید پشت گوش انداخت که فایلهایی که من برای تست استفاده می‌کنم بسیار کوچک هستند و قدرت همروندی زمانی مشخص میشه که فایل‌هامون حجم نسبتا بالایی داشته باشند.نتیجه این مطلب اینه که بفهمیم با استفاده درست از ابزار و تکنیک‌هایی که در دسترسمون هست چقدر می‌تونیم برنامه‌های سریعتر و بهینه‌تری بنویسیم و از سخت افزارمون نهایت استفاده رو ببریم. و مثل همیشه می‌تونید کدهای مربوط به این مطلب رو در گیتهاب من بهش دسترسی داشته باشید. https://github.com/2hamed/md5-workers پانوشت: اگر شما هم راه بهتر و بهینه‌تری رو می‌شناسید خوشحال میشم که در قسمت نظرات با من به اشتراک بذارید یا حتی بهتر ازون در موردش تو وبلاگ خودتون بنویسید.</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Tue, 07 May 2019 15:03:19 +0430</pubDate>
            </item>
                    <item>
                <title>ارزش کار عمیق یا اینکه چرا مولتی تسک بودن همیشه خوب نیست؟!</title>
                <link>https://virgool.io/@2hamed/%D8%A7%D8%B1%D8%B2%D8%B4-%DA%A9%D8%A7%D8%B1-%D8%B9%D9%85%DB%8C%D9%82-%DB%8C%D8%A7-%D8%A7%DB%8C%D9%86%DA%A9%D9%87-%DA%86%D8%B1%D8%A7-%D9%85%D9%88%D9%84%D8%AA%DB%8C-%D8%AA%D8%B3%DA%A9-%D8%A8%D9%88%D8%AF%D9%86-%D9%87%D9%85%DB%8C%D8%B4%D9%87-%D8%AE%D9%88%D8%A8-%D9%86%DB%8C%D8%B3%D8%AA-qmjsgqvdlxvl</link>
                <description>توی دنیای شلوغ و پلوغ امروز که همه چیز داره با سرعت سر و سام‌آوری پیش میره و تو این بازار کار رقابتی که ما توش هستیم مسلما توانایی سر و کله زدن با چند تسک به صورت همزمان خیلی توانایی جذابی به حساب میاد و مطمئنم که خیلی از کارفرماها نیز دنبال نیرویی می‌گردن که بتونه چند یا حتی چندین کار رو به صورت همزمان انجام بده.اما توی این نوشته قصد دارم کمی خلاف این موضوع صحبت کنم و بگم که همیشه این مولتی تسک بودن هم خوب نیست و نتیجه خوبی نمیده و می‌خوام به این نتیجه برسم که چرا گذاشتن همه کارها به کنار و تمرکز و تعمق روی یک تسک توانایی بسیار مهمتریه تا اینکه قادر باشید همزمان روی چندتا وظیفه کار کنید.بذارید از تجربه شخصی خودم براتون بگم.در طول عمر کاری من به این علت که با مباحث زیادی از برنامه‌نویسی سرور و موبایل و وب تا مدیریت گرفته آشنایی دارم، خیلی اوقات پیش میومده که در طول روز چندین تسک مختلف که به کل در حوزه‌های متفاوتی بودند رو در حال انجام داشتم.اوایل از اینکه می‌تونم این همه کار رو همزمان انجام بدم احساس غرور می‌کردم. حس نینجایی رو داشتم که تو همه جا سرک میکشه و خیلی حرفه‌ای هر کاری از دستش بر میاد رو انجام میده. حتی اطرافیان هم از این توانایی من شگفت زده بودن و واسشون سوال بود که چطوری می‌تونم این همه کار متفاوت رو همزمان انجام بدم.همه چیز به خوبی پیش می‌رفت تا اینکه کم‌کم این حس توی من شکل گرفت که یه جای کار ایراد داره. درسته که من خیلی کارها رو انجام می‌دادم و نهایت سعیم رو می‌کردم که بهترین کیفیت ممکن رو به اجرا بگذارم اما کم‌کم به این نتیجه رسیدم بعضی‌وقتا کارها اونجوری که ازشون راضی باشم انجام نمیشن. یا حتی اگه کار کیفیت قابل قبولی داره، من هیچ پیشرفتی رو تو خودم حس نمی‌کنم و این حس درجا زدن داشت کم کم شروع به آزارم می‌کرد.تا اینکه یک روز به من چیزی الهام شد...یکم درمورد کارکرد مغزمغز ما انسان‌ها ساختار واقعا شگفت انگیزی داره. این سازه حیرت‌آور از میلیاردها نورون (عصب) ساخته شده که تشکیل یک شبکه عصبی بسیار بزرگ و پیچیده رو میدن. تا به حال شده از خودتون بپرسید که ما چطور یک مهارت رو یاد میگیریم؟! یا اینکه چرا با تمرین در یک مهارت خاص می‌تونیم هر روز اون رو بهبود بدیم؟اگه خیلی ساده بخوام به این سوال جواب بدم، پاسخ به این صورت خواهد بود که مغز ما برای انجام هر کاری نیاز داره پیام‌های عصبی رو از قسمت‌های مختلف مغز به قسمت‌های دیگه خودش و همچنین به دیگر اندام‌های بدن بفرسته.پیام‌های از عصبی از نورون‌ها برای جابجایی استفاده می‌کنن و هر چه ارتباط بهتری بین نورون‌های درگیر وجود داشته باشه ما مهارت بیشتری در انجام اون کار خواهیم داشت. با تمرین و ممارست در انجام یک کاری، مغز ما برای اینکه بهتر بتونه اون کار رو انجام بده شروع می‌کنه به تقویت ارتباط بین نورون‌های درگیر و هر چه بیشتر اون کار رو تکرار کنید این ارتباط قوی‌تر و سریع‌تر خواهد بود. اینکار با استفاده تقویت ارتباطات بین عصب‌ها توسط ماده‌ای به نام Myelin توسط مغز صورت می‌گیره.پس حالا می‌دونیم که نقش تمرین و تکرار در این پروسه چی هست.و اما نقش کار عمیق یا Deep Workخوب تا اینجا متوجه شدیم که با تمرین و تکرار می‌تونیم در انجام یک کاری سرآمد باشیم. اما اکثر اوقات این تکرار و تمرین مداوم، نیازمند صرف زمانی بسیار طولانی هستش. یک ورزشکار حرفه‌ای سال‌ها و سال‌ها تمرین و تلاش کرده تا به جایی که هست رسیده.یک برنامه‌نویس حرفه‌ای که در کار خودش استاده سال‌ها تلاش کرده و هزاران ساعت کد نویسی انجام داده تا سرآمد حوزه کاری خودش شده.پس چطور میشه ما هم به این سطح برسیم؟ آیا لازمه ما هم همین قدر انرژی و زمان بذاریم؟ بله!!!اشتباه برداشت نکنید. من قرار نیست فرمول طلایی رو بهتون بدم که یک شبه ره صد ساله رو طی کنید. خیر. بهترین بودن نیازمند تلاش و تمرین مداوم و طولانی هست. اینجا فقط قصد دارم راهی رو معرفی کنم که شما رو تو این مسیر جلو بندازه. بهش به عنوان یک آپگرید ذهنی فکر کنید.بر می‌گردیم سر اصل مطلب.در مورد کارکرد مغز این نکته رو لازمه بگم که پروسه استحکام ارتباط عصب‌ها کار پرهزینه‌ای از لحاظ مصرف انرژی هست و مغز ما برای هر کار این پروسه رو انجام نمیده. فقط زمانی این پروسه استارت می‌خوره که به صورت مداوم اون نورون‌های خاص درگیر باشن و مغز برای بهینه سازی عملیات خودش شروع به استحکام ارتباطات می‌کنه.حالا تصور کنید که مغز شما در حال استحکام ارتباط تعدادی نورون خاص هست. در این لحظه دستور می‌رسه که اون قسمت رو رها کن و حالا به قسمت دیگه‌ای برو و کار دیگه‌ای رو انجام بده. این پروسه رو مدام تکرار کنید تا به مغز خسته‌ای برسید که نتونسته هیچ کدوم از شبکه‌های درگیر رو مستحکم کنه.حالا تصور کنید که شما برای مدت ۴ یا ۵ ساعت بدون مزاحم و با تمرکز عمیق به انجام کاری بپردازید. اینطوری به مغزتون فرصت دادید بدون وقفه و در بهترین و بهینه‌ترین حالت ممکن تمام تواناییش رو برای استحکام هر چه بیشتر ارتباط بین نورون‌های درگیر تقویت کنه.استفاده از این تکنیک به قدری تأثیر گذار و عمیقه که خیلی راحت می‌تونید مباحث بسیار سخت رو در کوتاه‌ترین زمان ممکن یاد بگیرید.تو بازار کار امروز همیشه تخصص حرف اول رو می‌زنه و کسی هم که همه چیز رو بلد باشه یا اصلا وجود نداره یا یک در میلیون پیدا میشه. ولی با استفاده از توانایی Deep Work شما می‌تونید اون چیزی رو بدست بیارید که شما رو تو زمینه کاری خودتون سرآمد می‌کنه، و اون توانایی استاد شدن در کوتاه‌ترین زمان ممکنه.و در آخر اگر دوست دارید در مورد تأثیرات کار عمیق و تمرکز بیشتر بدونید پیشنهاد می‌کنیم کتاب Deep Work نوشته Cal Newport رو حتما بخونید.اگر این مطلب براتون مفید بوده و یا فکر می‌کنی برای شخص دیگه‌ای می‌تونه مفید باشه خوشحال می‌شم لینک اون رو با بقیه به اشتراک بذارید. </description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Mon, 25 Feb 2019 16:58:10 +0330</pubDate>
            </item>
                    <item>
                <title>خودتون رو برنامه‌نویس می‌دونید؟! پس پروژه اویلر رو انجام بدید.</title>
                <link>https://virgool.io/Farzamhabibi/%D8%AE%D9%88%D8%AF%D8%AA%D9%88%D9%86-%D8%B1%D9%88-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87%D9%86%D9%88%DB%8C%D8%B3-%D9%85%DB%8C%D8%AF%D9%88%D9%86%DB%8C%D8%AF-%D9%BE%D8%B3-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D8%A7%D9%88%DB%8C%D9%84%D8%B1-%D8%B1%D9%88-%D8%A7%D9%86%D8%AC%D8%A7%D9%85-%D8%A8%D8%AF%DB%8C%D8%AF-w05jdgr0qyzg</link>
                <description>اگه الان از من بپرسن نظرت راجع به برنامه‌نویسی چیه پاسخ من این خواهد بود.برنامه‌نویسی کار خیلی خیلی راحتیه ولی سخت‌ترین شغل دنیاست!چرا سخته، چون فکر می‌کنم تنها رشته علمی دنیا باشه که شما هر روز و تا آخر عمر کاریتون باید یاد بگیرید تا از گردونه رقابت خارج نشید.و اما چرا راحته؟! به این دلیل که اگر ابزار کارتون رو درست و عمیق بشناسید خیلی راحت می‌تونید از پس هر کاری بر بیاید.پروژه اویلرو اما پروژه اویلر...پروژه اویلر مجموعه‌ای از مسائل هست که یک برنامه نویس می‌تونه با هر زبان برنامه‌نویسی که بلده یا دوست داره یاد بگیره اون‌ها رو انجام بده. در این مجموعه در حال حاضر بیش از ۶۰۰ مسئله وجود داره که بر اساس میزان سختی از آسون به سخت مرتب شدن.شما با ثبت نام توی سایت می‌تونید با حل کردن مسائل، صحت راه حل خودتون رو بسنجید و همچنین ببینید که نفر چندمی هستید که اون مسئله رو حل کرده.شرکت در این پروژه می‌تونه چندتا فایده داشته باشه. اول اینکه به شما کمک می‌کنه ریزه‌کاری‌های زبانی که باهاش کار می‌کنید رو خوب بشناسید. تقریبا تمامی مسائل بدون نیاز به هیچ کتاب‌خانه خاصی قابل حل هستند و در خیلی موارد عمق اطلاعات شما از زبان رو به چالش می‌کشن. این مورد می‌تونه هم برای برنامه‌نویسان تازه کار مفید باشه و هم برنامه‌نویس‌های باتجربه تر.همچنین اگر دارید زبان جدید رو یاد می‌گیرید پروژه اویلر می‌تونه بهتون کمک کنه که سریعتر با زبان مورد نظرتون آشنا بشید و قواعدش رو به خاطر بسپارید.فایده دیگه انجام دادن این پروژه اینه که به شما کمک می‌کنه تعدادی از مفاهیم پایه‌ای ریاضی رو اگر بلد نیستید یاد بگیرید و اگر بلدید واستون یادآوری بکنه. مفاهیمی مثل اعداد اول، انواع سری‌های ریاضی، مفهموم اعداد Palindromic (اعدادی که از هر طرف خونده بشن یکی هستن)، مفاهیم بازگشتی و ...نکته‌ای که در مورد مسائل هست اینه که اکثرا بیش از یک راه حل برای هر مسئله وجود داره. اگر راه حلی که طراحی کردید داره زمان خیلی زیادی می‌بره، احتمالا راه حل بهینه‌تری هم وجود داره.و اینکه سعی نکنید جواب مسائل رو توی اینترنت پیدا کنید. قرار نیست خودتون یا کسی رو گول بزنید چون نه جایزه‌ای در کاره و نه قراره چیزی نصیب کسی بشه، جز اینکه سطح دانش خودتون رو بالاتر می‌برید.اگر هم دوست داشتید می‌تونید با دوستانتون رقابت کنید. کافیه که از قسمت Friends کلید خودتون رو با دوستانتون به اشتراک بذارید.اونایی که دوست دارن این کلید منه:1433328_E85Ksc4RNtA9cA3ij4XIWmpSnf9xcO3m</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Thu, 14 Feb 2019 11:51:05 +0330</pubDate>
            </item>
                    <item>
                <title>برنامه‌نویس‌های جهان، متحد شوید!</title>
                <link>https://virgool.io/@2hamed/%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87%D9%86%D9%88%DB%8C%D8%B3%D9%87%D8%A7%DB%8C-%D8%AC%D9%87%D8%A7%D9%86-%D9%85%D8%AA%D8%AD%D8%AF-%D8%B4%D9%88%DB%8C%D8%AF-b5xqkkwxy1kw</link>
                <description>Programmers of the world, unite!من یک برنامه‌نویسم، و تا آخر هم برنامه‌نویس می‌مونم.مهم نیست که هر روز واسه کدی که می‌زنم پولی میگیرم یا نه. مهم نیست که مدیر فلان شرکت و مشاور بیسار شرکت خواهم بود یا نه.من یک برنامه‌نویسم.این  مطلب رو برای اون دسته از افرادی می‌نویسم که خودشون رو یک برنامه‌نویس  می‌دونن ولی برای برنامه‌نویس بودن تلاشی نمی‌کنن. ممکنه این حرف براتون  ناخوشایند باشه ولی شما برنامه‌نویس نیستید.برنامه‌نویس نیستید اگر هر روز به فکر یاد گرفتن چیز جدیدی نیستید.برنامه‌نویس نیستید اگر فقط در ساعات کاری و اون هم تو شرکت برنامه می‌نویسید.برنامه‌نویس نیستید اگر هیچ وقت سراغ متن‌باز و دنیای نرم‌افزارهای آزاد پا نگذاشتید.برنامه‌نویس نیستید اگر در گیتهاب فعالیتی ندارید و کدهاتون رو به صورت اوپن سورس منتشر نمی‌کنید.برنامه‌نویس نیستید اگر وبلاگ نمی‌خونید.برنامه‌نویس نیستید اگر وبلاگ نمی‌نویسید.برنامه‌نویس نیستید اگر به تکنولوژی خاصی تعصب دارید و سراغ چیزای جدید و متفاوت نمی‌رید.برنامه‌نویس نیستید اگر چیزی که بلدید رو به دیگری یاد نمی‌دید.برنامه‌نویس نیستید اگر در Stackoverflow عضو نیستید، سوال نمی‌پرسید و جواب نمی‌دید.برنامه‌نویس نیستید اگر در همایش‌ها و دورهمی‌های مختلفی که اطرافتون هست شرکت نمی‌کنید.برنامه‌نویس نیستید اگر حداقل ۵ تا برنامه‌نویس دیگه خارج از محل کارتون رو نمی‌شناسید.بدون اینها شما تنها یک کد نویس هستید. یک تایپیست! نه چیزی بیشتر.شاید  کلمات سخت باشن اما حقیقت دارن. اکثر برنامه‌نویس‌ها شخصیت‌های درون‌گرا  دارن و همین باعث میشه که برنامه‌نویس خوبی باشن. اگر درون‌گرا نباشید  نمی‌تونید ساعت‌ها جلوی مانیتور بشینید و کد بزنید و کد بزنید و کد بزنید.منِ  درون‌گرا ترجیح میدم اطرافم خلوت باشه و تو خلوت خودم با کدها و  کامپایلرها بازی کنم، اما دوره این روش تموم شده. قدرت ما انسان‌ها در جمع  شدنه و برنامه‌نویس‌ها هم انسان هستند (مگه اینکه خلافش ثابت بشه!).این  جمع شدن اما همیشه به این معنی نیست که ساعت‌های زیادی رو تو فلان همایش و  یا بهمان دورهمی بگذرونید (گرچه از نظر من حضور در این جمع‌ها برای شناختن  و شناخته شدن لازمه) بلکه می‌تونه خیلی راحت از پشت همون مانیتورتون انجام  بشه.شرکت در بزرگترین گردهمایی  برنامه‌نویس‌های جهان چیزی جز یه کامپیوتر که به اینترنت متصل باشه نیاز  نداره. منظورم گیت‌هابه! گیت‌هاب رو باز کنید، بخونیدش، کدهاتون رو روش  قرار بدید و ببینید که چطور عضوی از بزرگترین جامعه جهانی خواهید بود!یا  Stackoverflow! جای تأسفه که خیلی از کسانی که من میشناسم و خودشون رو  برنامه‌نویس می‌دونن حتی در استک‌اورفلو حساب کاربری هم ندارن! چه برسه به  اینکه سوال بپرسن و به سوالات دیگران پاسخ بدن!وبلاگ  بنویسید. وبلاگ نوشتن اگر برای زمان و حوصله خرج کنید مهارت‌های شما رو دو  چندان می‌کنه و همچنین اسمتون رو بر سر زبان‌ها می‌ندازه. نوشتن یک مطلب  آموزشی باعث میشه خودتون ابتدا در اون موضوع حرفه‌ای بشید. چرا که تا وقتی  نتونید چیزی رو به کسی آموزش بدید، واقعا اون رو بلد نیستید.یک  برنامه‌نویس خوب نباید ابزار براش مهم باشه. اینکه PHP بهتره یا Python یا  C# واقعاً بحث مهمل و بیهوده‌ایه. اینها همه ابزارهای انجام کارن. شمایی  که فقط PHP کار کردید و بس. مطمئن باشید در آینده‌ای نه چندان دور از صحنه  روزگار تکنولوژی عقب رونده خواهید شد. شمایی که فقط با C# و دات نت کار  می‌کنی. شما نیز همینطور. همه شماهایی که خودتون رو محدود به ابزار خاصی  می‌کنید.به جای زبان‌های برنامه‌نویسی مفاهیم برنامه‌نویسی رو یاد بگیرید. قدرت حل مسئله رو به توانایی‌هاتون اضافه کنید.معبود تویی، کعبه و بت‌خانه بهانه است...کسی  که واقعا برنامه‌نویس باشه فرقی واسش نمی‌کنه با PHP داره کد می‌زنه یا  C++ یا Python و یا هر زبان دیگه‌ای. و البته این رو می‌دونه که برای هر  کاری چه ابزاری مناسبه.شناختن برنامه‌نویس‌های دیگه چندتا حسن داره:فرصت‌های کاری بهتری سراغتون میاداز اینکه شرکت‌ها دارن رو چه چیزهایی کار می‌کنن مطلع میشیداز میزان حقوقی که شرکت‌های مختلف پرداخت می‌کنن با خبر می‌شید (یه برنامه‌نویس پولدار یه برنامه‌نویس خوشحاله!)از شرایط کاری شرکت‌ها مطلع می‌شید و متوجه میشید که دارید تو شرکتی که هستید وقت خودتون رو تلف می‌کنید یا نهپس خودتون رو بشناسید، هم صنفی‌هاتون رو بشناسید، یاد بگیرید و یاد بدید. اینطوری خوشحال‌تر زندگی می‌کنید.پ.ن:  عنوان این نوشته و البته عکس بکار رفته در بالا تغییر یافته شعار «کارگران  جهان، متحد شوید!» از کتاب مانیفست کمونیست کارل مارکسه.Workers of the world, unite! You have nothing to lose but your chains.پ.ن: کیفیت بهتری از تصویر بالا پیدا نکردم. اگر داشتید ممنون میشم برام بفرستید.</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Mon, 07 Jan 2019 10:25:43 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش Retrofit 2 در اندروید - قسمت ۲</title>
                <link>https://virgool.io/MobileLab/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-retrofit-2-%D8%AF%D8%B1-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-%D9%82%D8%B3%D9%85%D8%AA-%DB%B2-ckpovi2dxeun</link>
                <description>در قسمت اول  از آموزش Retrofit در اندروید به کلیات چگونگی استفاده از رتروفیت  پرداختیم. به طور حتم اگه در استفاده از رتروفیت تازه کار باشید نکات مبهم  بسیاری در قسمت اول وجود داره که در این پست سعی می‌کنم کمی بیشتر در مورد  اونها توضیح بدم.۱- رتروفیت چطور json دریافتی از سرور رو تبدیل به Object (شئ) می‌کنه؟پاسخ  اینجاست که رتروفیت اینکار رو نمیکنه، بلکه وظیفه این تبدیل رو  کتابخانه‌ای مثل Gson بر عهده داره. روش کارش هم به این صورته که شرح  می‌دم.ابتدا لازمه وابستگی‌های زیر رو به فایل build.gradle ماژول app برنامه‌تون اضافه کنید.dependencies {
    compile &#039;com.google.code.gson:gson:2.8.2&#039; // همیشه فکر خوبیه که وابستگی به کتابخانه اصلی رو به صورت مستقل هم داشته باشیم
    compile &quot;com.squareup.retrofit2:converter-gson:2.3.0&quot;
}خط اول که خوب کتابخانه اصلی  Gson رو وارد پروژه می‌کنه و خط دوم تبدیل کننده مخصوص Gson برای Retrofit  هست. این تبدیل کننده پل اصلی ارتباط Retrofit و Gson هستش.حالا  در مرحله دوم باید این تبدیل کننده رو به Retrofit بشناسونیم. در قسمت اول  اون قسمت که یک نمونه از Retrofit می‌ساختیم که یادتون هست؟retrofit = new Retrofit.Builder().build();فقط کافیه به صورت زیر converter رو به رتروفیت معرفی کنیم.retrofit = new Retrofit.Builder()
      .addConverterFactory(GsonConverterFactory.create())
      .build();۲- چطور فقط یکبار Retrofit رو بسازیم و همه جا ازش استفاده کنیم؟در  قسمت اول ما به صورت موقت آبجکت رتروفیت رو داخل Activity ایجاد کردیم که  خوب مسلما روش درستی نیست. چرا که مجبوریم در Activityهای مختلف هر بار این  آبجکت رو از اول بسازیم. راه حل این مشکل در این مرحله می‌تونه این باشه  که ما یکبار آبجکت رو در کلاس Application ایجاد کنیم و ساختن آبجکت  رتروفیت رو بسپاریم به Application. احتمالا به نحوه ساخت کلاس Application  آشنایی دارید پس توضیح بیشتری در این مورد نمیدم و فقط به نمونه کد زیر  بسنده می‌کنم.public class MyApp extends Application {
   private static MyApi myApi;
   private static Retrofit retrofit;

   @Override
   public void onCreate() {
      super.onCreate();
      createMyRetrofitInstance();
   }

   private void createMyRetrofitInstance() {
      retrofit = new Retrofit.Builder()
            .addConverterFactory(GsonConverterFactory.create())
            .build();
      myApi = retrofit.create(MyApi.class);
   }

   public static MyApi getMyApi() {
      return myApi;
   }

   public static Retrofit getRetrofit() {
      return retrofit;
   }
}پس از اون کافیه هربار موقع استفاده خیلی راحت مثل کد زیر عمل کنیم.MyApp.getMyApi().getPosts().enqueue(...);در  نهایت مطمئنا نکات زیاد دیگه‌ای هست که میشه در موردش صحبت کرد که در  پست‌های بعدی و تکمیلی در موردش خواهم نوشت. اگر سوالی بود حتما کامنت  بذارید.</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Mon, 07 Jan 2019 10:22:16 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش استفاده از Retrofit 2 در اندروید</title>
                <link>https://virgool.io/MobileLab/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D8%A7%D8%B2-retrofit-2-%D8%AF%D8%B1-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-knqlaj4dmftj</link>
                <description> Retrofit 2, a type safe HTTP client for Androidدر این مقاله سعی میکنم روش استفاده از کتابخانه Retrofit 2 رو در اندروید به زبان ساده و تا جای ممکن با مثال شرح بدم.اول مقدمه‌ای بر اینکه اصلا Retrofit چی هست و به چه دردی می‌خوره.تو  دنیای امروز تکنولوژی اکثر برنامه‌های موبایلی نیاز دارن تا با یک سرور در  ارتباط باشن و یا دیتای مورد نظرشون ازش بگیرن یا براش یک سری اطلاعات  ارسال کنن یا بالعکس. برای انجام این کار در اندروید روش‌های زیادی وجود  داره.انواع و اقسام کتابخانه برای این  کار طراحی شده و هر کدوم قابلیت‌های خودشون رو دارن ولی چیزی که همه اینها  به صورت مشترک ازش استفاده می‌کنن کلاس HttpUrlConnection هستش که پایه‌ای ترین کلاس برای ایجاد یه ارتباط با اینترنت و کلا هر جایی که زبون HTTP رو می‌فهمه و صحبت می‌کنه.و  اما مشکلی که استفاده از کلاس HttpUrlConnection داره اینه که استفادش  راحت نیست و پیاده‌سازی سناریوهای مختلف و پیچیده‌تر از یک کانکشن ساده  می‌تونه سخت و طاقت فرسا باشه. حالا فکر کنید که یک اپلیکیشن دارید که قرار  به چندین اندپوینت مختلف درخواست بفرسته که از متد REST استفاده می‌کنند.مشکلاتی ازین دست که هر کدوم از کتابخانه‌های مذکور سعی کردن به نحوی برطرفش بکنن.و اما Retrofit...رتروفیت که خودش از کتابخانه بسیار معروف OkHttp استفاده می‌کنه و هر دوی اون‌ها محصول شرکت  Square  هستن سعی می‌کنه پیاده سازی اپلیکیشن‌هایی که با اینترنت سر و کار دارن و  با API ها مخصوصا اونهایی که با REST کار می‌کنن رو خیلی راحت و مثل آب  خوردن کنه. برای این کار هم از Annotationها استفاده می‌کنه. چجوری؟! حالا  میگم...فرض  کنید اپلیکیشنی قراره بنویسیم که می‌خواد لیستی از پست‌های یک وبلاگ رو  نمایش بده. هر پست وبلاگ خصیصه‌هایی مثل شناسه یوزر &#x60;userId&#x60;، شناسه پست  &#x60;id&#x60;، عنوان &#x60;title&#x60; و متن پست &#x60;body‍&#x60; رو درون خودش جای داده. نمونه JSON  یک پست رو در زیر می‌بینید:{
    &quot;userId&quot;: 1,
    &quot;id&quot;: 1,
    &quot;title&quot;: &quot;sunt aut facere repellat provident occaecati excepturi optio reprehenderit&quot;,
    &quot;body&quot;: &quot;quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto&quot;
  }فرض کنید سرور شما قراره لیستی از این پست‌ها رو به شما برگردونه. می‌تونید خروجی مورد نظر رو در این آدرس ببینید.برای  این که ما بتونیم از این JSON استفاده کنیم بهترین کار (و البته روش درست)  اینه که یه کلاس Post به صورت زیر تو کدمون داشته باشیم.public class Post {
    private int userId;
    private int id;
    private String title;
    private String body;
    
    public int getUserId() {
        return userId;
     }
     public void setUserId(int userId) {
         this.userId = userId;
     }
     public int getId() {
         return id;
     }
     public void setId(int id) {
     	this.id = id;
     }
     public String getTitle() {
     	return title;
     }
     public void setTitle(String title) {
     	this.title = title;
     }
     public String getBody() {
     	return body;
     }
     public void setBody(String body) {
         this.body = body;
     }
}در این مرحله میریم سراغ خود  Retrofit. قبل از هر چیزی باید وابستگی (dependency) Retrofit رو به گریدل  خودتون اضافه کنید و پروژه خودتون رو Sync کنید.compile &#039;com.squareup.retrofit2:retrofit:2.3.0&#039;در  ادامه لازمه یک نمونه (instance) از Retrofit بسازیم. موقتا این کار رو  داخل Activity انجام می‌دیم. گرچه به یاد داشته باشید که اینکار درست نیست و  روش درست‌ترش اینه که برای اپلیکیشن‌های بزرگ داخل کلاس Application تعریف  بشه و یا بهتر از اون از Dagger استفاده بشه. ولی خوب فعلا سراغشون  نمی‌ریم.public class MainActivity extends AppCompatActivity {
	Retrofit retrofit;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		retrofit = new Retrofit.Builder().build(); // فعلا به همین صورت ساده بسنده می‌کنیم.
		}
}حالا برای اینکه بتونیم به  اندپوینت‌های مختلف API دسترسی داشته باشیم، باید یک interface ایجاد کنیم  که به ازای هر endpoint از APIمون یک متود داخلش تعریف می‌کنیم. فعلا فقط  برای گرفتن لیستی از پست‌ها این کارو می‌کنیم.public interface MyApi {
   @GET(&quot;https://jsonplaceholder.typicode.com/posts&quot;)
   Call&lt;List&lt;Post&gt;&gt; getPosts();
}تکه کد بالا دو قسمت مهم داره.  اولیش مربوط به کد &#x60;@GET&#x60; هست که میگه به آدرس مشخص شده داخل پرانتز یک  درخواست GET ارسال بشه. قسمت مهم بعدی نیز خروجی متود getPosts هست. به  خروجی متود دقت کنید. فعلا اون تیکه Call رو کار نداشته باشید و به داخلش  توجه کنید  &#x60;List&lt;Post&gt;&#x60;. اینجا مشخص میکنیم که چیزی که از سرور برای  ما میاد فهرستی از پست‌ها خواهد بود. حالا اینکه Retrofit چطور این کار رو  انجام میده تو مرحله بعد توضیح میدم.رتروفیت  برای اینکه بتونه دیتای دریافتی از سرور رو که به فرمت JSON هست به object  جاوا تبدیل کنه نیاز به یک ابزار مناسب داره که خوب معروف‌ترین این  ابزارها Gson هستش و البته به طور خاص‌تر ابزار retrofit-gson-converter که تنها لازمه خط زیر رو به فایل build.gradle ماژول appتون اضافه‌کنید.compile &#039;com.squareup.retrofit2:converter-gson:2.3.0&#039;این  کار گرچه لازمه اما کافی نیست. ما یه جوری باید به رتروفیت بفهمونیم که از  این استفاده کنه. برای اینکار لازمه به اون تیکه کدی که رتروفیت رو میسازه  یه خط اضافه کنیم. به این صورت:retrofit = new Retrofit.Builder()
    .addConverterFactory(GsonConverterFactory.create())
    .build();حالا دیگه رتروفیت می‌فهمه که باید از Gson استفاده کنه. اینکه Gson چطوری این تبدیلات رو انجام میده هم مربوط به بحث دیگریه.و اما ادامه ماجرا...حالا نیاز داریم interfaceی که بالاتر ساختیم رو یه جوری به رتروفیت متصل کنیم. برای اینکار از کد زیر استفاده می‌کنیم.MyApi myApi = retrofit.create(MyApi.class);حالا که یک نمونه از کلاس MyApi رو داریم خیلی راحت میتونیم از متودهای داخلش استفاده کنیم. myApi.getPosts().enqueue(new Callback&lt;List&lt;Post&gt;&gt;() {
	@Override
	public void onResponse(Call&lt;List&lt;Post&gt;&gt; call, Response&lt;List&lt;Post&gt;&gt; response) {
		List&lt;Post&gt; posts = response.body(); // اینجا خیلی راحت فهرست پست‌ها که توسط Gson ساخته شده رو در اختیار داریم
	}
	
	@Override
	public void onFailure(Call&lt;List&lt;Post&gt;&gt; call, Throwable t) {
		// این متود هم فقط زمانی فرخوانی می‌شه که به هر دلیلی کانکشن ما با مشکل روبرو بشه
	}
});خوب احتمالا باید بدونید که  تو اندروید اجرای عملیات شبکه نیاز به هیچ وجه نباید روی thread اصلی  برنامه اجرا بشه. به همین دلیل ما از متود enqueue استفاده می‌کنیم که این  مشکل ما رو حل میکنه یعنی کانکشن زدن و خوندن دیتا رو روی Background  Thread انجام میده.خوب تا اینجا خیلی  ساده سعی کردم استفاده از رتروفیت رو در پایه‌ای ترین حالت خودش توضیح بدم.  یادتون باشه که این مثال در عمل بهتره که از ابزارهای حرفه‌ای تری استفاده  بشه. برای مثال بهتره که وظیفه ساختن کلاس Retrofit و همچنین ایجاد نمونه  از interface ها رو به کتابخونه‌ای مثل Dagger بسپریم.همچنین میشه با استفاده از RxJava خیلی کد قشنگ‌تر، خواناتری داشته باشیم به علاوه اینکه میتونیم از قدرت Obervable ها نیز استفاده کنیم.سعی می‌کنم تو پست‌های بعدی مثال این مقاله گسترش بدم و روش‌های بهتری که برای پیاده سازی Retrofit هست رو شرح بدم.کد کامل این مقاله رو می‌تونید در آدرس گیتهاب زیر پیدا کنید و ازش الگو برداری کنید. https://github.com/2hamed/RetrofitSampleApp لطفا نظرات و انتقادات خودتون مطرح کنید و اگر توضیح بیشتری لازمه بگید که بگم.پ.ن. نکاتی که فکر می‌کردم در این مطلب جا افتاده رو در پستی جداگانه نوشتم.</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Mon, 07 Jan 2019 10:19:07 +0330</pubDate>
            </item>
                    <item>
                <title>آموزش ساخت Custom View در اندروید</title>
                <link>https://virgool.io/MobileLab/%D8%A2%D9%85%D9%88%D8%B2%D8%B4-%D8%B3%D8%A7%D8%AE%D8%AA-custom-view-%D8%AF%D8%B1-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-yd7lwsftsl5z</link>
                <description>احتمالا بارها پیش اومده که در برنامه‌ای که می‌نویسید به المانی نیاز پیدا کنید که در میان ابزارها و Viewهای خود اندروید وجود نداشته باشه. در این مواقع به احتمال بسیار بسیار زیاد می‌تونید چیزی که می‌خواید رو در میان هزاران کتابخانه اوپن سورسی که در اینترنت موجود هست پیدا کنید.اما احتمالا مواقعی هم بوده که چیزی رو که می‌خواستید پیدا نکردید و یا اگر هم پیدا کردید دقیقا اون چیزی نیست که می‌خواید. در این جور مواقع ۲ راه پیش رو دارید. یا اینکه به طراحتون بگید که طرح رو بر اساس ابزاری که موجود هست تغییر بده یا اینکه دست به کار بشید و خودتون اون چیزی که لازم دارید رو بسازید.در این مطلب ما قصد داریم از پایه ترین حالت ممکن یک Custom View بسازیم. ابتدا قبل از هر کاری ببینیم چیزی که قراره بسازیم چی خواهد بود. همونطور که میبینید چیزی که قراره ساخته بشه یک دکمه ضبط با چهار حالت بیکار، آماده، در حال ضبط و در حال بارگزاری خواهد بود.نکته: من در این آموزش از زبان Kotlin استفاده می‌کنم که اگر با کاتلین آشنا نیستید پیشنهاد می‌کنم هر چه سریع‌تر دست به کار بشید و یاد گرفتنش رو شروع کنید.مرحله ۱: اکستند از ویواولین کاری که باید انجام بدیم ساختن کلاس Viewمون هست که خوب مشخصا باید از کلاس View اندروید اکستند بشه. اسم ویو رو همونطور که میبینید RecordButton گذاشتیم. https://gist.github.com/2hamed/56fb6303ef9065d01ed7d985d5a8e4b6 در توضیح کد بالا باید بگم که ما در اینجا دو تا از Constructorهای کلاس View رو override می‌کنیم. این ۲ constructor معمولا پرکاربردترین حالت‌ها هستند که البته حالت‌های دیگری هم وجود داره که استفاده متفاوتی دارند.مرحله ۲: محاسبه ابعاد و اندازه‌هادر این مرحله ما ابتدا به سراغ ایجاد ساده‌ترین حالتمون میریم. یعنی مود بیکار یا Idle که از دو تا دایره تشکیل شده. دایره کوچکتر مرکز سفید رنگمون هست و دایره بزرگتر حاشیه خاکستری رنگ.دایره سفید در مرکز و قوس خاکستری در اطرافابتدا قبل از شروع کشیدن دایره‌ها لازمه که بدونیم ویوی ما دارای چه ابعادی هست. اینکه عرض و ارتفاع چه مقداری هست که ما بتونیم مرکز دایره و شعاعش رو مشخص کنیم. برای اینکه بتونیم این محاسبات رو انجام بدیم باید بدونیم که ابعاد ویوی ما چیا هستن و برای اینکار متود onMeasure رو override می‌کنیم. https://gist.github.com/2hamed/e3b5d5ff975bd95ec5163b621eef17d2 توضیح: در قسمت بالایی کد متغیرهای رو تعریف می‌کنیم که قراره مرکز ویو و شعاع دایره بزرگ رو تو خودشون نگه دارند. در خط اول onMeasure هم super.onMeasure رو صدا می‌زنیم که اجباری هست در این حالت و حتما باید حضور داشته باشه. توی اون if این شرط رو چک می‌کنیم که حتما اندروید به ویوی ما ابعادش رو تخصیص داده باشه و اگر هر کدوم از ارتفاع یا عرض، صفر بودن منتظر دوباره صدا زده شدن متود onMeasure می‌شیم.داخل شرط هم که مشخصه مرکز ویو رو با تقسیم کردن عرض و ارتفاع بر ۲ به دست میاریم. شعاع هم برابر میذاریم با ۹۵ درصد کوچکترین بعد. یعنی ۹۵ درصد ارتفاع یا عرض، هر کدوم که کوچکتر بود و همچنین مقدار padding رو هم ازش کم می‌کنیم.تذکر: اینکه چرا من ۹۵ درصد رو انتخاب کردم کاملا به سلیقه شخصی بر می‌گرده و شما می‌تونید هر چیزی بذاریدش.مرحله ۳: مشخص کردن رنگ و مشخصات اجزاءالان نوبت مشخص کردنه رنگ و بقیه مشخصات دایره و قوسمون رسیده. برای اینکار از کلاس Paint استفاده می‌کنیم. https://gist.github.com/2hamed/103cd73b7ca7c7d5fb4ed98fefc79d1e آبجکت innerPaint مربوط به دایره سفید رنگ وسط و outerPaint مربوط به دایره بیرونی هستش. نظر شما رو به radiusDiff هم جلب می‌کنم که مشخص میکنه دایره بیرونی ما چقدر بزرگتر از داخلیه باشه. مشخصه‌ی isAntiAlias هم برای اینه که دایره‌های ما اون حالت روان خودشون رو داشته باشن و اصطلاحا پیکسلی (pixelated) نشن.مرحله ۴: نقاشی روی بوممرحله کشیدن یا Draw میشه گفت مهمترین مرحله تو ساخت یک Custom View به حساب میاد که با override کردن متود onDraw انجام میشه. در اینجا با یک آبجکت Canvas سر و کار داریم که مثل یک بوم نقاشی کاملا خالی هستش و می‌تونیم هر چیزی رو داخلش نقاشی کنیم.این آبجکت Canvas چیزی هست که در نهایت به کاربر نمایش داده میشه.در اینجا ما ابزارهایی داریم که با کمک اونها می‌تونیم نقاشی کنیم که در این مرحله ما فقط از ابزار کشیدن دایره استفاده می‌کنیم. متود Canvas.drawCircle با دریافت مختصات x و y مرکز و مقدار شعاع و یک آبجکت Paint روی بوم دایره می‌کشه. https://gist.github.com/2hamed/e46f20d480590341d966a9ee71a35b40 تذکر: یک نکته مهم که اینجا لازمه یاداور بشم اینه که توی متود onDraw به هیچ وجه نباید allocation انجام بشه. به این معنی که هیچ آبجکت جدیدی نباید ساخته بشه و بهش حافظه تخصیص داده بشه. به طور کلی هیچ کار سنگینی نباید انجام بشه و این نکته به این دلیله که اندروید برای اینکه بتونه کیفیت انیمیشن‌ها و نمایش تصویرش رو حفظ کنه نیاز داره که در هر ثانیه، ۶۰ بار صفحه رو آپدیت کنه و این یعنی ما فقط فرصت داریم در فاصله یک فریم شکل مورد نظرمون رو بکشیم که میشه چیزی حدود ۱۶ میلی‌ثانیه. هر کاری بیش از این مقدار باعث ایجاد لگ میشه. پیشنهاد می‌کنم این مطلب رو در مورد این نکته بخونید.مرحله ۵: افزودن حالت‌های آماده و در حال ضبطدر این مرحله ما نیاز داریم که حالت‌های مختلفی رو نمایش بدیم. بهترین ابزاری که می‌تونید برای ذخیره و نمایش چند حالت خاص استفاده کنید از نظر من enum class هست. اگر نمی‌دونید enum ها چی هستن پیشنهاد می‌کنم این مطلب رو در سکان آکادمی بخونید.اگر خاطرتون باشه ما بطور کل ۴ حالت متفاوت داشتیم. حالت‌های بیکار، آماده، در حال ضبط و در حال بارگزاری که به ترتیب با Idle، Ready، Recording و Loading مشخص می‌شن. و کلاس enum به صورت زیر خواهد بود. https://gist.github.com/2hamed/a8c413b95490ecba4706681badf4a4e3 آیتم جدید دیگری که باهاش روبرو هستیم نمایش یک مربع قرمز برای حالت در حال ضبط هست. برای کشیدن یک مربع روی بوم ما نیاز به یک آبجکت از کلاس RectF داریم که چهار لبه مربعمون رو مشخص می‌کنه و برای اینکه بتونیم درست تشخیص بدیم که کجا این مربع قرار میگیره به سراغ متود onMeasure میریم. https://gist.github.com/2hamed/926355b85b5e793796fa50b22154794a توضیحات: در این قسمت به غیر از متغیرهای قبلی ما دو متغیر جدید recordRadius که برای اندازه دایره و مربع قرمز و recordRect برای مختصات مربع قرمز داریم. من در اینجا مقدار recordRadius رو برابر با یک چهارم دایره بزرگ قرار دادم و با کم و زیاد کردن recordRadius از مختصات مرکز، ابعاد recordRect رو نیز مشخص کردم. recordPaint هم که برای مشخص کردن رنگ قرمز استفاده شده.حالا دوباره نوبت نقاشی روی بوم رسیده. https://gist.github.com/2hamed/cb5fcb2580b410163ed1f5b0bb024069 مرحله ۶: در حال بارگزاریبرای حالت در حال بارگزاری یا Loading ما به ابزار جدیدی به نام Arc (قوس) احتیاج داریم. چون با توجه به درصد پیشرفت (progress) ممکنه لازم باشه فقط مقدار کمی از دایره بیرونی کشیده بشه. خوشبختانه کشیدن یک قوس بسیار راحته. یک قوس هم مثل یک مربع نیاز به یک آبجکت RectF داره که مشخص کنه در کجا این قوس کشیده بشه. پر واضحه که ابعاد این مربع، در متود onMeasure مشخص میشه. https://gist.github.com/2hamed/d564b4c1dd4f83019590f9cbd96348f4 و سپس نقاشی... https://gist.github.com/2hamed/e9cf81b00cbf69b87faad2d8242bf07b توضیحات: برای کشیدن یک قوس ما علاوه بر داشتن RectF نیاز به زاویه هم داریم که خیلی راحت مقدار progress رو تبدیل به کسر ۱۰۰ کرده و ضربدر 360 درجه می‌کنیم. مثلا با داشتن مقدار ۵۰ برای progress ابتدا ۵۰ رو تقسیم بر ۱۰۰ می‌کنیم که به عدد ۰.۵ می‌رسیم و سپس با ضرب در ۳۶۰ به زاویه ۱۸۰ میرسیم.مرحله ۷: جمع بندی و تمیز کارینکته دیگری که لازمه بهش اشاره کنیم به روزرسانی View در مرحله‌ای بعد از ایجاد اون هست. برای مثال ممکنه بخوایم از مود آماده به مود در حال ضبط بریم یا اینکه بخوایم درصد پیشرفت رو به روز کنیم. برای اینکه ما به ویو خبر بدیم که مقادیر تغییر کرده و نیازه که از ابتدا مرحله draw انجام بشه می‌تونیم از متود invalidate() استفاده کنیم. به این صورت که هر زمان هر کدوم از مقادیر ذکر شده تغییر کرد ما invalidate رو صدا بزنیم. به این صورت: https://gist.github.com/2hamed/976c8e5df7d52f215cb3b103e7838e5e یه مورد دیگه اینکه ما برای تغییر واحد dp به px از فانکشن dpToPx استفاده کردیم که تعریفش رو در ادامه میبینید.fun dpToPx(dp: Int) = (dp * resources.displayMetrics.density).toInt()تمام! شما الان یک CustomView ساختید که همه اجزاش از پایه درست شدن. ساختن CustomView برای ایجاد اشکال پیچیده خیلی بهینه‌تر و سریعتر از استفاده از Layoutهای پیچیده و تو هم هست. امیدوارم که توضیحاتم واضح بوده باشه و اگر فکر می‌کنید قسمتی رو گنگ توضیح دادم حتما در قسمت نظرات یاآور بشید که اصلاحش کنم.برای اون دسته از برنامه‌نویسان علاقه مند هم به عنوان تمرین می‌تونید خودتون قسمت بعدی که نمایش درصد پیشرفت داخل ویو هست رو انجام بدین.همونطور که می‌بینید در اکثر مواقع ساختن یک CustomView خلاصه میشه به استفاده و ترکیب همین ابزارهای ساده که دونستشون کمک می‌کنه کدهای بهتری و در نتیجه پروژه‌های بهتری رو بتونیم ایجاد کنیم.مثل همیشه تمام سورس این آموزش در مخزن گیت‌هاب زیر موجود است. https://github.com/2hamed/RecordButton </description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Tue, 01 Jan 2019 15:44:04 +0330</pubDate>
            </item>
                    <item>
                <title>داکر چیست؟ چگونه از داکر در کار استفاده کنیم؟</title>
                <link>https://virgool.io/@2hamed/%D8%AF%D8%A7%DA%A9%D8%B1-%DA%86%DB%8C%D8%B3%D8%AA-%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%A7%D8%B2-%D8%AF%D8%A7%DA%A9%D8%B1-%D8%AF%D8%B1-%DA%A9%D8%A7%D8%B1-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%DA%A9%D9%86%DB%8C%D9%85-yrvaoipe8q0i</link>
                <description>خب به نظرم یکم از دنیای اندروید فاصله بگیریم و یه سری هم به دنیای برنامه‌نویسی بک‌اند سری بزنیم بد نباشه.داکر، نسل جدید مدیریت سروربذارید اول بگم این مطلب مناسبه چه افرادیه. اگر شما برنامه نویسی بک‌اند یا فرانت‌اند هستید و توی تیم کار یا تنها این مطلب مناسب شماست. اگر شما SysAdmin هستید یا برنامه‌نویسی هستید که به دنیای SysAdmin ها یا DevOps کارها علاقه دارید هم این مطلب برای شماست. یا حتی اگر برنامه نویسی هستید که گاها با تکنولوژی‌های خاص و جدید و متفاوتی کار می‌کنید و از ستاپ کردن‌ها و نصب کردن‌های طولانی خسته شدید، باز هم این مطلب براش شماست.خلاصه بگم; اگر برنامه نویس هستید باید با داکر آشنا بشید.و اما جواب این سوال که کلا داکر (Docker) چیه؟داکر ابزاری برای ساختن، ارائه و اجرای پلتفرم‌های مختلف نرم‌افزاریه. می‌خواد روی لپ‌تاپ باشه یا روی ماشین مجازی رو سرور یا اصلا Cloud. داکر چیزی شبیه به مجازی‌سازهای معمول مثل KVM, VirtualBox , یا VMWare هستش ولی خوب به طور کلی با اونها فرق می‌کنه.شما اگر یک ماشین مجازی با یکی ابزارهای بالا بسازید، تمام منابع سیستم به طور اختصاصی برای شما در نظر گرفته میشه. شما Kernel سیستم‌عامل کاملا جدا خواهید داشت با فضای رم تضمین شده و کاملا اختصاصی و کلا انگار که سیستم عامل جدا رو ران کردید و همه چیز تقریبا با سیستم عامل واقعی یکی خواهد بود.اما تو داکر قضیه فرق می‌کنه. شما از Kernel سیستم عامل میزبان (Host) به صورت اشتراکی استفاده می‌کنید. اگر از سخت افزاری قراره استفاده بکنید لازمه که باز از سیستم‌عامل میزبان قرض بگیرید. فضای رم و فضای هارد هم به همین صورت. و حتی ظرفیت پردازشگر مرکزی رو.شاید سوال پیش بیاد که این چیش خوبه؟! خوب بنظرتون اگر ما سیستم‌عامل جدا نداشته باشیم و لازم نباشه تمامی Boot Sequence یک سیستم عامل رو انجام بدیم کلی تو زمان و منابع سیستمی صرفه جویی نکردیم؟با استفاده از داکر و روشی که به اصطلاح Containerization گفته میشه شما می‌تونید یک محیط کاملا ایزوله برای کد خودتون داشته باشید بدون دردسرهای ماشین مجازی و مصرف منابعی (رم، هارد، سی پی یو) بسیار کمتر که خیلی راحت و در عرض چند ثانیه میتونید انواع و اقسام Stackهای از پیش آماده رو اجرا و استفاده کنید.برای مثال من نرم افزار تحت سروری نوشتم که به یک محیط توسعه php احتیاج داره و برای دیتابیس هم از PostgreSql استفاده می‌کنه. خیلی راحت میام از دو تا Image پیش ساخته داکر یکی برای php و دیگری برای PostgreSql استفاده می‌کنم و با استفاده از روشی که در ادامه می‌گم این دو تا رو بهم وصل می‌کنم، بدون اینکه نیاز باشه خودم به صورت دستی چیزی رو نصب کرده باشم.یا حتی اگر هیچ کدوم از Image های آماده داکر به دردم نخوره، خیلی راحت با استفاده از یک Dockerfile ایمیج مخصوص به خودم رو می‌سازم و بارها ازش استفاده می‌کنم.مثلا دیگه‌اش رو می‌تونم به این صورت بزنم که من یک برنامه‌نویس بک‌اند هستم و روی یک API دارم کار می‌کنم که قرار به کلاینت‌های Android, iOS , وب سرویس دهی کنه. ما هنوز در مرحله توسعه هستیم و مطمئنا قرار کدها بارها عوض بشن. یک روش کار به این صورت که می‌تونیم کدها رو رو یک سرور مرکزی قرار بدیم و همه کلاینتها برای توسعه به اون ریکوئست بزنن و هر بار هم که تغییری لازم بود من سرور رو آپدیت می‌کنم. حالا اگه این وسط به هر دلیلی، دسترسی به سرور نباشه (از قطعی اینترنت گرفته تا مشکلات شبکه و یا اصلا هزینه بالای نگه‌داری سرور) تکلیف ما چیه؟!اینجاست که من می‌تونم با استفاده از داکر و ساختن ایمیج‌های مناسب با استفاده از Dockerfile و همچنین تعریف سرویس‌ها مورد نیاز و نحوه اتصالشون داخل فایلی به اسم docker-compose.yml یک بک‌اند شبیه سازی شده و کامل رو در اختیار تیم‌های مختلف کلاینت قرار بدم و تنها چیزی که اونا لازم دارن اجرای یک دستور ساده است تا API شما رو به طور کامل روی سیستم خودشون و به صورت لوکال داشته باشن. بنظرتون این روش خیلی خیلی ساده و کارا نیست؟مورد استفاده‌ای دیگه‌ای که می‌تونم مثال بزنم برای تست کردن زبان‌های و استک‌های جدیده. برای مثال من جدیدا به مباحث یادگیری ماشینی (Machine Learning) و یادگیری عمیق (Deep Learning) علاقه مند شدم و دوست دارم خیلی مختصر برای شروع باهاشون کار کنم و دلم نمی‌خواد سیستم‌عاملم رو با ده‌ها ابزاری که باید نصب کنم سنگین و آلوده کنم.اینجا خیلی راحت میام و از یکی از ایمیج‌های از پیش ساخته مثل این یا این یا این استفاده می‌کنم و در عرض چند ثانیه یه محیط کاملا آماده برای شروع به کار دارم. بدون اینکه کوچکترین پکیجی رو روی سیستم‌عامل اصلی خودم نصب کرده باشم.امروزه داکر همه جا داره استفاده می‌شه. از پروژه‌های کوچک و شخصی گرفته تا حتی ناسا! پس به عنوان یه برنامه‌نویس وظیفه همه ماست که در موردش بخونیم و نحوه استفاده اش رو یاد بگیریم. اگر هم که برنامه نویس بک‌اند هستید بنظرم لازمه با ابزارهای دیگه مرتبط مثل Docker Swarm و یا Kubernetes هم آشنا باشید.تو این مطلب سعی به صورت ساده داکر رو معرفی کنم و موارد استفاده مختلفش رو با کمک مثال شرح بدم. توی مطالب بعدی کمی قضیه رو عملی‌تر می‌کنیم و سعی می‌کنیم یه پروژه ساده رو تو داکر پیاده سازی بکنیم.پس حتما اگر سوالی بود بپرسید. اگر هم که این مطلب رو دوست داشتید ? یادتون نره.</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Wed, 29 Aug 2018 22:04:29 +0430</pubDate>
            </item>
                    <item>
                <title>ترفندهای RxJava در اندروید - قسمت اول</title>
                <link>https://virgool.io/Software/%D8%AA%D8%B1%D9%81%D9%86%D8%AF%D9%87%D8%A7%DB%8C-rxjava-%D8%AF%D8%B1-%D8%A7%D9%86%D8%AF%D8%B1%D9%88%DB%8C%D8%AF-%D9%82%D8%B3%D9%85%D8%AA-%D8%A7%D9%88%D9%84-mtvb5tlaeubh</link>
                <description>اسم کتابخانه RxJava 2 رو احتمالا تا حالا زیاد شنیدید و ممکنه حتی ازش استفاده هم بکنید. بسیاری از برنامه‌نویس بدون اینکه درک درستی از مفاهیم جریان‌های داده (Data Stream) داشته باشن و با مدل برنامه نویسی Reactive آشنا باشن به طور مختصری از RxJava در پروژه‌هاشون استفاده می‌کنند.در حالیکه قدرت اصلی RxJava در متودهای عملگر (Operator Methods) اون هست. تو این پست سعی دارم تعدادی از این عملگرها رو با مثال عملی توضیح بدم و نشون بدم که اگر درست از RxJava و اپراتورهاش استفاده کنید چقدر برنامه‌نویسی براتون جذاب‌تر، کدهاتون خواناتر و حالتون بهتر خواهد بود.Reactive Extentions (Rx)یادآوری: تمامی مثال‌های این پست به زبان Kotlin خواهد بود.۱- ترکیب ۲ جریان در یک جریانگاهی اوقات لازم میشه که ما اطلاعاتی رو از دو جریان متفاوت بگیریم. ولی هنگام نمایش باید این ها رو به صورت همزمان و یا ترکیب شده نمایش بدیم.تصور کنید که ما ۲ endpoint در سرور داریم که یکی فهرست پست‌های کاربر و دومی فهرست همه پست‌ها رو بر می‌گردونه. به صورت زیر:@GET(&quot;posts/mine&quot;)
fun getMyPosts(): Single&lt;List&lt;Post&gt;&gt;

@GET(&quot;posts&quot;)
fun getAllPosts(): Single&lt;List&lt;Post&gt;&gt;حالا برای ترکیب این دو تا جریان به صورتی که بعد از اینکه حتما هر دو جواب داشته باشن از از اپراتور  &#x60;zipWith&#x60; استفاده می‌کنیم. متود zipWith رو یک جریان عمل می‌کنه و به عنوان ورودی جریان دوم و تابعی رو دریافت می‌کنه بهش می‌گه چجوری دو تا جریان رو ترکیب کنه.api.getAllPosts()
        .zipWith(api.getMyPosts(), BiFunction&lt;List&lt;Post&gt;, List&lt;Post&gt;, List&lt;Post&gt;&gt; { t1, t2 -&gt;
            mutableListOf&lt;Post&gt;().apply {
                addAll(t1)
                addAll(t2)
            }
        })
        .subscribe({
            // We now have all the posts as a single result
        }, {
            // log error just in case
        })۲- کنترل سرعت ارسال دادهمطمئنا پیش اومده که لازم بوده بر اساس یکی از رویدادهای مربوط به کاربر مثلا کلیک یا تایپ بخواید عملیاتی رو انجام بدید. برای مثال گاهی لازمه بر اساس حروفی که کاربر در یک فیلد تایپ می‌کنه به صورت لحظه‌ای درخواست‌هایی برای سرور بک‌اند شما ارسال بشه. در این مثال اگر کاربر خیلی سریع عملیات تایپ رو انجام بده ممکنه در کمتر از ثانیه تعداد زیادی درخواست به سمت سرور شما ارسال بشه که در تعداد کاربر بالا مسلما باعث فشار بیش از اندازه به سرور میشه.حالا برای اینکه بتونیم این مشکل رو برطرف کنیم باید مثلا طوری پیاده سازی انجام بشه که فقط زمانی که از آخرین تایپ کاربر ۵۰۰ میلی‌ثانیه گذشت درخواست ارسال بشه.در RxJava به راحتی با استفاده از اپراتور debounce می‌تونید این کار رو انجام بدید.typingObservable.debounce(500, TimeUnit.MILLISECONDS)
.subscribe { 
    // 500 miliseconds is passed
}۳- چطور جریان مخصوص خودمون رو درست کنیمحالا شاید براتون سوال باشه که ما چطور میتونیم جریان (Observable) مخصوص خودمون رو درست کنیم. در اکثر موارد شما به اینکار نیاز پیدا نمی‌کنید و معمولا از observable هایی که به روشهای دیگه به دستتون رسیده استفاده می‌کنید ولی گاهی اوقات لازمه شما هم یک observable  مخصوص خودتون داشته باشید.برای مثال من زمانی که می‌خوام کار سنگینی رو روی thread پشت زمینه انجام بدم یک observable اختصاصی درست می‌کنم.به این صورت:Flowable.create&lt;String&gt;({ e -&gt;
    // some heavy and long running operation
    // run on background thread
}, BackpressureStrategy.DROP)
    .subscribeOn(Schedulers.io())
    .observeOn(AndroidSchedulers.mainThread())
     .subscribe {
            // We are now on Main Thread
            // Do UI stuff
        }دقت کنید که در تکه کد بالا به استفاده از متود subscribeOn(Schedulers.io()) انجام کار رو روی thread پس زمینه انجام دادیم و با استفاده از observeOn(AndroidSchedulers.mainThread()) نتایجش رو در ترد اصلی دریافت کردیم. ۴- میانبر subscribeOn و observeOnبطور کلی خیلی پیش میاد که شما تو استفاده از RxJava بخواهید کاری رو در thread پس زمینه انجام بدید و نتیجش رو در ترد اصلی داشته باشید. و معمولا کدتون پر میشه از زنجیره زیر:.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())حالا برای اینکه ما از تکرار و ازدیاد دوری کنیم خیلی راحت می‌تونیم از یه قابلیت عالی زبان Kotlin استفاده کنیم به اسم Extentions به این صورت که تابعی به صورت زیر تعریف می‌کنیم.fun &lt;T&gt; Single&lt;T&gt;.iomain(): Single&lt;T&gt; = this.compose {
    it.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
}حالا فقط کافیه همیشه به جای .subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())از .iomain()استفاده کنیم. به این صورت:api.getAllPosts()
        .iomain()
        .subscribe({
            // We now have all the posts as a single result
        }, {
            // log error just in case
        })تمام کدهایی که در این پست به کار رفته از طریق این گیتهاب در دسترسه. منتظر قسمت‌های بعدی این پست باشید و اگر فکر می‌کنید نکته جالبی رو بلدید که دوست دارید بقیه هم بدونن حتما تو بلاگ خودتون بنویسید یا به من بگید بنویسم.</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Sun, 22 Jul 2018 17:41:04 +0430</pubDate>
            </item>
                    <item>
                <title>مورد عجیب GoLang و RabbitMQ</title>
                <link>https://virgool.io/golangpub/%D9%85%D9%88%D8%B1%D8%AF-%D8%B9%D8%AC%DB%8C%D8%A8-golang-%D9%88-rabbitmq-zq4juldrkx8a</link>
                <description>امروز که مثل چند روز گذشته داشتم روی کد سرور چت آریو کار می‌کردم به مورد عجیبی خوردم که تا دیروز توی کد وجود نداشت.ابتدا توضیح مختصری در مورد نحوه کار سرور چت آریو می‌گم که بیشتر موضوع رو درک کنید. ما برای اینکه بتونیم تراکنش‌های بالای چند هزار مسیج در ثانیه رو به اصطلاح هندل کنیم از سیستم RabbitMQ در کنار چندتا تکنولوژی دیگه استفاده می‌کنیم. همچنین در نسخه جدید هم تصمیم بر این شد که از زبان Golang استفاده کنیم. همچنین برای ارتباط بین Go و RabbitMQ از این کلاینت AMQP استفاده می‌کنیم.و اما مشکلی که ابتدا بهش اشاره کردم این بود که حین کار سرور رو زیر بار گذاشته بودم برای تست متوجه میشدم که مثلا مسیج چند هزارم به بعد کانالی که با استفاده از اون مسیج رو به صف می‌فرستادم ناگهان بسته میشه. با بررسی لاگها به مشکل زیر رسیدم:Server closed connection: UNEXPECTED_FRAME - expected content body, got non content body frame instead, code=505, class_id=60, method_id=40و اما مشکل کار چی بود؟ نکته ساده‌ای وجود داشت که هرکسی که با RabbitMQ کار می‌کنه خوبه که بهش آگاه باشه اینه که همه channel هایی که برای ارسال یا دریافت مسیج به صف استفاده می‌شن بهتره که به صورت یک طرفه استفاده بشن. یعنی اینکه هر کدوم فقط برای ارسال یا فقط برای دریافت در نظر گرفته بشن. نکته مهم دیگری که اینجا اتفاق میوفتاد امکان رخ دادن به اصطلاح Race Condition زمانی بود که می‌خواستم توی مثلا ۲ تا goroutine مسیجی رو ارسال کنم که با پیغام خطای بالا کانال ارتباط بسته می‌شد و سرور کرش می‌کرد.راه حل هم خیلی ساده این بود که برای هر Goroutine یک channel اختصاصی ایجاد بشه و ارسال و دریافت از طریق اون انجام بشه.</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Sat, 26 May 2018 20:47:12 +0430</pubDate>
            </item>
                    <item>
                <title>چگونه در یک مصاحبه استخدامی خوب ظاهر شویم؟</title>
                <link>https://virgool.io/@2hamed/%DA%86%DA%AF%D9%88%D9%86%D9%87-%D8%AF%D8%B1-%DB%8C%DA%A9-%D9%85%D8%B5%D8%A7%D8%AD%D8%A8%D9%87-%D8%A7%D8%B3%D8%AA%D8%AE%D8%AF%D8%A7%D9%85%DB%8C-%D8%AE%D9%88%D8%A8-%D8%B8%D8%A7%D9%87%D8%B1-%D8%B4%D9%88%DB%8C%D9%85-bsdu6qkrbwqh</link>
                <description>در این نزدیک به ۱۰ سالی که از عمر حرفه‌ای من می‌گذره در تعدادی زیادی مصاحبه استخدامی شرکت کردم. با تجربه‌ای که از مدیریت فنی یکی دو تا شرکت دارم، علاوه بر حضور در تعداد زیادی مصاحبه به عنوان مصاحبه شونده یا کارجو، دفعات متعددی هم به عنوان مصاحبه کننده، با افراد زیادی مصاحبه انجام دادم.حالا سعی دارم در چند مورد، مهمترین نکاتی که با رعایت اون‌ها می‌تونید یک مصاحبه کاری موفق رو پشت سر بگذارید، به طور مختصر شرح بدم.چطور یک مصاحبه استخدامی موفق داشته باشیم؟۱. مقید به زمان باشید; یا به قول خودمون آن‌تایم باشیداولین و مهم‌ترین مورد تعهد شما به زمان است. همیشه و همیشه سعی کنید سر وقتی که برای شما مشخص شده در مصاحبه حضور پیدا کنید. حتما مسافتی که باید برید رو تخمین بزنید و عواملی مثل ترافیک رو هم در نظر بگیرید که بتونید سر ساعت مقرر در محل حضور پیدا کنید. اخلاق حرفه‌ای خودتون رو در قدم اول با زمان ثابت کنید.۲. آراسته باشید; شلخته نرید سر جلسه مصاحبه!همیشه و همه جا گفتن ظاهر یک شخص اولین معرف شخصت اونه. سعی کنید از تیپ‌های نامتفعارف پرهیز کنید. لباس و کفش تمیز می‌تونه تأثیر مثبت فراوانی رو شخص مقابل شما بگذاره. گرفتن یک دوش کوتاه قبل از مصاحبه هم شما رو سر حال میاره و هم باعث میشه که بوی عرق باعث آزار مصاحبه کننده نشه.از قدیم گفتن، از کوزه همان برون تراورد که در اوست.۳. خوش اخلاق باشیدخوش‌اخلاق و خوشرو بودن باعث میشه که مصاحبه کننده نسبت به شما حس بهتری داشته باشه. بهتره از همون ابتدای ورود به شرکت، با لبخند وارد بشید. خودتون رو معرفی کنید. سعی کنید به تمامی پرسنل شرکت که باهاشون برخورد می‌کنید احترام بگذارید، حتی نیروهای خدماتی. مطمئن باشید اخلاق خوب داشتن به ضرر شما نخواهد بود.۴. مشتاق باشیدبهتره قبل از اینکه در مصاحبه حضور پیدا کنید، در مورد شرکت و محصولاتش تحقیق مختصری بکنید و اشتیاق خودتون رو برای حضور در شرکت به عنوان یک عضو نشون بدید. خیلی از کارفرماها براشون مهمه که کسی که برای استخدام میاد حتما با برند و محصولات شرکت آشنا باشه.۵. آمادگی قبلی داشته باشیدتقریبا همه مصاحبه گرها از شما می‌خوان که به صورت مختصر از سابقه کاری و تحصیلات و گذشته‌تون تعریف کنید. اگر قبل از مصاحبه چیزی که می‌خواید بگید رو آماده کنید و حداقل یکی دوبار اون رو توی ذهنتون تعریف کنید می‌تونید بهترین توصیف رو از خودتون داشته باشید.چیز دیگری که ممکنه ازتون بپرسن، اینه که تا حالا کاری کردید که بهش افتخار کنید؟ جواب این سوال معمولا برای اکثر افراد سخت و حتی شاید ناممکن باشه. گذشته‌تون رو مرور کنید. مطمئنم بالاخره چیزی پیدا میشه که از انجامش احساس شور و شعف کرده باشید. همون رو بهش اشاره کنید.۶. صادق باشیدهیچ‌کس نمی‌تونه ادعا کنه که همه چیز رو بلده. پس از اینکه به بلد نبودن چیزی اعتراف کنید،‌نترسید. اینکه خیلی ساده بگید نمی‌دونم، خیلی بهتر از اینه که یه سری داستان نامربوط سرهم کنید و تحویل بدید. باور کنید اکثر افرادی که از شما می‌پرسن خودشون احتمالا اطلاعات مختصری دارن و متوجه می‌شن که شما چیزی بلد نیستید.۷. دندون گرد نباشیدخیلی اوقات پیش اومده که شخصی که قرار بوده برای مصاحبه بیاد با شرکت تماس گرفته و اعلام کرده که اگر از فلان قیمت بیشتر میدید من بیام!من، بدون برو و برگرد، حتی اگه شرکت توان پرداخت این مبلغ و بالاتر ازون رو هم داشته باشه،‌چنین شخصی رو رد می‌کنم.این‌ها نکاتی بود که فکر می‌کنم هر کسی که دنبال کار می‌گرده یا مایله که در شرکت‌های بهتر و بزرگتری کار کنه حتما بهشون نیاز پیدا می‌کنه.شما فکر می‌کنید مورد دیگری بشه موارد بالا اضافه کرد؟ نظر خودتون رو در کامنت‌ها با بقیه به اشتراک بگذارید.اگر هم این مطلب رو دوست داشید با ❤️ کردن مشوق مطالب بعدی باشید. :)</description>
                <category>حامد مومنی</category>
                <author>حامد مومنی</author>
                <pubDate>Wed, 11 Apr 2018 15:16:18 +0430</pubDate>
            </item>
            </channel>
</rss>