<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های Mohammad Keshavarz</title><link>https://virgool.ir/feed/@m.keshavarz.ch</link><description></description><language>fa</language><pubDate>2026-11-10 14:58:24</pubDate><image><url>https://files.virgool.ir/upload/users/2361500/avatar/avatar.png</url><title>Mohammad Keshavarz</title><link>https://virgool.ir/@m.keshavarz.ch</link></image><item><title>چالش ها و تعامل با مدیر نو پا</title><link>https://virgool.ir/@m.keshavarz.ch/novice-manager-challenges-lzffkfrwib93</link><description>وقتی سالها توی یک تیم کار میکنی، هر چند وقت یه بار یه مدیر تازه از راه میرسه. کسی که تازه روی اون صندلی نشسته و هنوز خودش هم نمیدونه قراره چطور نقش جدیدش رو بازی کنه. من تجربه‌ ام رو از این موقعیت‌ ها مینویسم، نه از زاویه مدیر،بلکه از زاویه هم تیمی هایی که باید با این مدیر کار کنیم.معمولا مدیر تازه از دو مسیر میاد، یا از دل خود تیمه و تا دیروز کنارمون مینشسته و حالا یهویی شده مدیرمون. یا از بیرون میاد. یعنی یه نفر رو از شرکت‌های دیگه میارن و میگن این از امروز مدیر شماست. ولی مهم نیست مسیرش چی بوده؛ مهم چالش‌هایی هست که بعدش برای ما ایجاد میشه.مدیری که میخواد همه چیز رو چک کنهبارها دیدم مدیر جدید، مخصوصا اونی که از داخل تیم ارتقا پیدا کرده، انقدر با ریزکارها آشناست که نمیتونه خودش رو کنترل کنه. میخواد همه چیز رو چک کنه، از جزیی ترین مرحله تا ساده‌ ترین تصمیم ها. یه جور مدیریت ذره‌ بینی یا میکرومنیجمنت که آدم رو خسته میکنه. حتی اگر نیتش خوب باشه، حس بی‌ اعتمادی رو منتقل میکنه.اگر قبلا تیم، مدیر سختگیر نداشته، این سبک مثل یه شوک عمل میکنه. به ناگه همه احساس می کنیم داریم زیر ذره‌ بین کار میکنیم.هدف‌گذاری‌ های رویا پردازانهمدیر جدید معمولا دوست داره ثابت کنه آدم توانمندیه. برای همین هدف‌ هایی میزاره که خودش هم ته دلش میدونه واقعی نیست اما برای اثبات خودش و کسب یه سری امتیازها دست به همچین کاری میزنه.مثلاً چند وقتی هست که رشد پایداری در بهبود کیفیت کد یا افزایش کارایی سیستم‌ ها در حد ۱۰ درصد داریم، اما ناگهان هدف افزایش ۲۵ درصدی عملکرد یا کاهش ۵۰ درصدی ریسپانس تایم رو پیش میکشه و هدف میزاره. ما که دستمون توی کار هست و مستقیم با سیستم سروکار داریم، میدونیم که این رقم‌ ها بدون تغییر اساسی در منابع، زمان یا روش و تکنولوژی، خیلی دور از واقعیته. اما اون به خیال خودش میخواد سقف عملکرد رو بزنه.در نتیجه این چنین تصمیم ها جز فشار بی‌خودی، بی‌ اعتمادی، و حس اینکه حرف‌ هاش از جنس واقعیت نیست، دستاوردهایی برای اون و تیم نداره.نقد کردن همه چی فقط برای اینکه بگه من بهترمیکی از مواردی که زیاد دیدم اینه که مدیر فنی جدید، فکر میکنه اگر قبول کنه کارهای قبل خوب بوده، موقعیتش زیر سوال میره. برای همین شروع میکنه به ایراد گرفتن و نقد کردن همه چی، از فرایندها، از روش‌های کار، حتی از چیزهایی که سالها درست کار کرده، فقط برای اینکه بگه &#34;من بهترم&#34;.یه بار یادمه، ما چند تا سرویس حیاتی با Golang داشتیم که سال‌ها با پایداری بالا و وضعیت خوبی داشتن کار میکردن. تیم لید جدید اومد و بدون تحلیل عمیق، گفت: &#34;این استک اصلا برای این مسیله مناسب نبوده! باید همه رو با Python بازنویسی کنیم.&#34; نتیجه این تصمیمش کلی هزینه برای بازنویسی، استخدام نیروهای جدید پایتون کار، و زمانی که تیم قدیمی مجبور شد بره توی یک فرایند طولانی یادگیری و مهاجرت به زبان جدید. کلی هدررفت زمان و انرژی شرکت و تیم.اما ماجرا به همینجا ختم نشد. وقتی اون مدیر از تیم رفت، مدیر بعدی با یه کوه از کدهای عجولانه، مستندات ناقص و یک استک دوپاره شده مواجه شد که حالا باید با دردسرهای خودش سروکله میزد. اون بازنویسی عجولانه، فقط یه ردپای بد از مدیر قبلی بود، نه یک بهبود واقعی.مشاوران عجیب غریببعضی مدیرها از وقتی وارد میشن یه لشگر مشاور با خودشون میارن. یا مدام با یکی بیرون از شرکت مشورت میکنن. مشکل وقتیه که تجربه اون مشاور از بچه‌های خود تیم کمتره، اما چون از بیرونه و اسمش بزرگه، حرفش میشه قانون. این هم باعث میشه انرژی تیم گرفته بشه، هم حس کنیم مدیر به ما اعتماد نداره.برخورد با کسی که فکر میکرد مدیر بعدی باید خودش باشهاین یکی رو از نزدیک زیاد دیدم. همیشه توی تیم یه نفر هست که خیال میکنه حقش بوده مدیر بشه. حالا یه نفر دیگه رو گذاشتن جاش. چنین آدمی کار تیم رو سخت میکنه. یا کارشکنی میکنه، یا مدام ایراد میگیره، یا سعی میکنه ثابت کنه مدیر جدید چیزی بلد نیست.تفویض اختیار یا خیلی زیاد یا خیلی کممدیر تازه معمولا هنوز نمیدونه چقدر باید کارها رو واگذار کنه. یکی همه چی رو ول میکنه و خودش تبدیل میشه به یه نقش ظاهری. یکی هم هیچی رو واگذار نمیکنه و همه باید منتظر بمونن ببینن اون چی میگه و همیشه معطل و چشم به دهان مدیر هستن تا ببین چی میگه. این یکی از سخت‌ترین حالت‌ هاست. چون یا آزاد رها میشی وسط میدان بی‌ قانون، یا تبدیل میشی به ادامه دست و انگشت‌ های مدیر.در نهایت، تجربه من اینه، هر مدیر جدیدی اولش باعث یه مدت بی‌ ثباتی میشه. نه چون آدم بدیه، چون هنوز نمیدونه کیه و چه سبکی براش جواب میده. و ما هم باید بلد باشیم چطور این دوره رو رد کنیم بدون اینکه خودمون و کارمون آسیب ببینیم.</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Sun, 14 Dec 2025 00:07:25 +0330</pubDate></item><item><title>جستجو در سرویس‌های پرترافیک: قسمت دوم</title><link>https://virgool.ir/@m.keshavarz.ch/search-in-high-traffic-services-two-bnwabzthpu7k</link><description>مسیر واقعی یک کلمه تا نتیجه نهاییتو قسمت قبل خیلی کلی از اهمیت سرویس سرچ و ویژگی های کلی و ابزارهای معروفش صحبت کردیم. توی این قسمت با جزئیات بیشتری از مسیری که یک کلمه تا نمایش نتیجه نهایی رو بررسی میکنیم.فرض کن تو اسنپ/تپسی فود هستی، ساعت ۸ شبه و کم کم داره گرسنه ات میشه، تایپ می‌کنی: &#34;پیتزای سیر و استیک نزدیک من&#34;. این یک جمله ساده‌ است، ولی پشتش یک سفر پیچیده و فوق‌العاده سریع تو سیستم‌های توزیع‌ شده، دیتابیس‌ها، کش‌ها، سرچ انجین ها و هوش مصنوعی وجود داره. تو این قسمت از سری مقاله‌ها، میریم تو دل یک سرویس واقعی، نه فقط تئوری، بلکه دقیقاً همون مسیری که یه کلمه طی می‌کنه تا به نتیجه تبدیل بشه. از لحظه‌ای که انگشتمون دکمه Enter رو می‌زنه، تا لحظه‌ای که ۱۰ تا رستوران جذاب با عکس، قیمت و زمان تحویل جلوت ظاهر می‌شه. آخر مطلب هم کل این مسیر رو به صورت یک دیاگرام کلی باهم میبینیم تا بهتر توی ذهنمون بمونه.سفر یک کلمه: از تایپ تا نتیجه (در ۲۰۰ میلی‌ثانیه)جدول مراحل سرچ یک کلمه در یک سرویس آنلاینمرحله به مرحله: تو دل سیستم۱. کلاینت: &#34;پیتزای سیر و استیک نزدیک من&#34; تایپ می‌شهاینجا دقیقا چه اتفاقی می‌افته؟ کاربر حین تایپ، autocomplete می‌بینه (مثل &#34;پیتزای گوشت&#34;، &#34;پیتزای سیر و استیک تهرانپارس&#34;، &#34;پیتزای سیر و استیک زعفرانیه&#34;).خب چرا باید همیچن اتفاقی بیافته؟ برای کاهش تعداد درخواست‌های کامل و افزایش سرعت و بهبود تجربه کاربر در جست و جوی چیزی که میخواد.تو این قسمت برای کلاینت، ابزارهای مختلفی استفاده میشه که در این قسمت اهمیت بالایی نداره چون فقط یک محیط جذاب برای کاربر هست که بتونه سرچ کنه و کارش رو پیش ببره.طراحی این قسمت برای پیشنهادهای سرچ به کاربر میتونه اثرگذاری خوبی روی انتخاب و پیش بینی رفتار کاربر و کاهش تعداد درخواست داشته باشه. به این صورت که دیتای لازم رو از کش بخونه و پردازش دوباره نداشته باشه.۲. Edge: درخواست به نزدیک‌ترین سرور ارسال میشه درخواست از طریق CDN (مثل Cloudflare، ابرآروان) به نزدیک‌ترین منطقه (مثل تهران، دبی یا فرانکفورت) هدایت میشه.چرا داریم اینکارو میکنیم؟ جوابش ساده است، کاهش latency شبکه از ۲۰۰ms به ۲۰ms.خب اینجا بحث یک مقداری میره سمت موضوعات زیرساخت و POP ها و مواردی که توی شبکه مدیریت میشه و اینجا برای سرویس سرچ ساده ای که محلی هست مثل اسنپ/تپسی این موضوعات توی همون محیط باید حل بشه اما برای سرویس های بین المللی مثل Uber یا امثالهم این مورد اهمیت بیشتری پیدا میکنه که بتونه جست و جوها رو در کشورهای مختلف مدیریت کنه.۳. API Gateway: درِ ورودی سیستمدرخواست با JWT Token احراز هویت میشه، Rate Limit هم روی این لایه داریم تا از حملات DDoS جلوگیری بشه (مثلاً ۱۰ درخواست در ثانیه).تو این قسمت به ابزارهایی مثل Kong یا AWS API Gateway با OAuth2 نیاز داریم تا بازهم از ارسال مستقیم درخواست روی سرورهای خودمون جلوگیری کنیم و بتونیم تعداد درخواست های خیلی خیلی زیادی رو مدیریت کنیم.۴. Search Service: مغز جستجویک میکروسرویس اختصاصی، کوئری رو می‌گیره و به بخش‌های مختلف می‌فرسته تا ادامه فرآیند پردازش درخواست جست و جوی کلمه انجام بشه.اهمیت استفاده از میکروسرویس در این قسمت برای جداسازی مسئولیت (Separation of Concerns) هست که سرویس ها بتونن به صورت مستقل کارشون رو پیش ببرن. تو این قسمت موضوع سرعت اهمیت بالایی داره و برای ارتباط بین سرویس ها از gRPC استفاده میشه به دو دلیل! (دلایل دیگه رو خودتون سرچ کنید!)payload  در این نوع ارتباطی نسبت به REST/JSON کمتره و چون ما داریم در حد چند کلمه رو منتقل میکنیم و از طرف دیگه Real-Time هسا، این نوع ارتباط برامون مناسبتره.۵. Query Parser: &#34;نزدیک من&#34; یعنی چی؟عبارت &#34;نزدیک من&#34; با موقعیت GPS کاربر (از کلاینت) ترکیب میشه و از ترکیب و تشخیص این دیتا محل مورد نظر کاربر مشخص میشه. &#34;پیتزای سیر و استیک&#34; به توکن‌های [&#34;پیتزا&#34;, &#34;سیر&#34;, &#34;استیک&#34;] تجزیه می‌شه چون میخواییم intent و entity رو به دست بیاریم. تو این لایه Custom NLP Parser + Synonym Dictionary (مثل &#34;پیتسا&#34; = &#34;پیتزا&#34;) برای پردازش و پیدا کردن نیت کاربر از این کلمه ای که سرچ کرده استفاده میشه.یک نمونه جدول intent های قابل تشخیصیک نکته مهم اینجا اینکه این قسمت در سرویس های ایرانی با همون pop-up اولیه یا پروفایلی که شما توی اون سرویس دارید پر میکنید ازش گرفته میشه، مثل آدرس هایی که برای ارسال سفارش توی سیستم ثبت کردید و همینطور قسمت فیلتر شهر و منطقه مورد نظر برای مشاهده خدمات دهنده های همون منطقه.۶. Geo Service: تبدیل مکان به سلولموقعیت کاربر به سلول S2 (از Google S2 Library) تبدیل می‌شه. سلول‌های اطراف (مثلاً شعاع ۵ کیلومتر) محاسبه می‌شن.خب این جا از ویژگی های کافکا برای آپدیت کردن موقعیت رستوران ها بر اساس همون لوکیشن کاربر که به دست آوردیمش یا خودش بهمون داده استفاده میکنیم.(Google S2 + Kafka Stream)سرویس S2.dev رو پیشنهاد میکنم مطالعه کنید.۷. کش (Cache): ۸۰٪ درخواست‌ها از اینجا جواب می‌گیرنلایه خیلی مهم بسیاری از سرویس ها کش هست، تو این قسمت سیستم چک میکنه: &#34;آیا این جستجو تو ۵ دقیقه اخیر انجام شده؟&#34; اگه جواب بله بود پس میره جواب رو از Redis میخونه و برمیگردونه.۸. Search Engine: قلب جستجوتو مرحله قبلی  اگه کش نبود، کوئری به OpenSearch (یا Lucene) میره. ایندکس منوها (میلیون‌ها آیتم) اسکن میشه. این سرویس سرعت میلی‌ثانیه‌ای در داده‌های عظیم داره و قابلیت های ویژه اون برای سرچ پرکاربرده.ساختار ایندکس Live Index: داده‌های ۱ ساعت اخیر (در حافظه)Snapshot Index: داده‌های ۲۴ ساعت (روی دیسک)Base Index: داده‌های قدیمی (آرشیو)۹. ML Ranker: چرا این رستوران اول اومد؟ ۱۰۰ نتیجه اولیه از Lucene میاد، یک مدل ML (TensorFlow) اونا رو بر اساس یک سری معیارهایی دوباره رتبه‌بندی میکنه. معیارها:فاصلهرتبه رستورانسابقه سفارش کاربر (کاربر قدیمیه یا جدید)زمان تحویل پیش‌بینی‌شدهاین کار باعث افزایش relevance و conversion rate میشه یعنی همون چیزی که کاربر سرچ کرده تا بهش برسه. این بخش تو فروشگاه های خیلی بزرگ مثل آمازون یا دیجیکالا اهمیت زیادی داره چون خیلی مهمه که وقتی کاربر سرچ میکنه &#34;شیر&#34; منظورش چیه؟ آیا سرویس سریع میخواد و باید بفرستیمش سمت خوراکی ها و سوپرمارکت یا اینکه نه دنبال شیرآلات میگرده و پرواضحه که این دوتا سرویس کاملا باهم متفاوت هستن از شاپ/وندور و قیمت ها بگیر تا نحوه ارسال اون سفارش.۱۰. Response: نتیجه نهاییخب رسیدیم به مرحله آخر، تو اینجا ۱۰ نتیجه برتر با عکس، قیمت، زمان تحویل و دکمه &#34;سفارش&#34; برگردونده میشه و منتظر میشیم تا کاربر سفارشش رو بزاره و این سرویس زنده بمونه! :)دیاگرام مسیر (ساده)دیاگرام کلی از مسیر و مراحل سرچ یک کلمه</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Fri, 07 Nov 2025 15:15:05 +0330</pubDate></item><item><title>جستجو در سرویس‌های ترافیک بالا - قسمت اول</title><link>https://virgool.ir/@m.keshavarz.ch/search-in-high-traffic-services-one-nhenarqweedq</link><description>اهمیت و چالش‌های جستجوتصور کن تو یه اپ مثل Uber Eats هستی، گرسنه‌‌ات هست و دنبال یه پیتزای وگان خوشمزه تو استانبول می‌گردی. یا تو یه تاکسی آنلاین مثل اسنپ، می‌خوای یه راننده نزدیک پیدا کنی که تو ترافیک گیر نیفته. حالا یه فروشگاه آنلاین مثل دیجی‌کالا رو در نظر بگیر که می‌خوای یه گوشی با یه بودجه خاص پیدا کنی. تو این سرویس‌ها، جستجو قلب تپنده‌ی سیستمه. اگه درست کار نکنه، کاربر یه ثانیه صبر نمی‌کنه و می‌ره سراغ رقیب! تو این مقاله، که اولین قسمت از یه سری چندقسمتیه، می‌خوام ساده و عامیانه درباره اهمیت جستجو تو سرویس‌های پرترافیک(مثل سفارش تاکسی، غذا و فروشگاه‌های آنلاین) حرف بزنم، چالش‌هاش رو باز کنم و یه نگاه کلی به ابزارهای مرتبط بندازم.چرا جستجو تو این سرویس‌ها اینقدر مهمه؟جستجو تو سرویس‌های پرترافیک مثل Uber، Uber Eats یا Amazon فقط پیدا کردن یه چیزی نیست، یه تجربه کامل برای کاربره و این مورد اهمیت خیلی بالایی داره. در واقع جستجو یه فرآیند اطلاعاتیه که باید کاربر رو سریع و دقیق به هدفش برسونه. مثلاً تو اوبر یا اسنپ، وقتی آدرس می‌زنی، سیستم باید موقعیتت رو با GPS چک کنه، راننده‌های نزدیک رو پیدا کنه، ترافیک و حتی فیلترها و اولویت های تو رو (مثل ماشین لوکس یا اقتصادی) در نظر بگیره و در کمتر از یه ثانیه جواب بده. خب اینجا یه تأخیر کوچیک داشته باشیم چی میشه؟ واضحا کاربر می‌ره سراغ رقیب!تو سرویس‌های غذا مثل Uber Eats یا اسنپ فود، جستجو باید میلیون‌ها منو رو اسکن کنه، فیلترهای قیمت، نوع غذا یا فاصله رو اعمال کنه و حتی پیشنهاد شخصی بده. مثلاً اگه قبلاً پیتزا سفارش دادی، سیستم باید بفهمه و پیتزای وگان رو بالاتر نشون بده. از لحاظ رفتار کاربر، کاربرهای امروزی انتظار نتایج &#34;هوشمند&#34; دارن، نه یه لیست ساده، بلکه چیزی که حس کنه برای اونا ساخته شده و حس سفارشی و خاص بودن داشته باشه. تو فروشگاه‌های آنلاین مثل دیجیکالا،سرویس جستجو باید بین میلیاردها محصول بگرده، نتایج رو بر اساس خریدهای قبلی یا تخفیف‌ها مرتب کنه.(حتی اگر نسخه های پیشرفته تر رو هم در نظر بگیریم باید جستجوی صوتی و پیچیدگی هاش رو هم حساب کنیم)چرا این موضوع انقدر حائز اهمیت و توجه است؟ چون این سرویس‌ها پر ترافیک یا درخواست هستن (یعنی هر ثانیه هزاران یا حتی میلیون‌ها جستجو دارن).تو همچین سیستم‌هایی، جستجو باید مقیاس‌پذیر باشه تا تو پیک‌های ترافیک (مثل Black Friday یا تخفیف عید برای فروشگاه ها یا ساعت وعده های غذایی مثل شام و نهار برای Uber Eats و اسنپ و تپسی فود) قفل نکنه. اگر تجربه دیدن دراپ کاربرها در ساعت های خاص رو داشته باشید اهمیت این موضوع رو کامل حس کردید.چالش‌های کلیدی جستجو تو سرویس‌های پر ترافیکجستجو تو این سرویس‌ها کا رچندان ساده ای نیست و پر از چالش هاییه که هر قسمتش پیچیدگی های خاص خودش رو داره. بیایم چندتا از مهم‌ترین هاش رو با هم ببینیم:حجم عظیم داده‌ها:تو Uber Eats، سیستم باید میلیون‌ها آیتم منو، رستوران و نظرات رو ایندکس کنه. تو Amazon، میلیاردها محصول با ویژگی‌های مختلف (قیمت، برند، تخفیف) هست. در معماری اطلاعات چالش اصلی اینه که باید یه ایندکس سریع بسازی که داده‌های بزرگ رو سریع اسکن کنه.به عنوان نمونه، تو اسنپ و تپسی، جستجو باید موقعیت راننده‌ها رو که هر ثانیه تغییر می‌کنه، تو یه نقشه عظیم جغرافیایی پیدا کنه.نیاز به دیتای لحظه ای (Real-Time):پر واضحه که داده‌ها باید به‌روز باشن. مثلاً تو تپسی یا اسنپ فود، اگه رستورانی بسته‌ست یا موجودی یه غذا تموم شده، نباید تو نتایج بیاد. مخصوصا در ساعت های پیک (زمان هایی که ریکوئست زیاد هست مثل ناهار) رستوران وقتی در لحظه درخواست اتمام موجودی یا بسته بودن رو میزنه باید در کسری از ثانیه ثبت بشه تا کاربر غذا رو سفارش نده و در ادامه وارد مسیرهای برگشت وجه نشه. در واقع این نیاز به &#34;near-real-time indexing&#34; داره که خیلی پیچیده‌ست.همچین نمونه ای رو توی داکیومنت الستیک سرچ میتونیم بخونیم و بعدا هم میریم سراغش.اگر بخواییم دوباره از اسنپ و تپسی مثال بزنیم، اگه موقعیت راننده ۱۰ ثانیه پیش آپدیت شده باشه، ممکنه دیگه درست نباشه و مسیرش به طور کلی تغییر کرده باشه.شخصی‌سازی و دقت:کاربرا انتظار دارن نتایج به اونا ربط داشته باشه. جستجو باید رفتار کاربر (مثل خریدهای قبلی) و مواردی زمینه ای (مثل مکان یا ساعت) رو در نظر بگیره. این موضوع زمان میتونه برای Q-commerce ها جذابیت داشته باشه که محصولات تاریخ انقضا و در زمان های مشخصی ممکن مصرف بشن. موقع خرید &#34;لپ تاپ&#34; تو دیجیکالا، سیستم بر اساس تاریخچه‌ ممکنه مدل‌های گیمینگ رو بالاتر بیاره یا حتی بر اساس سبد خرید های قبلی شاید حدس بزنه که گزینه های اقتصادی رو در اول لیست پیشنهاد بده.تنوع داده‌ها:جستجو باید با داده‌های چندزبانه، جغرافیایی و حتی صوتی کار کنه. سرچ در سرویس های سفارش غذای آنلاین، کاربر ممکنه با فارسی، انگلیسی یا حتی لهجه‌های محلی جستجو کنه. نمونه خیلی معروفش برای ما تفاوت حروف عربی و فارسی در سرچ یک کلمه مشخص یا تلفظ‌های مختلف یا کلمات مترادف (مثل &#34;پیتزا&#34; و &#34;پیتسا&#34;) که سیستم باید بتونه درست تشخیص بده.مقیاس‌پذیری تو پیک ترافیک:تو زمان‌های شلوغ (مثل ساعت ۸ شب برای غذا یا تخفیف‌های ویژه فروشگاه آنلاین)، تعداد درخواست‌ها می‌تونه ۱۰ برابر بشه.سیستم باید برای این پیک‌ها آماده باشه. تو کمپین های فروش و ایونت های مختلف باید میلیون‌ها جستجو رو تو زمان خیلی کوتاهی هندل کنه مخصوصا اگر کالای خاصی به عنوان کالای هدف برای گروه های مشتری در نظر گرفته شده باشه.ابزارهای اولیه جستجو: در یک نگاه سریعبرای حل این چالش‌ها، سرویس‌های با ترافیک بالا از ابزارهای خاصی استفاده می‌کنن. تو این قسمت، فقط یه معرفی کوتاه می‌کنیم (قسمت‌های بعدی عمیق‌تر می‌شن):Apache Luceneیک کتابخونه جاوا برای ایندکس کردن و جستجوی متنی است. Lucene پایه بسیاری از سیستم‌های جستجوی مدرن محسوب میشه چون:سرعت ایندکس کردن بالایی دارهاز کوئری‌های پیچیده پشتیبانی میکنهقابلیت جستجوی فازی (Fuzzy Search) و پردازش زبان طبیعی دارهUber از Lucene برای ایندکس کردن موقعیت راننده‌ها استفاده می‌کنه.Elasticsearchیک موتور جستجوی توزیع‌شده بر پایه Lucene که برای داده‌های بزرگ طراحی شده. قابلیت‌های کلیدی این سرویس شامل:پشتیبانی از جستجوی لحظه ای (Real-time)قابلیت مقیاس‌پذیری افقیپشتیبانی از جستجوهای مکانی (Geo-search)Uber Eats از Elasticsearch برای جستجوی رستوران‌ها تو مناطق خاص استفاده کرد.OpenSearchیک فورک از Elasticsearch که متن‌بازتر است و جامعه توسعه‌دهنده قوی‌تری داره. از مزایاش میشه گفت:سازگاری کامل با Elasticsearchانعطاف‌پذیری بیشتر در سفارشی‌سازیمناسب برای سرویس‌های پرترافیکUber Eats به OpenSearch مهاجرت کرد تا جستجوی real-time رو بهتر کنه.قسمت‌های بعدیاین مقاله فقط یه مقدمه بود. تو قسمت‌های بعدی، عمیق‌تر می‌ریم تو جزئیات.منابع اصلی:Information Architecture: For the Web and Beyond (فصل Search Systems) – برای اصول پایه جستجو.Designing the Search Experience (بخش User Behavior) – برای رفتار کاربر و طراحی تجربه.The Art of Scalability (فصل Architecture for Scalability) – برای مقیاس‌پذیری سیستم‌ها</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Tue, 21 Oct 2025 21:48:05 +0330</pubDate></item><item><title>جایگزینی تدریجی سیستم‌های قدیمی بدون دردسر (الگوی Strangler Fig)</title><link>https://virgool.ir/@m.keshavarz.ch/strangler-fig-pattern-kle274kswktu</link><description> جایگزینی تدریجی سیستم‌های قدیمی بدون دردسرتصور کن یه درخت قدیمی و پوسیده تو باغت داری، نمی‌تونی یهو قطعش کنی چون کل باغ رو به هم می‌ریزه. به جاش، یه درخت جدید (مثل Strangler Fig تو جنگل‌های استرالیا) رو می‌کاری که به تدریج دورش می‌پیچه، شاخه‌هاش رو می‌پوشونه، و آخرش درخت قدیمی رو کامل جایگزین می‌کنه. بدون اینکه باغت یه لحظه بی‌درخت بمونه. حالا اینو اگر ببریمش تو دنیای نرم‌افزار، الگوی Strangler Fig Pattern همون روشه برای جایگزینی سیستم‌های قدیمی (legacy) با کد جدید، بدون اینکه سیستم از کار بیفته یا کاربرها متوجه بشن. بر اساس مقاله  Chris Richardson در Microservices.io، این الگو بخشی از مدرن‌سازی تدریجیه که کمک می‌کنه سیستم‌های مونولیتیک رو کم‌کم به سرویس‌های مستقل تبدیل کنی.چرا سیستم‌های قدیمی مثل درختِ پوسیده‌ هستن؟سیستم‌های legacy (اونایی که سال‌ها پیش نوشته شدن) اغلب مثل یه درخت کهنه‌ان، کار می‌کنن، اما نگهداری‌شون گرونه، تغییر دادن‌شون خطرناکه، و مقیاس‌پذیری‌شون محدوده. اگه بخوای یهو همه چیز رو عوض کنی (مثل Big Bang Migration)، ریسک downtime و از دست دادن داده‌ها زیاده – و ممکنه پروژه‌ت رو به خاک سیاه بنشونی!الگوی Strangler Fig (مقاله مارتین فاولر رو حتما بخونید) راه‌ حل چنین مسئله ای هست. یه سیستم جدید رو کنار قدیمی می‌سازی، ترافیک رو کم‌کم به جدید منتقل می‌کنی، و قدیمی رو به تدریج خاموش می‌کنی. مثل همون درخت Strangler Fig که درخت میزبان رو آروم آروم می‌خوره!الگوی Strangler Fig چطور کار می‌کنه؟این الگو مثل یه پروکسی (واسط) عمل می‌کنه، یه لایه جدید (Strangler) رو جلوی سیستم قدیمی میزاریم که درخواست‌ها رو مدیریت کنه. بعد، بخش به بخش، کد قدیمی رو با جدید جایگزین می‌کنیم. این الگو بخشی از Architectural Decompositionهست، یعنی تجزیه سیستم به اجزای کوچیک‌تر، بدون اینکه کل سیستم رو از نو بسازیم.مراحل کلی:ساخت لایه Strangler: یه پروکسی (مثل API Gateway یا یه اپلیکیشن ساده) باید ساخته بشه که همه درخواست‌ها رو بگیره و به سیستم قدیمی بفرسته.مثلاً: درخواست‌های کاربرها به legacy backend فرستاده بشه.جایگزینی تدریجی: بخش‌های کوچیک یکی یکی با کد جدید جایگزین بشن. مثلاً اول &#34;مدیریت کاربر&#34; جدید ساخته بشه، ترافیکش رو به سرویس جدید ببریم، و قدیمی رو خاموش کنیم.انتقال کامل: وقتی همه بخش‌ها جدید شدن، Strangler رو هم حذف کنیم.نکته: همیشه fallback به قدیمی داشته باشیم تا اگه سرویس جدید مشکل داشت، سریع بتونیم برگردیم.مثلا بیایید یک سیستم فروشگاهی قدیمی رو درنظر بگیریم. Strangler اول درخواست‌های لیست محصولات رو می‌گیره و به legacy می‌فرسته. بعد، یه سرویس جدید برای محصولات می‌سازیم، ترافیک رو کم‌کم (مثل ۱۰٪ اول) به جدید می‌بریم، و وقتی مطمئن شدیم، کامل منتقل می‌کنیم. اینطوری میزان دان تایم کاهش پیدا میکنه و از سرویس جدید هم (از این نظر) اطمینان پیدا میکنیم.مزایای الگوی Strangler Figبدون downtime: سیستم همیشه آنلاینه، چون قدیمی رو آروم آروم خاموش می‌کنیم.ریسک کم: بخش‌های کوچیک رو تست می‌کنیم، اگه مشکلی بود، برمی‌گردیم به قدیمی.بهبود تدریجی: می‌تونیم معماری های جدیدی (مثل میکروسرویس‌ها) رو بدون بازنویسی کل سیستم اضافه کنیم.مناسب برای legacy: برای سیستم‌های قدیمی که مستندات ندارن یا تست‌شون سخته، گزینه خیلی خوبیه.انعطاف‌پذیری: می‌تونیم از مونولیت به ماژولار مونولیت یا میکروسرویس‌ها بریم با دردسرهای خیلی کمتر.معایب و چالش‌هازمان‌بر: ممکنه ماه‌ها یا سال‌ها طول بکشه، چون باید همه چیز تست بشن (مخصوصا سناریوهای خاص که بعدا سیستم و سرویس ها رو دست خوش تغییرات برای شرایط خاص میکنه).پیچیدگی موقت: Strangler خودش یه لایه اضافیه که باید مدیریت بشه. یعنی داریم دوتاسیستم رو همزمان نگهداری میکنیم و یکیشون درحال توسعه است.مدیریت ترافیک: باید مطمئن بشیم که ترافیک درست تقسیم میشه (مثلا با feature flags).تست سخت: تست همزمان قدیمی و جدید می‌تونه پیچیده باشه.یک مثال جذابتوی سایت Microservices.io یک مثالی از فروشگاه آنلاینی میزنه که یک legacy با ۵۰۰K خط کد، به سه تا ماژول (کاربران، سفارشات، موجودی) تقسیم شد. Strangler پروکسی استفاده کردن و ترافیک رو ۲۰٪ به جدید رسوندن، تو این حالت downtime صفر داشتن و همینطور سرعت ۳۰٪ بهتر شد. حتما پیشنهاد میکنم این مطلب رو توی سایتش پیدا کنید و بخونید.الگوی Strangler Fig مثل یه درخت هوشمند عمل می‌کنه، قدیمی رو آروم آروم جایگزین می‌کنه بدون اینکه باغت (سیستم) از کار بیفته. اگه با سیستم قدیمی دست و پنجه نرم می‌کنید، از DDD برای مرزبندی ها، تست‌های قوی، و پروکسی ساده شروع کنید. این روش نه تنها سیستم رو زنده نگه می‌داره، بلکه راه رو برای آینده (مثل میکروسرویس‌ها) باز می‌کنه تا بعدا تصمیم بهتری برای آینده ی سیستم بگیرید.</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Sun, 05 Oct 2025 01:39:33 +0330</pubDate></item><item><title>الگوی Request/Reply در سرویس‌های RESTful</title><link>https://virgool.ir/@m.keshavarz.ch/request-reply-pattern-jrnkdjrcckpq</link><description>الگوی Request/Reply (درخواست/پاسخ) یکی از الگوهای اصلی در طراحی سرویس‌های RESTful هست که توش یه کلاینت یه درخواست (request) به یه سرور می‌فرسته و منتظر یه پاسخ (reply) می‌مونه. این الگو تو سیستم‌های توزیع‌شده خیلی رایجه و پایه‌ ی خیلی از APIهای REST است. این الگو سادگی و وضوح خوبی داره، اما اگه بد استفاده بشه، می‌تونه مشکلاتی مثل تأخیر بالا یا کوپلینگ تنگاتنگ درست کنه. تو این مطلب میریم سراغ اینکه چطور تو سرویس‌های RESTful کار می‌کنه، مزایا و معایبش چیه، و چطور میشه درست ازش استفاده کنی.الگوی Request/Reply چیه؟اگر تا به حال فقط یک بار کد مربوط به API زده باشی یا تو مسیر یادگیری برنامه نویسی باشی قطعا از این معماری استفاده کردی، الگوی Request/Reply همون چیزیه که تو اکثر APIهای REST میبینیم: یه کلاینت (مثل مرورگر یا یه اپ) یه درخواست HTTP (مثلا GET یا POST) به سرور می‌فرسته، سرور پردازش می‌کنه و یه پاسخ (مثل JSON یا XML) برمی‌گردونه. این الگو ساده‌ست و مثل یه مکالمه‌ی دوطرفه عمل می‌کنه: تو سوال می پرسی،بعدش جواب می‌ گیری. این الگو برای خیلی از سناریوها عالیه، ولی محدودیت هایی داره که تو سیستم های بزرگ و توزیع شده دردسر درست میکنه.چطور تو سرویس‌های RESTful کار می‌کنه؟تو یه سرویس RESTful، الگوی Request/Reply اینطور پیاده میشه:کلاینت درخواست می‌فرسته: مثلاً یه درخواست GET به /api/users/123 برای گرفتن اطلاعات یه کاربر.سرور پردازش می‌کنه: سرور درخواست رو می‌گیره، دیتابیس یا منطق داخلی رو چک و یه پاسخ آماده میکنه.پاسخ برمیگرده: سرور یه پاسخ HTTP (مثل کد 200 و یه JSON) به کلاینت می‌ فرسته.کلاینت نتیجه رو می‌ گیره: کلاینت پاسخ رو پردازش می‌ کنه (مثلاً اطلاعات کاربر رو نشون می‌ده).مثال ساده:ریکوئست: GET /api/orders/456ریسپانس:این الگو به خاطر سادگیش تو اپلیکیشن‌های وب، موبایل، و حتی میکروسرویس‌ها خیلی پراستفاده‌ست.مزایای الگوی Request/Reply تو RESTسادگی: همه‌چیز سرراسته، یه ریکوئست می‌فرستی، یه جواب می‌گیری. و تقریبا تمام دولوپرها راحت باهاش کار میکنن.مثال: برای یه اپ فروشگاه، گرفتن لیست محصولات با یه GET ساده‌ست.وضوح: مدل Request/Reply با HTTP (مثل کدهای 200، 404) خوب جور درمیاد و همینطور قابل فهمه.پشتیبانی: ابزارهای REST (مثل Postman یا Swagger) برای این الگو بهینه شدن.مناسب برای عملیات فوری: اگه نیاز به ریسپانس سریع باشه (مثل چک کردن موجودی انبار)، این الگو عالیه.معایب و مشکلات الگوی Request/Replyکوپلینگ تنگاتنگ: کلاینت و سرور باید همزمان فعال باشن و هماهنگ کار کنن (یعنی sync باشن و در لحظه درخواست فرستاده بشه)، که تو سیستم‌های توزیع‌شده می‌تونه مشکل‌ ساز بشه.مثلا اگه سرور داون باشه، کلاینت گیر می‌کنه و جوابی نمیگیره.تأخیر بالا (Latency): تو سیستم‌های بزرگ که چند سرویس با هم در ارتباط هستن، کال کردن های پشت‌سرهم (chatty calls) می‌تونه باعث کندی بشه.مثال: برای یه سفارش، اگه نیاز باشه ۵ سرویس جداگانه فراخوانی بشن، تأخیر زیاد میشه.مقیاس‌پذیری محدود: چون درخواست‌ها سنکرونن (همزمان)، اگه تعداد درخواست‌ها زیاد بشه، سرور ممکنه قفل کنه.مدیریت خطاها: اگه سرور جواب نده یا خطا بده، کلاینت باید خودش هندل کنه، که پیچیده‌ست.نکته خیلی مهمه این هست که تو سیستم‌های پیچیده، استفاده بیش از حد از Request/Reply می‌تونه خودش به آنتی پترن &#34;Distributed Monolith&#34; منجر بشه.بهترین نمونه ها برای استفاده درستطراحی API های ساده و واضح:استانداردهای REST مثل روش‌های HTTP (GET، POST، PUT) درست استفاده بشه.مثلاً: برای گرفتن داده کاربر، از GET /users/{id} استفاده بشه، نه یه POST پیچیده.کاهش تعداد فراخوانی‌ ها:داده‌های مرتبط تو یه درخواست جمع بشن (از GraphQL یا BFF میشه کمک گرفت).مثلاً: به جای چند GET برای سفارش و محصولاتش، یه endpoint ترکیبی بسازیم.مدیریت خطاها:از کدهای HTTP درست (مثل 400 برای خطای کلاینت، 500 برای خطای سرور) استفاده بشه.یه مکانیزم retry با circuit breaker (مثل Resilience4j) اضافه کنیم.کشینگ (Caching):برای درخواست‌های پرتکرار، از کش (مثل Redis) استفاده کنیم تا بار سرور کم بشه.مثلاً: لیست محصولات پرطرفدار تو Redis نگه داشته بشه.مستندسازی خوب:APIها با ابزارهایی مثل Swagger یا OpenAPI مستند بشن تا تیم‌ها راحت‌تر کار کنن.مثلاً: مشخص بشه که /orders چه پارامترهایی می‌گیره و چه پاسخی میده.ترکیب با الگوهای Async:برای سناریوهایی که نیاز به پاسخ فوری نیست، از الگوهای event-driven (با Kafka) کنار Request/Reply استفاده بشه.مثلاً: برای ثبت سفارش، روش Request/Reply پیاده بشه، ولی برای آپدیت و اطلاع به انبار، event ارسال بشه.</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Thu, 02 Oct 2025 00:41:05 +0330</pubDate></item><item><title>5 اشتباه رایج در میکروسرویس ها</title><link>https://virgool.ir/@m.keshavarz.ch/5-common-mistakes-in-microservice-migration-gceqt6o9ymzb</link><description>اشتباهات رایج در مهاجرت به میکروسرویس‌هاخیلی از شرکت‌ها با شنیدن مزایای میکروسرویس‌ها (مثل مقیاس‌پذیری و سرعت توسعه بیشتر) سریع می‌گن: &#34;بریم سمت میکروسرویس!&#34; اما بدون برنامه‌ریزی، این کار می‌تونه به یک کابوس واقعی تبدیل بشه! طبق آمار، ۶۲٪ از سازمان‌ها با مدیریت وابستگی‌های بین سرویس‌ها مشکل دارن.لینک منبع این حرف: https://www.opslevel.com/resources/challenges-of-implementing-microservice-architectureچرا مهاجرت به میکروسرویس‌ها شکست می‌خوره؟تقلید کورکورانهچون شرکت‌های بزرگ استفاده می‌کنن، ما هم بریم سمت میکروسرویس! این ذهنیت اشتباهیه که عموم برنامه نویس ها و تصمیم گیرهای تکنولوژی در تیم های مختلف دارند و کمتر پیش اومده که برن سراغ معماری ها و راه حل هایی که متناسب با مسئله و نیاز کسب و کار باشه. خیلی ساده بخواییم نگاه کنیم این حجم از حرکت به سمت میکرو سرویس حتی برای شرکت های کوچیک اصلا منطقی به نظر نمیاد و جز چالش و دردسر در پیاده سازی و نگهداری برای شرکت های متوسط و کوچیک چیزی نداره.عدم طراحی درستوقتی تعریف دومین ها در پیاده سازی سرویس ها دقیق و با مرزهای مشخص نباشه، سرویس‌ها به هم وابسته می‌شن (به صورت غیر اصولی) و سیستم تبدیل به یک آش شله قلمکار توزیع‌شده می‌شه. مرحله ای پیش از پیاده سازی رو باید جدی گرفت چون این دقیقا همون نقشه ای هتس که قراره طبق اون پیاده سازی ها انجام بشه و بین سرویس های هر تیم هماهنگی و مسیر درست رو ایجاد کنه.فراموش کردن فرهنگ تیمیتوپولوژی تیم ها و بلوغ سازمان یا شرکتی که قراره بره سراغ میکروسرویس اهمیت بالایی داره و تاثیر مستقیمی روی عملکرد تیم ها و محصول نهایی میزاره. میکروسرویس فقط معماری نیست بلکه روش کار تیم‌ها رو هم عوض می‌کنه و نحوه ارتباط بین اعضای تیم و همچنین بین تیم های مختلف رو هم تحت تاثیر قرار میده. مدل فعالیت و کار در معماری درست میکروسرویس تفاوت های قابل توجهی نسبت به سایر معماری ها داره که همین خودش نیازمند آشنایی با این نوع از ارتباط و مهارت ارتباطی درست و مناسب هست.اشتباهات کلیدی در پیاده‌سازی میکروسرویس‌ها۱. شتاب زده وارد عمل شدنخیلی از تیم‌ها بدون بررسی آمادگی سازمان، مهارت تیم یا زیرساخت‌های لازم، سریع به سمت میکروسرویس می‌روند و در نتیجه این تصمیم عجولانه و ناپخته، دچار دردسرهایی میشن که حل کردنشون زمان و منابع شرکت و تیم ها رو از بین میبره. از نشونه هایی که میشه تشخیص داد تصمیم میکروسرویس نادرست بوده:افزایش دردسرهای عملیاتیقطعی‌های مکرر سرویس‌هااعصاب‌خردی و آشفتگی برنامه نویس هابرای چنین تصمیمی با اثرگذاری بلند مدت، اول بهتره آمادگی تیم و سازمان رو ارزیابی کنیم بعد تصمیم بگیریم. برای شروع و با یک تیم کوچیک، انتخاب مونولیت قطعا هوشمندانه تر از یک میکروسرویس هست.۲. تقسیم‌بندی اشتباه سرویس‌هاسیستم بدون درنظرگرفتن مرزهای دومین کسب‌وکار (Domain Boundaries) به سرویس‌های خیلی کوچیک تقسیم میشه و موقع پیاده سازی تازه اشتباهات و وابستگی های بیش از حد، مشخص میشن و اینجا همون نقطه ای هست که کلی سرویس کوچیک با کاربرد های خیلی جزئی وجود داره که تفکیک کردنشون تا این حد ریز کار اشتباهی بوده.خب اینجا این سوال پیش میاد که چطور تشخیص بدیم محدوده و اندازه سرویسمون رو اشتباه انتخاب کردیم؟سرویس‌های بیش از حد ریز و به هم وابستهتاخیر زیاد در ارتباط بین سرویس هاDistributed Monolith (میکروسرویسِ مونولیتی)یک فروشگاه آنلاین رو درنظر بگیرید که برای &#34;ورود کاربر&#34; و &#34;ثبت نام کاربر&#34; دو سرویس جدا ساخته! نتیجه‌اش چی میشه؟ هر عملیات ساده نیاز به ۱۰ بار call بین سرویس داره و آپدیت نگهداشتن دیتابیس ها چالش بعدی میشه.روشی که اینجا به عنوان راه حل شناخته شده ای هست، استفاده از اصول Domain-Driven Design (DDD) در تقسیم بندی مناسب سرویس ها است. این روش بهمون کمک میکنه تا سرویس‌ها رو بر اساس قابلیت‌های کسب‌وکار تقسیم‌بندی کنیم.۳. بی‌توجهی به مدیریت و ابزارهااز موارد خیلی مهمی که توی پیاده سازی میکروسرویس اهمیتش خیلی زیاده، موضوع ابزارها و مانیتورینگ هست. برای مطلع بودن لحظه ای از وضعیت سرویس ها و ارتباطاتشون، ریلیزها و موارد دیگه ای که نیازه بدونیم، باید از ابزارها و روش های مدیریتی مناسب میکروسرویس ها استفاده بشه در غیر این صورت مواردی مثل دیباگ و آپتایم سرویس ها از بزرگترین چالش های تیم میشه.مواردی که در تیم هایی با روش های نادرست مدیریتی و ابزار نامناسب دیده میشه:تیم‌های جداگانه که با هم همکاری نمی‌کنندکارهای تکراری و هدررفت منابعمشکلات امنیتیاینجاست که تعریف استانداردهای تیمی و استفاده از ابزارهایی مثل Istio, Prometheus اهمیت خودشون رو برای حل چنین مشکلی نشون میدن.۴. مهاجرت بدون برنامه به میکروسرویسمهاجرت سریع و بدون برنامه از مونولیت به میکروسرویس، دوره‌ی گذار خیلی طولانی و طاقت فرسایی رو برای تیم و هزینه های نگهداری به شدت زیادی رو برای شرکت در پی داره که با توجه به مثال هایی که در اکوسیستم استارتاپی ایران دیده شده حتی بعضی شرکت ها چندین سال درگیر این دوره گذار میشن و حتی با رفت و آمد تیم های زیاد در شرکت، این کار زمان بیشتر و هزینه سنگین تری روی دست ذی نفعان میزاره.از نشون های مهاجرت سریع و بدون برنامه میشه به این موارد اشاره کرد:downtime طولانیناسازگاری داده‌هامهاجرت نیمه‌کارهپیشنهاد منابع معتبر برای حل چنین چالشی استفاده از الگوی Strangler Fig و همچنین اولویت بندی درست بر اساس نیاز بیزنس و سرویس های با ارزش هست.۵. فراموش کردن وابستگی‌ها و عملکردعدم مدیریت درست وابستگی‌های بین سرویس‌ها و توجه نکردن به عملکرد نهایی باعث میشه پرفورمنس محصول کاهش پیدا کنه و زمانی که سیستم داره توسعه پیدا میکنه، سرویس های جدیدی اضافه یا لود بیشتر میشه، عملکرد ضعیف سیستم بیزنس رو دچار مشکل جدی کنه. یکی از نمونه هاش سرویس های سنکرون هستن که فقط کافیه یکی از سرویس ها ریسپانس نده یا fail بشه تا به همین ترتیب زنجیره ریکوئست بیافته و از هم گسسته بشه.نشونه های رایج از این مورد در سیستم:خطاهای آبشاری (Cascading Failures)عملکرد ضعیف سیستممشکل در مقیاس‌پذیریبرای حل چنین مشکل رایجی در میکروسرویس این روش ها در اکثر موارد راه حل خوبی بوده:از ارتباط غیر همزمان (مثلاً با Kafka) استفاده کنیدCircuit Breaker پیاده‌سازی کنیدبا ابزارهایی مثل Jaeger عملکرد رو مانیتور کنیدپیاده‌سازی میکروسرویس‌ها علاوه بر اینکه مزیت های بسیار خوبی داره، چالش های بسیار جدی در پیاده سازی و مشکلات رایجی داره که شرکت های بزرگی مثل اوبر در مسیر پیاده سازی اون تجربه کردن و با توجه به مقیاس شرکت از پس حل این مشلات بر اومدن. نکته مهمی که حتما باید در نظر گرفت، موفقیت در چنین تصمیماتی در گرو پرهیز از اشتباهات رایج است. اینطوری هزینه های پیاده سازی کاهش چشمگیری داره.</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Sun, 28 Sep 2025 16:14:41 +0330</pubDate></item><item><title>هزینه‌های پنهان مجیک متدها در PHP</title><link>https://virgool.ir/@m.keshavarz.ch/hidden-costs-of-magic-methods-in-php-fuqeo59mgfex</link><description>مجیک متدهای PHP این قابلیت رو بهمون میدن که رفتار آبجکت‌ها رو سفارشی کنیم. مثلا get() و set() برای دسترسی به پراپرتی‌های تعریف‌نشده، call() و callStatic() برای متدهای تعریف‌نشده، و invoke() برای کال کردن آبجکت مثل فانکشن. اینا کد رو انعطاف‌پذیر می‌کنن، ولی اگه در استفاده ازشون زیاده‌روی کنیم، مشکلاتی مثل کندی، دیباگ سخت، و نگهداری پیچیده رو برامون به وجود میارن. خصوصا توی فریم‌ورک‌ها که پروژه‌ها بزرگن.اینجا میخواییم این دردسرها رو با سناریوهای واقعی بررسی کنیم.این متدها چه کاربردهایی دارند؟get($name) و set($name, $value): وقتی به پراپرتی‌ای دسترسی پیدا می‌کنی که وجود نداره (مثل $obj-&gt;foo)، اینا وارد عمل می‌شن. کجاها میتونه مفید باشه؟ برای پروکسی‌ها، lazy load، یا اعتبارسنجی بدون getter/setter مشخص.call($name, $arguments) و callStatic($name, $arguments): برای متدهایی که تعریف نشدن (اینستنس یا استاتیک). تو facadeها میتونیم ببینیمش.__invoke(...$args): آبجکتت رو مثل فانکشن کال می‌کنه (مثل $obj())، برای کلوژرها یا میدل‌ویرها گزینه مناسبیه.تو متاپروگرمینگ این موارد خودشون رو خیلی خوب نشون میدن، ولی هزینه دارن!۱. مشکل پرفرومنس، کندی پنهانمجیک متدها یه لایه اضافی به کد اضافه می‌کنن؛ PHP باید چک کنه این متدها وجود دارن یا نه، که زمان می‌بره.چه فایده ای داره: این داینامیک بودن باین قابلیت رو بهمون میده که بدون تعریف صریح پراپرتی‌ها یا متدها، چیزها رو مدیریت کنیم.کجا اذیتمون میکنه: دسترسی‌ها کند می‌شن، گاهی ۵-۱۰ برابر. توی لوپ‌های بزرگ، CPU رو حسابی مشغول می‌کنه.فرض کن یه سایت فروشگاهی با لاراول داریم. از __get() توی مدل Eloquent استفاده کردیم که $product-&gt;discount اتوماتیک تخفیف رو حساب کنه.حالا این چه کمکی بهمون میکنه؟ کد کوتاه و تمیزه، بدون نیاز به getterهای اضافی.اما چطور و کجا مارو به دردسر میندازه؟ توی صفحه اصلی که ۱۰۰تا (یا بیشتر) محصول رو لیست می‌کنیم، لود صفحه به جای ۱۰۰ میلی‌ثانیه، ۳۰۰-۶۰۰ میلی‌ثانیه طول می‌کشه، چون هر دسترسی یه چک داینامیک داره. تو این نقطه است که موضوع پرفورمنس مهم تر میشه.جنبه دسترسی/کال مستقیم از طریق مجیک متد هزینه اضافی (بنچمارک ۲۰۲۵)دسترسی به پراپرتی$this-&gt;_foo (مستقیم)$obj-&gt;foo (__get)~۱۰-۲۰ میکروثانیه vs. ۵۰-۱۰۰ میکروثانیه کال متدmethod($args)$obj-&gt;method($args) (__call)~۵ میکروثانیه vs. ۱۵-۳۰ میکروثانیهلوپ (۱ میلیون تکرار)~۱۰۰ میلی‌ثانیه~۳۰۰-۶۰۰ میلی‌ثانیه۳-۶ برابر کندتر۲. دردسر دیباگ، پیداکردن خطا مثل سوزن توی انبار کاهمجیک متدها مسیر جریان کد رو مخفی می‌کنن؛ استک تریس‌ها به خود متد اشاره می‌کنن، نه منطق اصلی که پشتش هست.کجاها میتونه مفید باشه: میتونه منطق پیچیده رو پشت یه API ساده پنهان کنه.چطور به دردسر میندازه: وقتی خطا میده، نمی‌فهمی مشکل از کجاست. ابزارهایی مثل Xdebug هم گیج می‌شن و فایده چندانی ندارن.فرض کن داریم یه اپ بانکی با سیمفونی می‌سازیم. از call() توی یه facade استفاده کردیم که متدهای سرویس‌های مختلف رو داینامیک کال کنه.این facade همه چیز رو تمیز جمع می‌کنه و اون پیچیدیگی ها دیگه دیده نمیشه. اما وقتی یه ارور PDO توی یه سرویس نمایش داده میشه، تریس فقط call() رو نشون می‌ده. دو ساعت می‌گردی تا بفهمی مشکل از یه کوئری دیتابیسه. توی پروداکشن، قطعا این منجر به داون‌تایم میشه و محصول رو دچار مشکل میکنه.۳. خوانایی و نگهداری، کد گنگ و دردسرهای بعدشمجیک متدها خوانایی و وضوح کد رو کم می‌کنن، و کلاس‌ها تبدیل به موجودات عجیبی می‌شن که پراپرتی‌ها و متدها از هیچ جا خیلی یهویی پیداشون می‌شه.فایده این ویژگی چیه؟ برای پروتوتایپ سریع، کد کمتر و تمیزتری نوشته میشه. اما موقع ریفکتورینگ کار سخت می‌شه، و توسعه‌دهنده‌های جدید نمی‌فهمن چی به چیه. ابزارهای استاتیک مثل Psalm هم نمی‌تونن درست تحلیل کنن.فرض کن توی یه پروژه تیمی با Codeigniter، از __get() توی یه مدل استفاده شده که ۵۰ داینامیک پراپرتی تولید کنه. اینجا این قابلیت کمک میکنه که سریع پروتوتایپ زده بشه و کد کوتاه و مختصر بمونه. ولی وقتی یه توسعه‌دهنده جدید به تیم یا پروژه اضافه میشه، نمی‌فهمه این پراپرتی‌ها از کجا میان. اگه یکی رو تغییر بده، بقیه هم خراب می‌شن. پروژه بدهی فنی جمع می‌کنه و نگهداریش دو برابر زمان می‌بره.نمونه های دیگه از مجیک متدهالوپ بی‌نهایت: __call() که خودش رو کال کنه، باعث stack overflow میشه که توی روترهای دست‌ساز زیاد دیده میشه.مشکل سریالایزیشن: آبجکت‌ها درست سریالایز نمیشن و باید __sleep() دستی درست بشه.باگ امنیتی: زنجیره‌های POP توی دیسیریالیزیشن از __wakeup() و مجیک متدها سوءاستفاده می‌کنن، مثل باگ‌های لاراول.چطور از مجیک متدها استفاده نکنیم؟کمتر استفاده کنیم: از روش‌های استاندارد مثل traitها به جای مجیک متدها استفاده کنیم. با Blackfire عملکرد رو بررسی کنیم.شفاف باشیم: با PHPDoc داکیومنت کنیم؛ برای interceptها تست بنویسیم .از هوک‌های پراپرتی PHP 8.4 استفاده کنیم البته اگر پروژه قابلیت ارتقای ورژن رو داره.جایگزین‌ها:attributeها + getterها گزینه بهتری نسبت به Lazy Propertyها هستن.از کلوژرها یا typeهای callable به جای __invoke() استفاده کنیم.توی فریم‌ورک‌ها هم با کانفیگ مثل مود strict لاراول میتونیم این موضوع رو کنترل کنیم؛ با Rector هم میشه کد رو تمیز کرد.</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Thu, 18 Sep 2025 12:30:43 +0330</pubDate></item><item><title>راهنمای طراحی RESTful API استاندارد و اصولی</title><link>https://virgool.ir/@m.keshavarz.ch/restful-api-standard-tptg48zfwhnf</link><description>RESTful APIs امروزه ستون فقرات ارتباط بین سرویس‌های مدرن هستند؛ از اپلیکیشن‌های موبایل تا سیستم‌های ابری پیچیده. اما طراحی یک API RESTful کارآمد، بسیار فراتر از پیاده‌سازی چند endpoint ساده است.چرا RESTful APIs مهم است؟مقیاس‌پذیری: APIهای خوب طراحی شده به راحتی با رشد کسب‌وکار سازگار می‌شوندتجربه توسعه‌دهندگان: APIهایی با طراحی واضح، سرعت توسعه را چند برابر می‌کنندقابلیت نگهداری: معماری تمیز باعث می‌شود تغییرات آینده بدون دردسر انجام بشونداصول کلیدی REST و بهترین پراکتیس‌هااستفاده از متدهای HTTP مناسب (HTTP Methods):متدهای HTTP قلب تپنده APIهای RESTful هستند و باید به درستی استفاده شوند:GET: برای دریافت داده (ایمن و تکرارپذیر). مثال: GET /users/123POST: برای ایجاد داده جدید. مثال: POST /usersPUT: برای به‌روزرسانی کامل یک منبع. مثال: PUT /users/123PATCH: برای به‌روزرسانی جزئی یک منبع. مثال: PATCH /users/123DELETE: برای حذف داده. مثال: DELETE /users/123نکته: استفاده نادرست (مثل POST به جای GET) می‌تواند باعث مشکلات امنیتی مانند CSRF شود!طراحی URLهای معنادار (Resource-Based URLs):آدرس‌های API باید مانند یک نقشه واضح و قابل درک باشند:از اسامی جمع استفاده کنید: /users نه /userسلسله‌مراتبی طراحی کنید: /users/123/ordersاز فعل در URL خودداری کنید: به جای /getUserOrders از /users/123/orders استفاده کنیدپارامترهای Query فقط برای فیلتر کردن و جستجو: /users?role=adminنکته کلیدی: URLها باید Stateless باشند و به هیچ Sessionای وابسته نباشند!مدیریت کدهای وضعیت HTTP (HTTP Status Codes):کدهای وضعیت، زبان ارتباطی API شما هستند:2xx (موفق):200 OK: درخواست موفق201 Created: منبع ایجاد شد204 No Content: عملیات موفق ولی ریسپانسی وجود ندارد4xx (خطای کلاینت):400 Bad Request: درخواست نامعتبر401 Unauthorized: نیاز به احراز هویت403 Forbidden: دسترسی ممنوع404 Not Found: منبع یافت نشد5xx (خطای سرور):500 Internal Server Error: خطای عمومی سرور503 Service Unavailable: سرویس موقتاً در دسترس نیستبهترین روش:همیشه کد مناسب برگردانید.در بادی ریسپانس، جزئیات خطا را به صورت JSON ارسال کنید:{&#xA;  &#34;error&#34;: &#34;User not found&#34;,&#xA;  &#34;code&#34;: 404,&#xA;  &#34;details&#34;: &#34;The requested user ID does not exist&#34;&#xA;}نسخه‌بندی API (API Versioning):تغییرات در API اجتناب‌ناپذیر هستند، اما نسخه‌بندی هوشمندانه از ایجاد مشکل برای کلاینت‌های موجود جلوگیری می‌کند:URL Versioning: ساده و شفاف (مثال: https://api.example.com/v1/users)Header Versioning: تمیزتر (مثال: Accept: application/vnd.company.v1+json)Query Parameter Versioning: انعطاف‌پذیر (مثال: https://api.example.com/users?version=1)نکته کلیدی: تغییرات باید Backward Compatible باشند!فیلدهای جدید اضافه کنید، ولی فیلدهای موجود را حذف یا تغییر ندهید.از Deprecation Strategy استفاده کنید: ابتدا اطلاع دهید، سپس نسخه جدید منتشر کنید.مدیریت داده‌ها و فرمت‌ها (Data Handling):فرمت داده‌ها در عملکرد و خوانایی API:JSON: فرمت پیش‌فرض برای اکثر APIها (خوانا و گسترده‌پذیر)Protobuf/MessagePack: برای مواردی که پرفورمنس بالاتری نیاز است (مثلاً در میکروسرویس‌ها)بهترین روش‌ها:HATEOAS: اضافه کردن لینک‌های مرتبط برای کشف داینامیک API:json{&#xA;  &#34;id&#34;: 123,&#xA;  &#34;name&#34;: &#34;John&#34;,&#xA;  &#34;_links&#34;: {&#xA;    &#34;self&#34;: { &#34;href&#34;: &#34;/users/123&#34; },&#xA;    &#34;orders&#34;: { &#34;href&#34;: &#34;/users/123/orders&#34; }&#xA;  }&#xA;}Pagination: برای داده‌های حجیم (مثال: ?page=2&amp;size=20)فشرده‌سازی: فعال کردن GZip/Brotli برای کاهش حجم ریسپانس هاامنیت و احراز هویت (Security and Authentication):امنیت باید در هسته طراحی API قرار گیرد:HTTPS: الزامی برای تمام ارتباطاتاحراز هویت:JWT: برای حالت StatelessOAuth 2.0 برای احراز هویت Delegatedاعتبارسنجی ورودی: جلوگیری از حملات تزریق کد (مثال: SQL Injection)Rate Limiting: محدود کردن درخواست‌ها (مثال: 1000 درخواست در ساعت برای هر کلاینت)الگوی امنیتی:استفاده از API Gateway برای مدیریت یکپارچه امنیت (احراز هویت، اعتبارسنجی، Rate Limiting)separation of concerns: سرویس‌های کسب‌وکار تحت شبکه داخلی و محافظت‌شده باقی بمانند.مدیریت خطاها و Idempotency:Idempotency:تضمین که تکرار یک درخواست نتیجه یکسان داشته باشد (مثلاً PUT و DELETE idempotent هستند).Idempotency Key برای عملیات حساس (مثل پرداخت)POST /payments&#xA;Idempotency-Key: unique-key-123مدیریت خطا:پاسخ خطای دارای ساختار منظم:{&#xA;  &#34;error&#34;: {&#xA;    &#34;code&#34;: &#34;invalid_parameter&#34;,&#xA;    &#34;message&#34;: &#34;The &#39;email&#39; field is invalid.&#34;,&#xA;    &#34;details&#34;: {&#34;field&#34;: &#34;email&#34;}&#xA;  }&#xA;}استفاده از استتوس کدهای HTTP مناسب (مثلاً 409 Conflict برای تضاد داده).طراحی و توسعه APIهای RESTful موفق، نیازمند ترکیبی از اصول فنی دقیق، مدیریت هوشمندانه تغییرات و تمرکز بر تجربه برنامه نویس ها است. با رعایت موارد گفته شده می‌توان APIهایی ساخت که نه تنها پایدار و امن باشند، بلکه به راحتی قابل توسعه و نگهداری باشند. علاوه بر این، استفاده از ابزارهای مدرن (مانند Contract Testing با Pact) و  رویکردهایی مثل Consumer-Driven Contracts، از ایجاد مشکل برای کلاینت‌های موجود در برابر تغییرات جلوگیری می‌کند. در نهایت، موفقیت APIها به‌صورت مستقیم به مستندسازی دقیق، نظارت مستمر و همکاری موثر بین تیم‌ها وابسته است تا بتوانند در بلندمدت پاسخگوی نیازهای پیچیده کسب‌وکار باشند.</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Tue, 16 Sep 2025 15:15:07 +0330</pubDate></item><item><title>تفاوت بین معماری نرم‌افزار و طراحی کد چیست؟</title><link>https://virgool.ir/@m.keshavarz.ch/software-architecture-vs-code-design-gtisihwh9nb9</link><description>در دنیای توسعه نرم‌افزار، دو مفهوم کلیدی &#34;معماری نرم‌افزار&#34; و &#34;طراحی کد&#34; اغلب با هم اشتباه گرفته می‌شوند، اما تفاوت‌های اساسی بین آن‌ها وجود دارد. کتاب Fundamentals of Software Architecture نوشته مارک ریچاردز و نیل فورد، در فصل 1 با عنوان &#34;Introduction&#34;، این تفاوت را به توضیح می‌دهد. معماری نرم‌افزار بر ساختار کلی سیستم تمرکز دارد، در حالی که طراحی کد به جزئیات پیاده‌سازی مربوط می‌شود. در این مقاله، بر اساس محتوای این کتاب، به بررسی این تفاوت‌ها، ویژگی‌ها، و اهمیت هر کدام می‌پردازیم. تعریف پایه‌ای دو مفهوممعماری نرم‌افزار: به ساختار سطح بالا و سازمان‌دهی سیستم اشاره دارد. این مفهوم شامل تصمیم‌گیری‌های کلیدی در مورد چگونگی سازمان‌دهی اجزا، روابط بین آن‌ها، و ویژگی‌های غیرکارکردی (مانند مقیاس‌پذیری، امنیت، و قابلیت نگهداری) است. معماری مانند نقشه یک ساختمان است که پایه و اساس را تعیین می‌کند.طراحی کد: به جزئیات پیاده‌سازی کد، مانند الگوریتم‌ها، ساختار داده‌ها، و کدهای خاص در سطح کلاس‌ها یا توابع اشاره دارد. این مانند جزئیات داخلی اتاق‌های ساختمان است که بر اساس نقشه معماری ساخته می‌شوند.معماری بر &#34;چرا&#34; و &#34;چگونه&#34; سیستم به عنوان یک کل تمرکز دارد، در حالی که طراحی کد بر &#34;چگونگی&#34; پیاده‌سازی جزئیات است.تفاوت‌های کلیدیبر اساس فصل 1 کتاب، تفاوت‌های اصلی بین معماری نرم‌افزار و طراحی کد عبارتند از:سطح انتزاع (Level of Abstraction):معماری: سطح بالا و انتزاعی است. تمرکز بر اجزای بزرگ مانند سرویس‌ها، ماژول‌ها، و روابط بین آن‌ها. مثلاً تصمیم‌گیری در مورد استفاده از معماری میکروسرویس‌ها یا لایه‌ای.طراحی کد: سطح پایین و بتن است. تمرکز بر کدهای خاص، مانند پیاده‌سازی یک الگوریتم جستجو یا ساختار یک کلاس.تمرکز بر ویژگی‌ها:معماری: بر ویژگی‌های غیرکارکردی (Non-Functional Requirements یا NFRها) مانند عملکرد، قابلیت اطمینان، و مقیاس‌پذیری تأکید دارد. این ویژگی‌ها سیستم را به عنوان یک کل تحت تأثیر قرار می‌دهند.طراحی کد: بر ویژگی‌های کارکردی (Functional Requirements) مانند چگونگی اجرای یک تابع خاص تمرکز دارد.زمان و دامنه تأثیر:معماری: تصمیمات آن بلندمدت هستند و تغییر آن‌ها هزینه‌بر است. معماری بر کل سیستم تأثیر می‌گذارد و پایه‌ای برای طراحی کد فراهم می‌کند.طراحی کد: تصمیمات آن کوتاه‌مدت‌تر هستند و می‌توان آن‌ها را آسان‌تر تغییر داد. این طراحی درون مرزهای معماری انجام می‌شود.نقش افراد:معماری: معمولاً توسط معمار نرم‌افزار انجام می‌شود که دید کلی دارد و با ذی نفعان همکاری می‌کند.طراحی کد: توسط توسعه‌دهندگان انجام می‌شود که بر پیاده‌سازی تمرکز دارند.ابزارها و روش‌ها:معماری: از ابزارهایی مانند مدل C4، UML، یا ADR برای مستندسازی استفاده می‌شود.طراحی کد: از ابزارهایی مانند IDEها، Refactoring Tools، یا Design Patterns (مانند Singleton یا Factory) استفاده می کنند.یک مثال برای درک بهترمثال کتاب از یک سیستم بانکی:معماری: تصمیم‌گیری در مورد استفاده از معماری لایه‌ای (Layered) برای جداسازی لایه‌های ارائه، کسب‌وکار، و داده. این تصمیم بر مقیاس‌پذیری سیستم تأثیر می‌گذارد.طراحی کد: پیاده‌سازی یک کلاس برای مدیریت تراکنش‌ها در لایه کسب‌وکار، مانند استفاده از الگوریتم خاصی برای محاسبه سود.در یک مثال دیگر، اگر معماری سیستم را به یک شهر تشبیه کنیم، معماری مانند برنامه‌ریزی شهری (خیابان‌ها، ساختمان‌ها، و زیرساخت‌ها) است، در حالی که طراحی کد مانند طراحی داخلی یک ساختمان خاص است.اهمیت تمایز بین دو مفهومنادیده گرفتن این تفاوت می‌تواند به مشکلات منجر شود، مانند طراحی کدی که با معماری سیستم سازگار نیست و باعث پیچیدگی یا عملکرد ضعیف می‌شود. کتاب این نکته را گوشزد میکند که معماران باید مرز بین این دو را حفظ کنند تا تیم‌ها بتوانند به طور مؤثر کار کنند. در محیط‌های Agile، این تمایز کمک می‌کند تا معماری پایدار بماند در حالی که طراحی کد با تغییرات سریع همگام شود.تفاوت بین معماری نرم‌افزار و طراحی کد در سطح انتزاع، تمرکز، و تأثیر آن‌ها نهفته است. بر اساس Fundamentals of Software Architecture، درک این تفاوت به معماران و توسعه‌دهندگان کمک می‌کند تا سیستم‌هایی کارآمد و قابل نگهداری بسازند. معماری پایه را فراهم می‌کند و طراحی کد جزئیات را پر می‌کند – هر دو مکمل یکدیگر هستند، اما نباید با هم اشتباه گرفته شوند. برای موفقیت، تیم‌ها باید این مرز را رعایت کنند و از ابزارهای مناسب برای هر سطح استفاده نمایند.</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Mon, 08 Sep 2025 10:59:46 +0330</pubDate></item><item><title>چطور برای پروژه برنامه نویسی داکیومنت بنویسیم؟</title><link>https://virgool.ir/@m.keshavarz.ch/چطور-برای-پروژه-برنامه-نویسی-داکیومنت-بنویسیم-v3wm4ijkqete</link><description>یکی از کارهایی که کمتر کسی حوصله انجام دادنش رو داره همین داکیومنت نویسیه. بیان و نوشتن اینکه چه کاری انجام دادی در ظاهر کار خسته کننده و شاید بی فایده‌ای به نظر بیاد چون با خودمون میگیم که: “خب نفر بدی که میاد برنامه نویسه! حتما یه نگاه به کدهای من بندازه میدونه چی نوشتم”برای همین تو پروژه ها یکی از کارهای نسبتا پرچالش انتقال دانش پروژه به افراد تازه وارد هست.برای این افراد سوالات زیادی نسبت به کدها و تصمیم های تو پروژه ایجاد میشه که بهترین راه حل نوشتن داکیومنت مناسب برای انتقال دانش است.اما این جمله درست نیست چون بعضی تصمیم‌ها تو ذهن ما یا به صورت شفاهی بین تیم انجام شده و ما نتیجه این تصمیم‌ها رو توی کد اجرا می کنیم و میبینیم.از جمله کاربردهای داکیومنت اینه که زمان بقیه اعضای تیم کمتر صرف جواب دادن به سوال های تکراری و متداول میشه چون بیشتر سوالاتی که برای افراد ممکنه پیش بیاد تو داکیومنت نوشته شده.تو این پست سعی کردم بیشتر درباره داکیومنت نویسی توضیح بدم.چطور برای پروژه داکیومنت بنویسیم؟بقیه قسمت ها هم به زودی منتشر میشه :))</description><category>Mohammad Keshavarz</category><author>Mohammad Keshavarz</author><pubDate>Sun, 02 Apr 2023 15:31:09 +0330</pubDate></item></channel></rss>