<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های مهدی قوسیان | Mahdi Gosyan</title>
        <link>https://virgool.io/feed/@mahdigosyan</link>
        <description>برنامه‌نویس از پشت با آچار تو دست و کتاب رو میز</description>
        <language>fa</language>
        <pubDate>2026-06-16 07:44:46</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/595957/avatar/yClh4L.jpg?height=120&amp;width=120</url>
            <title>مهدی قوسیان | Mahdi Gosyan</title>
            <link>https://virgool.io/@mahdigosyan</link>
        </image>

                    <item>
                <title>راهنمای کامل Apache Kafka: از معماری تا بهترین شیوه‌ها</title>
                <link>https://virgool.io/@mahdigosyan/%D8%B1%D8%A7%D9%87%D9%86%D9%85%D8%A7%DB%8C-%DA%A9%D8%A7%D9%85%D9%84-apache-kafka-%D8%A7%D8%B2-%D9%85%D8%B9%D9%85%D8%A7%D8%B1%DB%8C-%D8%AA%D8%A7-%D8%A8%D9%87%D8%AA%D8%B1%DB%8C%D9%86-%D8%B4%DB%8C%D9%88%D9%87-%D9%87%D8%A7-ogsrhlkvzlha</link>
                <description>Apache Kafka یک پلتفرم جریانی توزیع‌شده (Distributed Streaming Platform) است که برای ساخت پایپ‌لاین‌های داده، پردازش رویدادها و پیام‌رسانی مقاوم در برابر خطا در مقیاس بزرگ طراحی شده است. این سیستم قادر به پردازش میلیون‌ها پیام در ثانیه است و به یکی از اجزای اصلی معماری‌های داده‌محور و رویدادمحور مدرن تبدیل شده است.در این مقاله نگاهی ساختاریافته به مفاهیم اصلی، معماری داخلی، چالش‌های رایج و نکات کلیدی برای شروع استفاده از Kafka در محیط تولید خواهیم داشت.. Apache Kafka چیست؟Kafka یک سامانه پیام‌رسان توزیع‌شده با الگوی انتشار/اشتراک (Publish/Subscribe) است که برای داده‌های جریانی لحظه‌ای بهینه‌سازی شده است.پیام‌ها در Topic‌ها ذخیره می‌شوند؛ Producer آن‌ها را تولید می‌کند و Consumer آن‌ها را مصرف می‌نماید. برخلاف صف‌های سنتی، Kafka پیام‌ها را بر اساس سیاست نگهداری مبتنی بر زمان (Retention) حفظ می‌کند و بلافاصله پس از مصرف حذف نمی‌کند.مهم‌ترین کاربردهای Kafka شامل:تحلیل لحظه‌ای داده‌هامعماری مایکروسرویس رویدادمحورجمع‌آوری و پردازش لاگ‌هاپایپ‌لاین‌های ETL برای انبار داده. معماری KafkaBroker – هر سرور Kafka یک Broker است. هر خوشه شامل چند Broker بوده که داده‌ها را ذخیره و سرویس‌دهی می‌کنند.Topic و Partition – پیام‌ها در Topic‌ها دسته‌بندی می‌شوند و هر Topic به چند Partition تقسیم می‌شود تا پردازش موازی انجام گیرد.Producer – فرستنده پیام به Kafka.Consumer – دریافت‌کننده پیام از Kafka.Consumer Group – گروهی از مصرف‌کنندگان که بار پردازش پیام‌ها را بین خود تقسیم می‌کنند.Zookeeper/KRaft – مدیریت متادیتا و هماهنگ‌سازی خوشه؛ نسخه‌های جدید Kafka امکان استفاده از KRaft بدون Zookeeper را فراهم کرده‌اند.. مزایاکارایی بالا – پردازش میلیون‌ها پیام در ثانیه.مقیاس‌پذیری افقی – افزودن Broker برای افزایش ظرفیت.تحمل‌پذیری خطا – تکرار داده‌ها برای جلوگیری از از دست رفتن.جداسازی سرویس‌ها – استقلال کامل Producer و Consumer.. چالش‌هاپیچیدگی پیکربندی – تنظیمات اشتباه Retention یا Partition می‌تواند مشکل‌ساز شود.مدیریت خوشه – نیازمند تجربه عملی است.لزوم مانیتورینگ – بدون نظارت بر متریک‌ها، مشکلات به سرعت حاد می‌شوند.. مثال عملی: مشکل Retentionدر یک پروژه جمع‌آوری لاگ، تنظیمات پیش‌فرض Retention باعث شد تا حجم Topicها طی چند ساعت فضای دیسک را اشباع کند. این تجربه نشان داد که تنظیمات پیش‌فرض Kafka همیشه متناسب با محیط عملیاتی نیستند.. سه نکته کلیدی برای شروع۱. تنظیم Retention مناسباگر داده کوتاه‌عمر است، زمان نگهداری را کاهش دهید:log.retention.hours=24۲. استفاده درست از Consumer Groupاین ساختار مانع پردازش تکراری پیام‌ها و موجب تقسیم بار می‌شود.۳. شروع مانیتورینگ از روز اولبا Prometheus و Grafana یا Confluent Control Center، شاخص‌هایی مانند Consumer Lag، مصرف دیسک و ترافیک شبکه را زیر نظر بگیرید.۸. جمع‌بندیKafka یک پلتفرم قدرتمند برای ارتباطات بلادرنگ، مقاوم و مقیاس‌پذیر است؛ اما استفاده بهینه از آن نیازمند شناخت عمیق معماری، پیکربندی درست و مانیتورینگ فعال از روز اول است.</description>
                <category>مهدی قوسیان | Mahdi Gosyan</category>
                <author>مهدی قوسیان | Mahdi Gosyan</author>
                <pubDate>Mon, 11 Aug 2025 13:39:03 +0330</pubDate>
            </item>
                    <item>
                <title>ردیس؛ قهرمان پرحاشیه پروژه‌های نرم‌افزاری!</title>
                <link>https://virgool.io/@mahdigosyan/%D8%B1%D8%AF%DB%8C%D8%B3-%D9%82%D9%87%D8%B1%D9%85%D8%A7%D9%86-%D9%BE%D8%B1%D8%AD%D8%A7%D8%B4%DB%8C%D9%87-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D9%87%D8%A7%DB%8C-%D9%86%D8%B1%D9%85-%D8%A7%D9%81%D8%B2%D8%A7%D8%B1%DB%8C-sgqxtoxstaih</link>
                <description>ردیس: عشق اول همه بک‌اندکارهااگه تو دنیای نرم‌افزار کار بک‌اند کرده باشی، بعید می‌دونم اسم «ردیس» به گوشت نخورده باشه.برنامه‌نویس‌ها وقتی اسم ردیس رو می‌شنون، برق خاصی تو چشماشون می‌زنه. انگار تو ذهنشون این جمله می‌چرخه:«با ردیس هر کاری میشه کرد! کش؟ Session Store؟ صف؟ Pub/Sub؟ همه چی!»ولی یک نکته‌ی طلایی این وسط هست؛در دنیای واقعی، ردیس فقط سریع و خفن نیست، کلی دام و چاله هم داره که اگه حواست نباشه، پروژه رو به فنا می‌ده! ردیس یعنی چی دقیقاً؟یه دیتااستور خیلی سریع که همه‌چی رو تو RAM نگه می‌داره.ساختار داده‌هایی مثل String، List، Set، Hash، حتی Stream رو ساپورت می‌کنه.مناسب برای کش (cache)، نگهداری session، لیدربوردهای سریع و کارهای real-time مثل نوتیفیکیشن.یعنی؟مثلاً تو سایت فروشگاهی، می‌خوای نتایج سرچ رو سریع نشون بدی؟یا می‌خوای session کاربر رو برای چند دقیقه تو حافظه نگه داری؟جواب راحت‌ترین راه: ردیس! چاله‌های ردیس؛‌ قصه‌هایی که کمتر کسی تعریف می‌کنهزندگی فقط در لحظه!هرچی توی ردیس ذخیره کنی توی RAM می‌مونه؛ پس اگه حجم دیتا یا تعداد یوزرت زیاد بشه، به سرعت رم سرور پر می‌شه.پایداری = چالش!ردیس خودش یه جورایی “بانک اطلاعاتی” نیست! دو نوع پایداری داره (RDB و AOF) ولی هیچ‌کدوم تضمین نمی‌کنه دیتای مهمت همیشه باقی بمونه.همه چیز روی دوش یک ترد!ردیس ذاتاً تک‌ترد هست؛ اگه ترافیک یا عملیات خیلی سنگین باشه، همه چی قفل می‌کنه!امنیت بی‌خیال!اگر باب میل کانفیگش نکنی، ممکنه کل دنیا به ردیس تو دسترسی داشته باشن. پورت 6379 خداحافظی کن با امنیت…استفاده اشتباه = فاجعه!ملیون‌ها بار دیدم که برنامه‌نویس‌ها، دیتاهای اساسی و مهم بیزینس رو تو ردیس می‌ذارن! «چون سریع‌تره…»بعد که همه چی می‌پره، دکمه panic رو می‌زنن! یه خاطره واقعی از پروژه‌های ایرانیتو یه پروژه فروشگاه، همه‌ی سبد خرید کاربرها رو بدون expire-time تو ردیس ذخیره کردیم.اولش همه چی اوکی!مث قصه‌های بیستون و فرهاد…تا وقتی که یه روز سر یه کمپین شلوغ، رم سرور پر شد. ردیس بی‌رحمانه شروع کرد سبد خریدهای قدیمی رو پاک کردن!چند تا مشتری خاص کلی داد زدند «چرا همه چی پرید؟!»روز بد من و تیممون بود؛ ولی بعدش دیگه یاد گرفتیم همیشه TTL بذاریم، همیشه دیتای مهم رو دوباره تو دیتابیس بفرستیم! توصیه‌های بقا با ردیسTTL (زمان انقضا) برای هر دیتای غیرضروری بذار!حواست به memory usage و eviction policy باشههیچ‌وقت ردیس رو بدون پسورد و روی شبکه عمومی لخت نذاربه پایداریش اطمینان نکن برای دیتای حساس (فقط کش، نه دیتابیس اصلی)مانیتور کن؛ alert بذار روی حافظهساختار داده رو بشناس و استفاده درست کنجمع‌بندیردیس اگه درست استفاده شه، گل‌سرسبد سیستم‌های پرسرعته؛ولی اگه باهاش قمار کنی و بی‌گدار به آب بزنی، می‌تونه قشنگ حال پروژه‌ات رو بگیره!پس عاشقش باش، ولی هوشمندانه استفاده کن.</description>
                <category>مهدی قوسیان | Mahdi Gosyan</category>
                <author>مهدی قوسیان | Mahdi Gosyan</author>
                <pubDate>Tue, 05 Aug 2025 01:45:09 +0330</pubDate>
            </item>
                    <item>
                <title>سه ترفند داکری که کاش قبل اولین پروژه بلد بودم</title>
                <link>https://virgool.io/@mahdigosyan/%D8%B3%D9%87-%D8%AA%D8%B1%D9%81%D9%86%D8%AF-%D8%AF%D8%A7%DA%A9%D8%B1%DB%8C-%DA%A9%D9%87-%DA%A9%D8%A7%D8%B4-%D9%82%D8%A8%D9%84-%D8%A7%D9%88%D9%84%DB%8C%D9%86-%D9%BE%D8%B1%D9%88%DA%98%D9%87-%D8%A8%D9%84%D8%AF-%D8%A8%D9%88%D8%AF%D9%85-dnpuaiama5uf</link>
                <description>رفقا… هیچ وقت یادم نمیره اولین باری که اسم داکر رو شنیدم. فک می‌کردم مثله یه ژنراتوره که پروژه رو برق میده! اما واقعیت اینه که داکر بیشتر شبیه سرایدار باحالِ ساختمونی‌ـه که هیچی رو گم نمی‌کنه—اما اگه اشتباه بگی، با خاک یکسانت می‌کنه!بذار راحتت کنم. اگه تا حالا اسباب‌کشی کردی، حتماً می‌دونی بسته‌بندی درست یعنی چی. داکر دقیقاً همینه: پروژه‌تو با تمام نیازمندی‌هاش تو یه جعبه‌ (کانتینر) می‌چینه، هر جا بردیش جواب میده. کلیشه‌ی معروف «بابا روی سیستم من که کار می‌کنه» رو، خود به خود میزنه تو صورتت و میگه: «کار میکنه چون کانتینره همه جا همونه!»اولین بار که یه پروژه Node رو داخل داکر آوردم بالا، اعتماد به نفس زیاد داشتم—ولی یادم رفت پورت کانتینر رو درست map کنم! نیم ساعت با خودم کلنجار رفتم که چرا سایت بالا نمیاد. آخرش فهمیدم: -p 8080:3000 رو اشتباه نوشتم! نقطه شروع همه دردسرها هم معمولاً همینه…سه ترفند کاربردی داکری (که کاش همون روز اول می‌دونستم!)همیشه پورت رو درست map کن!یعنی مثلاً:docker run -p 8080:3000 my-appهر وقت اشتباه بزنی، سایت بالا نمیاد و تو هم قاطی می‌کنی که باگ کجاست؟!۲-داده‌ها رو هیچ‌وقت تو خود کانتینر ذخیره نکن!Volume رو جدی بگیر:docker run -v /my/data:/app/data my-appیه روز یهو کل دیتاتو از دست میدی. خودم روز اولی فایل لاگ پروژه رو اینطوری گم کردم!۳-دیسکت رو تمیز نگه دار!کانتینرهایی که تموم شدن و ایمیج‌های اضافی رو با این دستورات پاک کن:docker ps -a
docker system prune -f
docker system prune -a --volumesاشتباهات رایج (برادرانه! 😅)اشتباه map کردن پورت (همون مثال بالا)نگرفتن Volume (و دعوای همیشگی با بخش دیتا)نگه داشتن کانتینر و ایمیج‌های اضافی (و حرکت رو به بازار آزاد SSD!)داکر رفیقیه که اگه قلقش رو یاد بگیری، سنگ صبوره پروژه‌ته. اما یار بد موقع هم هست، اگه بدون شناخت بری سمتش! سوال داشتی یا خاطره خنده‌داری از اولین بار کار با داکر داری، این پایین کامنت بده که دور هم بخندیم! دم همه‌تون گرم!#داکر #برنامه‌نویسی #بک‌اند #تجربه_شخصی #کافه_کد #Docker #Backend #توسعه‌دهنده</description>
                <category>مهدی قوسیان | Mahdi Gosyan</category>
                <author>مهدی قوسیان | Mahdi Gosyan</author>
                <pubDate>Sun, 03 Aug 2025 02:27:48 +0330</pubDate>
            </item>
                    <item>
                <title>مایکروسرویس چیه؟ به زبون خودمونی(:</title>
                <link>https://virgool.io/@mahdigosyan/micro-o7tmdwhchv0w</link>
                <description>تا حالا برات پیش اومده بشینی سر یه پروژه و احساس کنی هر تیکه‌اش به یه تیکه‌ی دیگه بند شده؟ درست مثل آش رشته مامان‌بزرگ که اگه بخوای فقط لوبیاشو دربیاری، کل رشته‌ها باهاش میاد بالا!این دقیقاً همون وضعیتیه که بهش میگن “Monolith”. همه‌چی تو یه ظرف، همه اعصاب‌خردکن اما آسون واسه شروع.حالا بیایم سمت مایکروسرویس؛ جوری فکر کن انگار قراره ساندویچ بسازی. نون جدا، پنیر جدا، کاهو و گوجه سر جاشون… هر کدوم اگه خراب شه، ساندویچ رو دور نمیندازی! فقط همون تیکه‌اش رو عوض می‌کنی.تعریف خیلی خودمونیمایکروسرویس یعنی هر بخش از برنامه‌ت یه اپ کوچیک و مستقل باشه. مثلاً قسمت ثبت‌نام، سفارش، و گزارش هرکدوم جداگونه و بی‌دردسر کار خودشون رو می‌کنن و اگه قرار شد آخر هفته یکی‌شون رو تعویض یا ارتقا بدی، کل اپ نمی‌تَره.فرقش با مونولیت چیه؟تو Монولیت، یه جای کدت مشکل داشته باشه، کل سیستم رُ داغون می‌کنی.تو Microservice خراب شد؟! فقط همون تیکه پایین میاد، بقیه رو هوا می‌مونه.چرا همه جوگیر مایکروسرویس شدن؟هر تیم می‌تونه رو یه سرویس کار کنه، بی دردسر دخالت بقیه.فقط اون سرویسی که لازمه رو میشه قوی‌تر کرد (مثلاً سرویس سفارشای یه فروشگاه، نه همه چی!)راحت‌تر میشه دیپلوی و نسخه جدید داد.اما واقعیتش…دیباگ‌کردنش حقیقتاً آتیشیه! (همیشه یه جایی یکی “یادم رفت” داره)اگر بلد نباشی، فقط خودتو سر کار گذاشتی.حواست به شبکه و لاگ گرفتن باید باشه وگرنه یه ارورِ کوچیک کار همه‌رو تعطیل می‌کنه!یه خاطره واقعی:اولین بار که پروژه‌مون رو مایکروسرویسی کردیم، سرویس ثبت‌نام جدا شد. فرداش سرور لاگین ترکید! همه چی ارور Timeout… آخرش فهمیدیم کل داستان سر یه کانفیگ ناقص شبکه بود.خلاصه: همیشه دو بار تنظیماتتو چک کن و بیخود جوگیر نشو!حرف آخرسه توصیه قبل رفتن سراغ Microservice:از همون اول نرو سروقتش، با بزرگ‌شدن پروژه شروع کن به جداکردن سرویسا.هر سرویس باید واقعا مستقل باشه، نه اسماً!همیشه لاگ و مانیتورینگ دقیق بذار (این رفیقات یهویی غیب میشن!)سوال داشتی یا تجربه خفنی داشتی کامنت بذار، دمت گرم!#برنامه_نویسی #توسعه_دهنده #مایکروسرویس #معماری_نرم_افزار #مهندسی_نرم_افزار #فناوری #تجربه_برنامه_نویس #توسعه_بک_اند #Nodejs #backend #Microservice #خاطرات_برنامه_نویسی #نکته_برنامه_نویسی #ویرگول #برنامه_نویسی_مدرن</description>
                <category>مهدی قوسیان | Mahdi Gosyan</category>
                <author>مهدی قوسیان | Mahdi Gosyan</author>
                <pubDate>Sat, 02 Aug 2025 01:47:25 +0330</pubDate>
            </item>
                    <item>
                <title>سه نکته ساده برای بهبود کد های laravel شما</title>
                <link>https://virgool.io/@mahdigosyan/%D8%B3%D9%87-%D9%86%DA%A9%D8%AA%D9%87-%D8%B3%D8%A7%D8%AF%D9%87-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A8%D9%87%D8%A8%D9%88%D8%AF-%DA%A9%D8%AF-%D9%87%D8%A7%DB%8C-laravel-%D8%B4%D9%85%D8%A7-yfat8yacfovb</link>
                <description>۱. کالکشن‌های خود را ریفکتور کنیدتصور کنید که در حال ایجاد وبسایتی هستید که دانش‌آموزان یا دانشجویان در پروژه‌های آن شرکت می‌کنند و هر هفته به آن‌ها نمره داده می‌شود، و وظیفه شما این است که میانگین نمرات یک پروژه‌ را به مربی(استاد،معلم) نشان دهید، و میانگین نمره دانش‌جویان را به ترتیب درجه‌بندی کنید ( به منظور مشاهده پیشرفت آن‌ها).ممکن است شما با یک Project class مثل این رو‌به رو شوید :}&lt;?phpclass Project extends Model{/** ... code omitted for brevity **/public function studentsAverageScore() {$participants = $this-&gt;participants;$sum = 0;$totalStudents = 0;foreach($participants as $participant) {if ($participant-&gt;isStudent()) {$totalStudents++;$sum += $participant-&gt;student-&gt;lastRating()-&gt;averageScore();}}return $sum / $totalStudents;}به نظر می‌رسد که متد studentsAverageScore() ما بسیار خوب کار می‌کند. با استفاده از یک foreach می‌بینیم که شرکت کنندگان جز دانشجویان هستند یا نه ( برخی از شرکت‌کنندگان می‌توانند از بین استادان باشند) و سپس آخرین میانگین نمره را جمع می‌زنیم(میانگین هر تستی در یک ریت مشخص شده است.)مسأله اینجاست که اگر یک نفر بعدا به این متد برای باگ فیکس یا یک تغییر ضروری برگردد، هم تیمی یا حتی خود شما باید قبل از انجام هرکار دیگری در ذهن خود این foreach را کامپایل کند. حلقه‌ها generic هستند، و در این مورد، ما در هر pass چندین کار انجام می‌دهیم: بررسی می‌کنیم که دانشجو هستند یا نه و سپس به sum اضافه می‌کنیم و فقط دوباره در return statement مقدار می‌دهیم.البته این فقط یک نمونه ساده است، اما تصور کنید که بخواهیم کار بیشتری انجام دهیم؟ اگر بخواهیم این را فقط برای بعضی از دانشجویان فیلتر کنیم یا چیزی به آن‌ها اضافه کنیم چه؟ شاید همه‌ی امتیازهای آن‌ها را بخواهیم نه فقط آخرین آن‌ را ؟ این کارها به سرعت از دست من و شما خارج می‌شود.بنابراین چگونه می‌توانیم این بررسی‌ها و محاسبات را بهتر کنیم؟ خوشبختانه ما می‌توانیم با متدهایی که Eloquent در اختیار ما می‌گذارد، کمی از برنامه‌نویسی فانکشال استفاده کنیم.به جای اینکه به صورت دستی چک کنید که شرکت‌کنندگان دانشجو هستند یا نه، می‌توانید با استفاده از متد filter فقط دانشجویان را return کنید :}&lt;?phppublic function studentsAverageScore() {$participants = $this-&gt;participants;$participants-&gt;filter(function ($participant) {return $participant-&gt;isStudent();});با استفاده از فانکشن filter، ما می‌توانیم فقط یک فانکشن را به عنوان یک آرگومان pass کنیم تا فقط شرکت‌کنندگانی که دارای تمام شروط ما هستند return شوند. در این حالت، این call یک زیرمجموعه از $participants را برخواهد گرداند: فقط دانش‌جویان را.به طور طبیعی، ما نیاز داریم که با حساب کردن میانگین نمره آن‌ها این کار را به پایان برسانیم. خب حالا به foreach نیاز داریم؟ این که هنوز هم بهینه نیست. یک راه حل داخلی یا built-in در فانکش دیگری وجود دارد، که average (میانگین)نام دارد و در کالکشن Eloquent ما وجود دارد؛ در جایی که ما فقط می‌خواهیم مقداری را از کل کالکشن میانگین بگیریم و return کنیم  کمی شبیه به filter را رفتار می‌کند و به عبارت دیگر قوانینی که filter دنبال می‌کند را دنبال خواهد کرد. کد نهایی به صورت زیر است :}&lt;?phppublic function studentsAverageScore() {$participants = $this-&gt;participants;return $participants-&gt;filter(function ($participant) {return $participant-&gt;isStudent();})-&gt;average(function ($participant) {return $participant-&gt;student-&gt;lastRating()-&gt;averageScore();});از آنجایی که  average یک عدد را برمی‌گرداند، پس دقیقاً همان چیزی است که ما می‌خواهیم. توجه کنید که چگونه call های خود را زنجیروار کرده‌ایم و چقدر کد بهتری داریم. تقریباً می‌توانید آن را مثل یک زبان طبیعی بخوانید : شرکت ‌کنندگانی را که دانشجو هستند را بگیر، و سپس مقدار میانگین آخرین نمره‌ آن‌ها را return کن. هدف ما از این کار این است که کدی تمیزتر و مفهومی‌تر داشته باشیم.این کار نه تنها برای php یا Eloquent صدق می‌کند، بلکه می‌توانید کارهای مشابه این را با جاوااسکریپت نیز انجام دهید. گرچه که این از محدوده‌ی مقاله‌ی ما خارج است اما اگر تا بحال در مورد filter ،map و reduce در جاوااسکریپت نشنیده‌اید، آن‌ها را بررسی کنید.۲.بدانید و آگاه باشید که مشکلی مثل N+۱ کوئری وجود دارد!خب بیایید بعضی از نکاتی را که در مورد کد خود در بالا گفتیم را انجام دهیم. توجه داشته باشید که چگونه Student model را برای یک شرکت‌کننده مشخص در فانکشن average فچ کردیم. این مسأله بسیار مشکل‌ساز است چراکه ما همزمان چندین student models را لود می‌کنیم و یک sql کوئری اضافه (در پشت صحنه) انجام می‌گیرد.راه‌حل بهتر برای این کار این است که برای اولین کوئری خود eager load را انجام دهیم. هنگامی که این‌ کار را انجام می‌دهیم، می‌توانیم به جای داشتن کوئری‌های N+۱ ، این تعداد را به مقدار قابل توجهی کاهش دهیم ( پس از نام این مشکل بترسید).کار ساده‌ای است که این را با eloquent و با متد with انجام دهیم. بیایید کد بالا را دوباره ریفکتور کنیم :}&lt;?phppublic function studentsAverageScore() {$participants = $this-&gt;participants()-&gt;with(&#039;student&#039;)-&gt;get();return $participants-&gt;filter(function ($participant) {return $participant-&gt;isStudent();})-&gt;average(function ($participant) {return $participant-&gt;student-&gt;lastRating()-&gt;averageScore();});خب، هر زمان که ما $participant→student را فراخوانی میکنیم، student model مربوط به شرکت‌‌کننده هم قبلاً در اولین فراخوانی ما کش شده( $this→participants() ).(در ضمن، هنوز یک فراخوانی بهینه نشده مربوط به همین نکته در کد بالا وجود دارد، آیا می‌تونید تشخیص بدید؟ در بخش نظرات برای ما بنویسید).۳. فایل‌های Blade خود را بهبود دهیدمن عاشق blade هستم، balde یک templating engine فوق‌العاده قدرتمند است که با laravel عرضه شده و سینتکس شگفت‌انگیزی دارد. اما آیا شما از تمام این قدرت و پتانسیل استفاده می‌کنید؟همه ما برای نمایش برخی از کالکشن‌ها به کاربران باید از @foreach استفاده کنیم، اما اگر کالکشن empty باشد چه باید کرد؟ پاسخ ساده این است که باید قبل از @foreach از @if statement استفاده کنید. راه بهتری نیز برای نوشتن این وجود دارد :@endforelse&lt;?php@forelse ($participants as $participant)&lt;li&gt;{{ $participant-&gt;email }}&lt;/li&gt;@empty&lt;p&gt;No participants in this project :(&lt;/p&gt;@forelse شباهت زیادی به @foreach دارد، اما با اضافه شدن بخش @empty ، بسیار کار تمیزتر از استفاده @if شده، اینطور نیست؟صحبت از @if شد، blade دستور جذاب دیگری نیز دارد که من عاشق آن هستم: @unless و @endunless. این دقیقاً برعکس @if است و بسیار بهتر از یک @if با شرط منفی است و خوانایی کد را بالا می‌برد. اگر تا به حال از روبی استفاده کرده باشید، می‌دانید که چگونه کار می‌کند.همچنین استفاده از میانبرهای احراز هویت (@auth/@endauth و @guest/@endguest) بسیار بهتر از @if(Auth::check()) است.خوانایی کد را بالا می‌برد.مثالی از داکیومنت laravel ۵.۵ :@endguest&lt;?php@auth// The user is authenticated...@endauth@guest// The user is not authenticated...در اسناد رسمی laravel موارد بیشتری وجود دارد که می‌توانید از آن استفاده کنید. اکیدا توصیه می‌کنم به جا استفاده از دسته‌ای if بی‌معنی از این روش‌ها استفاده کنید تا فایل template خود را بهتر و بهتر کنید.</description>
                <category>مهدی قوسیان | Mahdi Gosyan</category>
                <author>مهدی قوسیان | Mahdi Gosyan</author>
                <pubDate>Sat, 17 Apr 2021 02:19:15 +0430</pubDate>
            </item>
                    <item>
                <title>راهکاری هوشمندانه برای بهبود سئو در لاراول</title>
                <link>https://virgool.io/@mahdigosyan/%D8%B1%D8%A7%D9%87%DA%A9%D8%A7%D8%B1%DB%8C-%D9%87%D9%88%D8%B4%D9%85%D9%86%D8%AF%D8%A7%D9%86%D9%87-%D8%A8%D8%B1%D8%A7%DB%8C-%D8%A8%D9%87%D8%A8%D9%88%D8%AF-%D8%B3%D8%A6%D9%88-%D8%AF%D8%B1-%D9%84%D8%A7%D8%B1%D8%A7%D9%88%D9%84-g7pltmzuojxr</link>
                <description>همیشه برای سئو دغدغه های زیادی داریم و با توجه به اینکه cms هایی همانند وردپرس با قدرت افزونه هایی که دارند عملا همیشه در لاراول آرزوی راحتی سئو را دارا هستیم .برای سئو در لاراول بهترین راه استفاده از پکیج seotools هست مشکل بزرگی که این پکیج ها دارن اینه که توی هر متد از کنترلر ما باید این تایتل پاس داده بشه و اگر جایی بخواهیم تغییر بدیم باید توی تک تک جاهایی که تعریف کردیم این تغییر انجام بدیم.برای این منظور راهکاری رو استفاده کردم که شاید به کار شما عزیزان هم بیاد و یکی از اصول سالید هم اینطوری خیلی بهتر رعایت خواهد شد.composer require artesaos/seotoolsشما باید بعد از نصب پکیج با دستورphp artisan make:middleware SEOیک میدلویر با نام سئو بسازید و این میدلویر در بخش روت میدلویر ها در Kernel.php اضافه کنید.بعد از اینکار شما باید یک کلاس Enum درست کنید در نسخه جدید پی اچ پی این امکان محیاست در نسخه های قدیمی هم کلاسی مشابه کلاس زیر باید بسازید}&lt;?phpclass SEOModelTypesEnum{const PAGE = &#039;pages&#039;;const PRODUCT = &#039;product/&#039;;const ARCHIVE = [&#039;products&#039;];const HOME = &#039;/&#039;;const TYPES = [&#039;PAGE&#039; =&gt; self::PAGE,&#039;PRODUCT&#039; =&gt; self::PRODUCT,&#039;ARCHIVE&#039; =&gt; self::ARCHIVE,&#039;HOME&#039; =&gt; self::HOME,];کد هایی که میبینید مربوط به یک سایت فروشگاهی می باشد که تمام صفحاتی که نیاز به سئو و تایتل و دیسکریپشن داینامیک را دارا هستند در کلاس بالا به شکلی که میبینید قرار خواهید داد تا تمام اجزای سایت یک پارچه شود.حالا به سراغ میدلویری که ساختیم میرویم:و طبق نمونه زیر کد ها را تغییر میدهیم در این کد ما از Enum هایی که تعریف کردیم استفاده میکنیم و به صورت کاملا داینامیک بر اساس محلی که کاربر درخواست ارسال کرده ما هم طبق آن درخواست تایتل و دیسکریپشن و حتی عکس را هم پر میکنیم});&lt;?phpnamespace App\Http\Middleware;use App\Enumoration\SEO\SEOModelTypesEnum;use Artesaos\SEOTools\Facades\SEOTools;use Closure;class Seo{/*** Handle an incoming request.** @param  \Illuminate\Http\Request  $request* @param  \Closure  $next* @return mixed*/public function handle($request, Closure $next, $seo=null){$seo = is_array($seo)? $seo: explode(&#039;|&#039;, $seo);$path = $request-&gt;path();$find = explode(&#039;/&#039;,$path);$type = null;$base_url = url(&#039;/&#039;);foreach (SEOModelTypesEnum::TYPES as $key=&gt;$seoType){if(str_contains($path,is_array($seoType)?$seoType[0]:$seoType)){$type = $key;break;}}switch ($type){case &#039;HOME&#039;:$seo = [&#039;Rocket - Home&#039;,&#039;آموزش برنامه نویسی&#039;,&#039;https://bareshacademy.com&#039;.$path,&amp;quot$base_url/آدرس عکس&amp;quot];break;case &#039;Product&#039;:$product = Product::query()-&gt;whereSlug(end($find))-&gt;first();$seo = [&amp;quot$product-&gt;title - &amp;quot,&#039;آموزش برنامه نویسی&#039;,$base_url.$path,&amp;quot$base_url/$product-&gt;image&amp;quot];break;case &#039;PAGE&#039;:$page = Page::query()-&gt;whereSlug(end($find))-&gt;first();$seo = [&amp;quot$page-&gt;title - &amp;quot,&#039;آموزش برنامه نویسی&#039;,$base_url.$path,&amp;quot$base_url/$page-&gt;image&amp;quot];break;case &#039;ARCHIVE&#039;:$seo = [////////];break;و ....}SEOTools::setTitle($seo[0]??&#039;Roocket&#039;);SEOTools::setDescription($seo[1]??&#039;آموزش برنامه نویسی&#039;);SEOTools::opengraph()-&gt;setUrl(&#039;https://bareshacademy.com&#039;.$seo[2]??&#039;https://bareshacademy.com&#039;);SEOTools::twitter()-&gt;setSite(&#039;@twitter&#039;);SEOTools::jsonLd()-&gt;addImage($seo[3]??&#039;&#039;);return $next($request);}}‍Route::middleware(&#039;seo&#039;)-&gt;group(function (){Route::get(&#039;/&#039;, &#039;HomeController@index&#039;)-&gt;name(&#039;home&#039;);همانطور که دیدید این کد به سادگی جلوی تکرار هزاران خط کد اضافی را گرفت حالا برای استفاده فقط کافی است تا روت هایی که قصد دارید تا تایتل داشته باشند رو از روت میدلویر رد بکنید تا همه آن ها سئو شوند و دیگر دغدغه سئو و پکیج های مختلف را فراموش کنیدبه همین راحتی ! جلوی تکرار کد گرفته شد‌ ٬ کد یکپارچه تر شد و هر موقع خواستیم هر تغییری بدیم نهایت ۲ فایل را ویرایش میکنیم نه ۱۰۰ فایل! و واقعا خود من به شخصه این راهکار را برای اکثر کارها پیش میبرم حتی گاها بجای استفاده از چند کنترلر برای تفکیک api , view میشه خیلی راحت با میدلویر اینکارو انجام داد که سعی میکنم در آموزش های بعدی اینو بهتون آموزش بدم.در نهایت برای نمایش و خروجی در blade هم از کد زیر در هد Head صفحه بهره میبرید:{!! SEO::generate() !!}</description>
                <category>مهدی قوسیان | Mahdi Gosyan</category>
                <author>مهدی قوسیان | Mahdi Gosyan</author>
                <pubDate>Wed, 07 Apr 2021 00:29:15 +0430</pubDate>
            </item>
                    <item>
                <title>۷ اشتباه برنامه نویسان مبتدی هنگام یادگیری کد نویسی</title>
                <link>https://virgool.io/coderlife/%DB%B7-%D8%A7%D8%B4%D8%AA%D8%A8%D8%A7%D9%87-%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%D8%A7%D9%86-%D9%85%D8%A8%D8%AA%D8%AF%DB%8C-%D9%87%D9%86%DA%AF%D8%A7%D9%85-%DB%8C%D8%A7%D8%AF%DA%AF%DB%8C%D8%B1%DB%8C-%DA%A9%D8%AF-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-mhfm4qmadto4</link>
                <description>یادگیری نحوه درست کد نویسی می‌تواند بسیار ارزشمند باشد. امروزه مهارت‌های کد نویسی تقاضای بالایی دارند، بنابراین اکنون فرصتی عالی برای شروع کردن و دستیابی به مشاغل پردرآمد است. یادگیری اصول کد نویسی ممکن است برای عده‌ای دلهره آور به نظر برسد اما همزمان با اینکه یاد می‌گیرید، دانش شما کم کم شکل می‌گیرد و برای رسیدن به یک هدف نهایی کار می‌کند و در این مسیر میتوانید از اشتباه خود جلوگیری کنید.با وجود بسیاری از زبان‌های برنامه نویسی ممکن است ابتدا در انتخاب زبان دچار سردرگمی شوید، اما هر زبان روش‌های مختلفی برای کد نویسی پروژه‌هایتان ارائه می‌دهد، زیرا هرکدام مزایای خاص خود را دارند. با این حال فقط به یکی پایبند باشید و قبل از رفتن به مرحله بعدی مهارت کافی در آن کسب کنید. در این صورت اطمینان حاصل می‌کنید که در دانش خود خللی نخواهید داشت و می‌توانید مهارت‌هایتان را کاملا به نفع خود پیش ببرید.بگذارید برخی از اشتباهاتی را که ممکن است هنگام توسعه مهارت‌های کد نویسی یا شروع آموزش کدزنی مرتکب شد را بررسی کنیم تا مطمئن شوید که می‌توانید از رویکرد خود بهره گیری کامل را داشته باشید و نتایج مورد نیاز خود را به دست آورید.۱. انتخاب معلم یا مربی نامناسبمعلمان و مربیان بخش مهمی از تجربه یادگیری شما هستند، خصوصا اگر با خودآموزی راحت نباشید. انتخاب اولین معلم یا مربی ممکن است برایتان مفید واقع نشود، زیرا آنها هر یک تجربه متفاوت خود را دارند و فقط با برخی زبان‌های برنامه نویسی یا روش‌های کلی آن آشنا هستند.این روزها تعداد منابع آنلاین برای یادگیری کد نویسی رشد چشمگیری داشته و با ارائه برخی محتوای با کیفیت، به راحتی می‌توان به صورت آنلاین کار را شروع کرد. اگر دوره‌های آنلاین را انتخاب می‌کنید، باید کیفیت آن را نیز بررسی کنید. تحقیقات خود را انجام دهید و ببینید آیا می‌توانید بعد از اتمام دوره به درآمدزایی برسید یا نه. در چنین بازار سودآوری، فروشندگانی وجود دارند که تنها قول می‌دهند با شرکت در این دوره‌ها نتایج عالی ارائه دهند.فناوری همیشه در حال پیشرفت است و انتخاب افرادی که از آنها می‌آموزید یکی از مهمترین معیارهای موفقیت شماست. توجه داشته باشید که هیچ مربی یا دوره‌ای وجود ندارد که بتواند همه چیز را به شما یاد دهد. مشورت با چندین نفر ارزشش را دارد تا دیدگاه‌ها و تخصص‌های مختلفی را در نظر بگیرید.۲. یادگیری همه چیز به یک بارهیافتن یک نقطه شروع در کد نویسی نسبتا ساده است، قبل از اینکه به بخش عمیق ماجرا بپردازید، ابتدا یک زبان برنامه نویسی را انتخاب کنید و اصول را یاد بگیرید. وقتی صحبت از برنامه نویسی می‌شود، عمق، اهمیت بیشتری نسبت به وسعت دارد. کارفرمایان به دنبال درک عمیق یک زبان هستند تا درک مختصری از بسیاری زبان‌ها. سعی کنید از منابع متعددی استفاده کنید تا زوایا، روش‌ها و دیدگاه‌های مختلف را فرا بگیرید و درک خود را از روش‌های مختلف حل یک مسئله گسترش دهید. به یاد داشته باشید هدف این است که دانش خود را تمرین دهید و بارها آن را تکرار کنید تا بتوانید بدون راهنمایی و بدون افتادن در دام برزخ آموزشی، پروژه نهایی خود را بسازید.با اینکه بیشتر دانش شما از تحصیلات، مربیان و منابع به دست می‌آید، با فعالیت در محیط‌های کار واقعی به همراه همکارانی که زبان انتخابی شما را نیز می‌دانند، مهارت بیشتری کسب خواهید کرد. همکاری همزمان با هم تیمی‌هایتان در پروژه‌های واقعی به شما کمک می‌کند تا خلا دانش برنامه نویسی خود را پر کنید و مهارت‌های خود را بیشتر توسعه دهید.۳. یاد نگرفتن اصولنمی‌توان تأکید کرد که یادگیری نحوه کار سیستم‌های کامپیوتری حداقل در سطح اولیه قبل از ورود به دنیای کد نویسی مهم است. یادگیری چگونگی ارتباط کامپیوترها و برنامه‌ها با یکدیگر از اهمیت بالایی برخوردار است، به خصوص درک اینکه چرا زبان‌های بسیاری به وجود آمدند و اینکه هر کدام به طور جداگانه چگونه می‌توانند در یک پروژه واقعی به کار برده شوند.قبل از اینکه به طور عمیق وارد دنیای فناوری اطلاعات شویم، ابتدا باید با اصول اساسی شروع کنیم. تکنولوژی‌های مختلف می‌آیند و می‌روند اما فناوری اصلی و نحوه کار برنامه‌ها در چند دهه اخیر تغییر چندانی نکرده است. ما در جهانی زندگی می‌کنیم که علم دائما در حال به روز شدن و تغییر است. هنگامی که یادگیری اصولی را شروع کنیم، مواردی هستند که در طول زمان ثابت می‌مانند و در کنار آن فناوری‌های مختلف به مرور دستخوش تغییرات می‌شوند.با یادگیری اصول و ساختارهای اساسی در هر زبان برنامه نویسی مانند متغیرها، دامنه‌ها، توابع، حلقه‌ها، شرط‌ها، آرایه‌ها، انواع داده‌ها و موارد دیگر به سرعت قادر به انتقال به یک زبان برنامه نویسی جدید در هر زمان خاص هستیم.بنابراین می‌خواهیم به جای کسب دانش کوتاه مدت، بر دانشی متمرکز شویم که از ساختار همه زبان‌های برنامه نویسی پشتیبانی می‌کند. اگر اینگونه شروع کنیم، مهم نیست که تکنولوژی چه مدت تغییر می‌کند، مهم نیست که جامعه چگونه تغییر کند، ما این اصول را برای توسعه مهارت خود به کار می‌گیریم و آن را تغییر می‌دهیم تا با جامعه فعلی سازگار شود.۴. گرفتاری در دام برزخ آموزشیتماشای آموزش آنلاین یک روش مطمئن برای ایجاد یک نسخه کپی از یک پروژه موجود است. درعوض روش بهینه برای یادگیری و به دست آوردن تجربه بیشتر این است که دانش موجود خود را عملی کنید و پروژه خود را توسعه دهید. بعید است کد شما همانطور که انتظار دارید تمیز و مختصر باشد. با توسعه مداوم پروژه‌های مختلف، آنچه می‌توانید دفعات بعدی بهبود ببخشید را فراهم می‌کنید.همچنین سعی کنید به جای عجله در ایجاد یک پروژه پیچیده از طریق آموزش گام به گام، ابتدا شروع به کار کوچک کرده تا از رویکرد خود اطمینان حاصل کنید.۵. تعیین نکردن اهداف و مهلت مشخصاهداف و ددلاین‌ها از اهمیت ویژه‌ای برخوردار هستند که در یک محیط کار واقعی، بارها با آنها روبه رو خواهید شد. آشنایی با نحوه کار برنامه‌ها، اهداف و مهلت‌های تعیین شده سرعت کار شما را افزایش می‌دهد و می‌توانید تعیین کنید که آیا دانش و تجربه شما به اندازه کافی کامل است تا بتوانید یک پروژه واقعی را در مهلت مشخصی مدیریت کنید.شما هستید که باید تعیین کنید پروژه چگونه خواهد بود و بسته به اندازه، یک مهلت مشخصی برای اتمام آن همراه با تعیین اهداف کوچک در این بین تعیین کنید تا در مسیر درست قرار بگیرید. همچنین تعیین اهداف كوچكتر، به حفظ انگیزه و نگه داشتن شما در پروژه كمك می‌كند. اگر در این مدت به موانعی برخوردید، می‌توانید میزان پیشرفت خود را ارزیابی کرده و مهلت خود را متناسب با هرگونه تغییر در برنامه تنظیم کنید. این امر به شما امکان می‌دهد تا درمورد هر مسئله‌ای که پیش آمده با کارفرما یا مشتری خود ارتباط برقرار کنید و باعث ایجاد یک رابطه کاری خوب می‌گردد که در محیط کاری واقعا ارزشمند است.۶. عدم توضيح مفاهيم فني به زبان سادهاین اشتباه فاحشی است که می‌تواند رابطه بین مشتری و توسعه دهنده را خراب کند. مشتریان باید توضیحات منظم و واضحی دریافت کنند، این نشان می‌دهد که پروژه قرار است به درستی برنامه ریزی شود و تمام نیازهای آنها را برآورده می‌کند. اصطلاحات فنی مورد استفاده توسط برنامه نویسان اغلب برای افراد بی تجربه گیج کننده است، بنابراین باید به روشی واضح و مختصر توضیح داده شود.وقتی نوبت به برنامه نویسی می‌رسد، کاربر نهایی یا مشتری به طور کلی به تأثیرات کار علاقه مند است، نه فرایند پشت آن. بنابراین توضیح دادن اینکه &quot;سرور هنگام پردازش دستور در خط ۱۲ با خطا مواجه شده است&quot; احتمالا برای او معنایی نخواهد داشت. درعوض باید بتوانید اینگونه توضیح دهید که &quot;فایل بارگذاری نشده است و ما تخمین می‌زنیم که این مشکل ظرف مدت یک ساعت حل شود&quot;، این روش اطلاعات مهم مورد نیاز مشتری را در اختیارش قرار می دهد و مشکل را به روشی می‌فهمد که درک آن برای همه آسان است.همچنین کار در محیطی که شما در حال طراحی یک مفهوم برنامه نویسی هستید بسیار مفید است. مشتری به دنبال هر مزیتی است که کد نویسی شما برای آنها فراهم می‌کند و هرگونه تأثیر احتمالی ممکن است ایجاد شود. مثلا توضیح اینکه چگونه نرم‌افزار مورد نظر از راه‌های ارتباطی استفاده می‌کند تا مدت زمان مکالمه مشتری توسط نماینده خدمات کاربر کاهش یابد.اگر می‌دانید که قسمت انتهایی این نوع سیستم چگونه کار می‌کند اما نمی‌توانید مزایای برنامه نویسی خود را به مشتری منتقل کنید، بعید است که کار شما به نفع آنها باشد.۷. عدم درخواست پشتیبانیاگر چیزی را نمی‌فهمید، باید درخواست کمک کنید. برنامه نویسان در تیم‌ها بسیار خوب کار می‌کنند و اغلب قادر به ارائه اطلاعات در مورد حل و انطباق یک مشکل هستند. به همین دلیل توصیه می‌شود کسی را پیدا کنید که در مسیری مشابه با شما قرار دارد یا حتی یک مربی که برای پاسخگویی به سوالاتتان در آنجا حضور دارد و می‌تواند به شما در تسریع روند یادگیری کمک کند. همچنین به شما کمک می‌کند تا بتوانید به طور خلاصه یک مسئله را توضیح دهید و مهارت خود را برای حل مشکل نشان دهید.همه برنامه نویسان مراحلی را طی کرده‌اند که در آن تمام پاسخ‌ها برای حل یک مشکل خاص را نداشته‌اند و مجبور بوده‌اند به دنبال پشتیبانی باشند.جمع بندیهنگامی که وقت خود را صرف کاری می‌کنید، فرصت انجام کار دیگری را از دست می‌دهید. همه آموزش‌ها با هم برابر نیستند، بنابراین توصیه می‌شود کمی وقت بگذارید و به تحقیق بپردازید تا بتوانید تصمیم درست بگیرید که چه کاری را باید چه موقع انجام دهید. کسانی که موفق می‌شوند کسانی هستند که می‌توانند به طور کارآمد یاد بگیرند. این مهارتی است که فراتر از یادگیری کد نویسی است.خودتان کار کنید و چالش‌های مختلف را امتحان کنید، سعی کنید مربیانی پیدا کنید که بتوانید به آنها اعتماد کنید. صبور باشید چرا که این کار زمان می‌برد، اما در یک مهارت ارزشمند سرمایه گذاری می‌کنید که همیشه دارای پتانسیل رو به رشد است.</description>
                <category>مهدی قوسیان | Mahdi Gosyan</category>
                <author>مهدی قوسیان | Mahdi Gosyan</author>
                <pubDate>Tue, 09 Feb 2021 14:56:34 +0330</pubDate>
            </item>
                    <item>
                <title>برنامه نویسی فانکشنال چیست؟</title>
                <link>https://virgool.io/fboard/%D8%A8%D8%B1%D9%86%D8%A7%D9%85%D9%87-%D9%86%D9%88%DB%8C%D8%B3%DB%8C-%D9%81%D8%A7%D9%86%DA%A9%D8%B4%D9%86%D8%A7%D9%84-%DA%86%DB%8C%D8%B3%D8%AA-owiwppxhbjyq</link>
                <description>بیشتر آنچه در این مقاله بحث خواهیم کرد، دانش جمع شده از مطالعه “برنامه نویسی فانکشنال در جاوااسکریپت“، توسط لوئیس آتنسیو است.برنامه نویسی فانکشنال چیست؟به زبان ساده، برنامه نویسی فانکشنال یک سبک توسعه نرم‌افزار است که تأکید عمده‌ای بر استفاده از توابع دارد. ممکن است بگویید “من روزانه از توابع استفاده می‌کنم، پس تفاوت چیست؟” خوب، فقط استفاده از توابع نیست که به نتیجه برسد. هدف این است که تجزیه کنترل جریان و عملکرد داده‌ها با توابع به منظور جلوگیری از عوارض جانبی و کاهش جهش حالت‌ها در برنامه شما باشد.کنترل جریان دادهبرای درک معنای کنترل جریان‌های انتزاعی، ابتدا باید مدلی از برنامه نویسی را به نام برنامه نویسی ضروری یا رویه‌ای بررسی کنیم. برنامه نویسی Imperative یک برنامه کامپیوتری را فقط دنباله‌ای از دستورات بالا به پایین می‌داند که برای محاسبه نتیجه، وضعیت سیستم را تغییر می‌دهد.برنامه نویسی دستوری با جزئیات کامل، به کامپیوتر می‌گوید که چگونه می‌تواند یک کار خاص را انجام دهد (برای مثال حلقه و استفاده از فرمول داده شده برای هر مورد از یک آرایه). این متداول‌ترین روش نوشتن کد است. به عنوان مثال:var array = [۰, ۱, ۲, ۳, ۴, ۵, ۶, ۷, ۸, ۹];
for(let i = ۰; i &lt; array.length; i++) {
    array[i]= Math.pow(array[i], ۲);
}
array;
//-&gt; [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]از طرف دیگر، برنامه نویسی فانکشنال (تابعی) تحت تاثیر برنامه‌های اعلامی قرار می‌گیرد. این نوعی برنامه نویسی است که مجموعه‌ای از عملیات را بیان می‌کند بدون اینکه نحوه پیاده‌سازی یا چگونگی جریان داده در آن‌ها را بیان کند.برنامه نویسی اعلامی ، توصیف برنامه را از ارزیابی جدا می کند. این برنامه بر استفاده از عبارات برای توصیف منطق یک برنامه متمرکز است بدون اینکه لزوماً جریان کنترل یا تغییرات حالت آن مشخص شود.برنامه نویسی اعلامی، توصیف برنامه را از ارزیابی جدا می‌کند. این برنامه بر استفاده از عبارات به منظور توصیف منطق یک برنامه متمرکز است، بدون اینکه لزوما جریان کنترل یا تغییرات حالت آن مشخص شود.شما فقط باید نگران اعمال درست در هر عنصر و کنترل حلقه در سایر قسمت‌های سیستم باشید. به عنوان مثال، اجازه دادن به ()Array.map که بیشترین کار سنگین را انجام دهد، یک رویکرد کاربردی‌تر محسوب می‌شود.[۰, ۱, ۲, ۳, ۴, ۵, ۶, ۷, ۸, ۹].map(num =&gt; Math.pow(num, ۲));
//-&gt; [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]با استفاده از این روش، ما حلقه‌های خود را با توابع انتزاع می‌کنیم و در مقایسه با مثال قبلی، می‌بینید که این کد شما را از مسئولیت مدیریت صحیح یک شمارنده حلقه و دسترسی به آرایه آزاد می‌کند. به زبان ساده‌تر، هرچه کد شما بیشتر باشد، مکان‌های بیشتری برای بروز اشکال وجود دارد. همچنین حلقه‌های استاندارد قابل استفاده مجدد نیستند، مگر اینکه با توابع انتزاع شده باشند.در حالت ایده‌آل، حلقه‌های دستی باید کاملا از کد شما حذف شود و به نفع توابع درجه یک مانند نقشه، کاهش و فیلتر که توابع را به عنوان پارامتر می‌پذیرد تا کد شما قابل استفاده مجدد و گسترش‌پذیر باشد.از عوارض جانبی خودداری کنیدبرنامه نویسی فانکشنال بر این فرض استوار است که شما هنگام ساختن برنامه‌های خود از توابع خالص (توابع بدون هیچگونه عوارض جانبی) به عنوان بلوک‌های اصلی استفاده می‌کنید. توابع خالص دارای ویژگی‌های زیر است:آنها فقط به ورودی ارائه شده بستگی دارند و به هیچ ورودی پنهان یا خارجی بستگی ندارند. آن‌ها تغییراتی فراتر از محدوده خود اعمال نمی‌کنند، مانند اصلاح یک شی گلوبال.هر تابعی که این شرایط را برآورده نکند “نا خالص” است. تابع زیر را در نظر بگیرید:var counter = ۰;
function increment() {
    return ++counter;
}این تابع ناخالص است زیرا یک متغیر خارجی، شمارنده را خوانده یا اصلاح می‌کند که مختص به دامنه تابع نیست. به طور کلی، توابع هنگام خواندن یا نوشتن از منابع خارجی عوارض جانبی دارند، همانطور که در مثال بالا نشان داده شده است. نتیجه آن غیر قابل پیش‌بینی است، زیرا متغیر شمارنده می‌تواند در هر زمان بین هر فراخوانی تغییر کند.ممکن است سوال شود که “اگر قادر به ایجاد و اصلاح اشیا نباشید یا روی کنسول چاپ نکنید، از چنین برنامه‌ای چه ارزش عملی می گیرید؟” در واقع، استفاده از توابع خالص در دنیایی پر از پویایی رفتار و جهش دشوار است اما برنامه نویسی فانکشنال، همه تغییرات وضعیت را محدود نمی‌کند. این فقط یک چارچوب را برای کمک به شما در مدیریت و کاهش آن‌ها فراهم می‌کند در حالی که به شما امکان می‌دهد ناخالصی را جدا کنید. کد ناخالص عوارض جانبی قابل رویت خارجی ایجاد می‌کند.جهش حالت را کاهش دهیدداده غیرقابل تغییر داده‌ای است که پس از ایجاد تغییر نمی‌کند. در جاوااسکریپت، مانند بسیاری از زبان‌های دیگر، انواع ابتدایی (String ، Number و …) ذاتا قابل تغییر نیستند. اما اشیا دیگری مانند آرایه‌ها، تغییرپذیرند.وضعیت یک برنامه را می‌توان از داده‌های ذخیره شده در همه اشیا آن در هر لحظه از زمان تعریف کرد. متأسفانه، جاوااسکریپت یکی از بدترین زبان‌ها در مورد امنیت وضعیت یک شی است. یک شی جاوااسکریپت بسیار پویا است و شما می‌توانید در هر برهه از زمان ویژگی‌های آن را تغییر دهید، اضافه یا حتی حذف کنید. اگرچه این ممکن است به شما آزادی انجام بسیاری از کارهای نرم‌افزاری را بدهد، اما همچنین می‌تواند به کدی منجر شود که نگهداری آن بسیار دشوار است.ممکن است بپرسید که چرا توصیه می‌شود همیشه حلقه‌های دستی را از کد خود حذف کنید؟ خوب، حلقه دستی یک ساختار کنترل ضروری است که استفاده مجدد از آن دشوار است و اتصال آن به سایر عملیات امری مشکل است. به علاوه این حاوی کدی است که در پاسخ به تکرارهای جدید دائما در حال تغییر شکل است.برنامه‌های فانکشنال تا حد امکان تغییرناپذیری را هدف قرار می‌دهند.ES۶ از کلمه کلیدی const برای ایجاد مراجع ثابت استفاده می‌کند. این سوزن را در مسیر درست حرکت می‌دهد زیرا ثابت‌ها را نمی‌توان دوباره تعیین یا دوباره اعلام کرد. در برنامه نویسی فانکشنال، شما می‌توانید از ساختار به عنوان وسیله‌ای برای وارد کردن داده‌های پیکربندی ساده (رشته‌های URL، نام پایگاه داده و …) استفاده کنید. اما این مشکلات قابل تغییر بودن را تا حدی که برنامه نویسی تابعی نیاز دارد حل نمی‌کند. می‌توانید از تعیین مجدد یک متغیر جلوگیری کنید، اما چگونه می‌توان از تغییر وضعیت داخلی یک شی جلوگیری کرد؟ به عنوان مثال، این کد کاملا قابل قبول است:const student = new Student(&#039;Alonzo&#039;, &#039;Church&#039;, &#039;۶۶۶-۶۶-۶۶۶۶&#039;, &#039;Princeton&#039;);
student.lastname = &#039;Mourning&#039;;آنچه شما نیاز دارید سیاست سخت‌گیرانه‌تری برای تغییر ناپذیری آن است، Encapsulation استراتژی خوبی برای محافظت در برابر جهش است. برای ساختارهای ساده اشیا متناوب، یک گزینه خوب اتخاذ الگوی Value Object است که به آن الگوی Module نیز گفته می‌شود.function zipCode(code, location) {
  let _code = code;
  let _location = location || &#039;&#039;;
  return {
    code: function () {
      return _code;
    },
    location: function () {
      return _location;
    },
    fromString: function (str) {
      let parts = str.split(&#039;-&#039;);
      return zipCode(parts[۰], parts[۱]);
    },
    toString: function () {
      return _code + &#039;-&#039; + _location;
    }
  };
}در جاوااسکریپت، می‌توانید با بازگرداندن یک شی تحت اللفظی که مجموعه کوچکی از متدها را در معرض فراخوانی گیرنده قرار می‌دهد و خصوصیات محصور شده آن را به عنوان متغیرهای شبه خصوصی در نظر می‌گیرد، از توابع و دسترسی به حالت داخلی یک تابع استفاده کنید. این متغیرها فقط در شی از طریق کامپوزرها (بستارها) قابل دسترسی هستند، همانطور که در مثال بالا مشاهده می‌کنید.شی برگشتی در واقع مانند یک نوع اولیه رفتار می‌کند که هیچ متد جهشی ندارد. از این رو، متد toString، اگرچه یک تابع خالص نیست، اما مانند آن رفتار می‌کند و یک نمایش رشته‌ای خالص از این شی است. اشیا دارای ارزش پایینی بوده و در برنامه نویسی فانکشنال و شی‌گرا کار راحتی را بر عهده دارند.نتیجه‌گیریوقتی به طراحی برنامه خود فکر می‌کنید، سوالات زیر را از خود بپرسید:آیا برای پشتیبانی از قابلیت‌های اضافی، مرتبا کد خود را تغییر می‌دهم؟اگر یک فایل یا تابع را تغییر دهم، دیگری تحت تأثیر قرار می‌گیرد؟آیا تکرار زیادی در کد من وجود دارد؟آیا کد من بدون ساختار است یا پیگیری آن سخت است؟اگر به هر یک از این سوالات پاسخ مثبت دادید، سعی کنید برنامه نویسی فانکشنال را در صدر کار قرار دهید. فقط به یاد داشته باشید، در برنامه نویسی فانکشنال، توابع واحدهای اساسی کار هستند، به این معنی که همه چیز در اطراف آن‌ها قرار دارد.یک تابع عبارتی است که بتوان با استفاده از عملگر () بر روی آن ارزیابی کرد. توابع می‌توانند مقدار محاسبه نشده یا تعریف نشده (تابع خالی) را فراخوانی کنند. از آنجا که برنامه نویسی فانکشنال بسیار شبیه ریاضیات است، توابع فقط وقتی معنی‌دار هستند که نتیجه قابل استفاده (غیر صفر یا تعریف نشده) ایجاد کنند. در غیر این صورت، فرض بر این است که آن‌ها داده‌های خارجی را اصلاح می‌کنند و باعث بروز عوارض جانبی می‌شوند.برای اینکه از برنامه نویسی فانکشنال بهره‌مند شوید، باید یاد بگیرید که تابعی بیندیشید و در نتیجه، آگاهی تابعی خود را توسعه دهید – غریزه نگاه کردن به مشکلات به عنوان ترکیبی از توابع ساده که در کنار هم یک راه‌حل کامل را ارائه می‌دهند.در سطح بالا، برنامه نویسی فانکشنال به طور موثر تأثیر متقابل بین تجزیه (شکستن برنامه‌ها به قطعات کوچک) و ترکیب (پیوستن قطعات به یکدیگر) است. همین دوگانگی است که برنامه‌های کاربردی را ماژولار و بسیار موثر می‌کند.اگر هرگونه سوال، پیشنهاد یا نظری دارید، در بخش زیر با ما در میان بگذارید.</description>
                <category>مهدی قوسیان | Mahdi Gosyan</category>
                <author>مهدی قوسیان | Mahdi Gosyan</author>
                <pubDate>Fri, 29 Jan 2021 15:14:15 +0330</pubDate>
            </item>
                    <item>
                <title>از “data” به عنوان نام متغیر استفاده نکنید</title>
                <link>https://virgool.io/@mahdigosyan/%D8%A7%D8%B2-data-%D8%A8%D9%87-%D8%B9%D9%86%D9%88%D8%A7%D9%86-%D9%86%D8%A7%D9%85-%D9%85%D8%AA%D8%BA%DB%8C%D8%B1-%D8%A7%D8%B3%D8%AA%D9%81%D8%A7%D8%AF%D9%87-%D9%86%DA%A9%D9%86%DB%8C%D8%AF-pbjc75fbanel</link>
                <description>فیل کارلتون می‌گوید: “فقط دو چیز سخت در علوم کامپیوتر وجود دارد: نامعتبر بودن حافظه پنهان و نام گذاری موارد.” ؛با کنار گذاشتن نامعتبر بودن حافظه پنهان که واقعا دشوار است، این جمله چیزی است که هر زمان در پیدا کردن نام مناسب به مشکل می‌خورم، در ذهن من به صدا درمی‌آید. نام گذاری صحیح برای کسی که نیاز به فهم سریع کد داشته باشد، چه در حال دیباگینگ و چه برای کمک به هم تیمی، از اهمیت بالایی برخوردار است. لازم نیست از کسی بپرسم منظور از users چیست، اما باید بپرسم که data به چه معناست. هرچند که خودم اغلب بهترین اسامی را پیدا نمی‌کنم، اما سعی دارم با رعایت برخی قوانین اساسی کد خود را برای خواننده بهینه کنم.قوانین:از پیشوندهای معنی‌دار استفاده کنیداگرچه این پیشوندها جهانی نیستند، اما برای ایجاد یک زبان مشترک در تیم شما عالی هستند و استفاده مداوم از آنها در کد می‌تواند درک مطلب را آسان کند.get، find، fetch برای توابعی که مقداری را برمی‌گردانند یا یک promise که بدون تغییر دادن استدلال‌ها به یک مقدار تبدیل می‌شود.set، update برای توابعی که آرگومان‌ها را تغییر می‌دهند یا اعضا را فراخوانی می‌کنند. این توابع همچنین ممکن است مقدار به روز شده یا promise را که به مقدار به روز شده تغییر می‌کند، برگردانند.on، handle برای توابع کنترل کننده رویداد. قرارداد تیم من این است که onEvent از طریق props به درون کامپوننت منتقل می‌شود و handleEvent در داخل کامپوننت تعریف می‌شود.is، should، can برای متغیرها و توابع بولین با مقادیر برگشت بولی.هر کنوانسیونی که در تیم شما استاندارد شود، می‌تواند به خوانایی شما کمک کند. مطمئن شوید که این موارد را در README یا wiki مستند کنید. ایجاد linterهای سفارشی برای اجرای این موارد حتی موثرتر خواهد بود.از کلمات بامعنی استفاده کنیدبه عنوان مثال توسعه‌دهندگان غالبا متغیرها را به طور پیش فرض data نامگذاری می‌کنند، اما بیایید چند تعریف از آنها را بررسی کنیم:“اطلاعات واقعی (مانند اندازه‌گیری یا آمار) که به عنوان مبنایی برای استدلال، بحث یا محاسبه استفاده می‌شوند”“اطلاعاتی که به شکل دیجیتال قابل انتقال یا پردازش‌اند”این تعاریف می‌توانند به هر متغیری که پردازش می‌کنیم اشاره داشته باشند، بنابراین هیچ اطلاعاتی به خواننده نمی‌دهند. بیایید به مثالی نگاه کنیم که از این قاعده پیروی نمی‌کند:function total(data) {
  let total = ۰;
  for (let i = ۰; i &lt; data.length; i++) {
    total += data[i].value;
  }

  return total;
}می‌دانیم که این تابع در کل چیزی را محاسبه می‌کند، اما مطمئن نیستیم که آن چه چیزی است.استثناهاگاهی اوقات متغیر می‌تواند شامل هر چیزی باشد، مانند بدنه پاسخ یک درخواست در شبکه. کتابخانه‌هایی مانند axios از data استفاده می‌کنند که در این مورد نام معقولی است. حتی در این سناریو، body بیشتر معنی می‌دهد و می‌تواند جایگزین شود. این همان چیزی است که web API fetch در Response خود از آن استفاده می‌کند.از کلمات کامل استفاده کنیدمانند دیگران سیستم مغزم همیشه به من می‌گوید میانبرها را بردار تا کار من زودتر تمام شود. وقتی صحبت از نام گذاری متغیرها می‌شود، میانبرها اغلب به معنای کلمات اختصاری یا نام متغیرهای تک کاراکتری هستند.مانند قبل، بیایید به تابعی نگاه کنیم که از این قانون پیروی نمی‌کند:function totBal(accts) {
  let tot = ۰;
  for (let i = ۰; i &lt; accts.length; i++) {
    tot += accts[i].bal;
  }

  return tot;
}در اینجا باید به ذهن خود فشار بیاوریم تا بتوانیم حدس بزنیم accts به معنای accounts و tot به معنای total است، اما نمی‌توانیم با یک نگاه کد را پردازش کنیم.استثناهااختصارات معمول در این حوزه بر فرم طولانی آنها ترجیح داده می‌شود (به عنوان مثالURL ، API ، CSS و موارد دیگر).از کلمات ترکیبی طولانی استفاده نکنیدContainer و Wrapper فقط در رابطه با چیزی که در آن قرار می‌گیرند معنی دارند. مسئله این است هر کامپوننتی که عنصر پایه نباشد، حاوی کامپوننت دیگری است. سرانجام شما در موقعیت نامناسبی قرار می‌گیرید و MyComponentContainerContainer را نامگذاری می‌کنید. در مورد Wrapper نیز همین مورد وجود دارد.استثناهادر بعضی موارد، این کلمات ترکیبی و طولانی می‌توانند معنی قابل توجهی داشته باشند. الگوی رایج در کامپوننت‌های کلاس  الگوی presentation/ container است. container در این حالت ممکن است یک کامپوننت را نشان دهد که state را در کامپوننت presentation مدیریت می‌کند. فقط مطمئن شوید که همیشه از آن برای این منظور استفاده کنید.از غلط املایی پرهیز کنیدغلط املایی کلمات مشکلاتی ایجاد کرده و جستجوی کد شما را دشوارتر می‌کند. نادیده گرفتن اشتباه تایپی به راحتی انجام می‌شود، اما داشتن املای درست برای همه موارد موجود در پایگاه کد دنیایی از تفاوت را ایجاد می‌کند. به ویژه هنگام تلاش برای یافتن یا جایگزین کردن یک مورد.به کار گرفتن همه قوانینبا استفاده از همه قواعدی که تا اینجا گفته شد به طور همزمان، تابع زیر را دریافت می‌کنیم:function getAccountsTotalBalance(accounts) {
  let totalBalance = ۰;
  for (let accountIndex = ۰; accountIndex &lt; accounts.length; accountIndex++) {
    totalBalance += accounts[accountIndex].balance;
  }

  return totalBalance;
}هرچند ممکن است AccountIndex در مقابل i طولانی باشد، اما بقیه تابع بسیار واضح‌تر به نظر می‌رسد. getAccountsTotalBalance به طور کامل هدف تابع را اعلام می‌کند و پیشوند get نشان می‌دهد که منجر به ایجاد mutation نخواهد شد. ارزش دارد که توسعه دهنده کد در ازای منافع خواننده تلاش بیشتری را انجام دهد. خودتان نیز در آینده وقتی کد را ببینید، از این کار قدردانی خواهید کرد.اگر نگران طول خط هستید، از ابزاری مانند Prettier برای قالب‌بندی خودکار کد استفاده کنید.جمع‌بندیهدف از شکل‌گیری این قوانین، معنی دادن به کدی است که برای آیندگان می‌نویسیم. مواردی را که برای متن شما مناسب هستند پیدا کنید و اگر هر کدام از این قوانین شما را دچار مشکل می‌کند، آن را تغییر دهید یا کنار بگذارید. تنظیم قوانین در تیم به برقراری ارتباط اعضا با شما کمک بهتری می‌کند و به معنای مخالفت با اعضای تیم یا سخت‌گیری در تیم نیست.لطفاً هنگام نامگذاری متغیرها، توابع، کلاس‌ها و … قوانین دیگری را که دنبال می‌کنید به اشتراک بگذارید یا اگر با هر یک از قوانین اینجا مخالف هستید، نحوه تغییر آنها را به ما اطلاع دهید.</description>
                <category>مهدی قوسیان | Mahdi Gosyan</category>
                <author>مهدی قوسیان | Mahdi Gosyan</author>
                <pubDate>Wed, 27 Jan 2021 14:19:48 +0330</pubDate>
            </item>
            </channel>
</rss>