├── Buffer - Uber.md ├── Circuit Breaker Pattern - Uber.md ├── Cold Start - Uber.md ├── Correlation ID in Headers - Uber.md ├── Database Sharding.md ├── Distance Anomaly Issue - Uber.md ├── Feature Flags (Feature Toggle) - Uber.md ├── Graceful Shutdown - Uber.md ├── Hash Table Data Structure - Uber.md ├── KISS Principle.md ├── Lazy Loading vs Eager Loading - Uber.md ├── Lowest Common Ancestor in a Binary Tree (LCA) - Uber.md ├── Map Matching and Sensor Fusion for Improved Driver Navigation.md ├── Multiplexing vs Demultiplexing - uber.md ├── NDA - Uber.md ├── PEMIDI solutions.md ├── README.md ├── Race Condition - Uber.md ├── SoC.md ├── TCP Slow Start Restart Algorithm - Uber.md ├── YAGNI.md ├── git reset command.md └── git rest.md /Buffer - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 |
6 | 7 | کیان 🌈: بچه‌ها کسی میتونه buffer رو به من توضیح بده؟ 8 | 9 | حسین: 😊 آفرین کیان جان! سوال خیلی خوبی هست. بذار برات توضیح بدم که buffer چیه. 10 | 11 | فکر کن داری یه بازی آب بازی انجام میدی. یه تشت بزرگ آب داری و یه لیوان کوچیک. می‌خوای آب رو از تشت به یه گلدون منتقل کنی. [🔗](https://www.techopedia.com/definition/3/buffer) 12 | 13 | 1. **لیوان کوچیک تو، یه buffer هست:** 14 | - وقتی می‌خوای آب رو از تشت به گلدون منتقل کنی، اول لیوان رو پر می‌کنی. 15 | - بعد آب لیوان رو توی گلدون خالی می‌کنی. 16 | - این کار رو چند بار تکرار می‌کنی تا گلدون پر بشه. 17 | 18 | 2. **حالا چرا از buffer (لیوان) استفاده می‌کنیم؟** 19 | - چون اگه بخوای یهو کل آب تشت رو روی گلدون خالی کنی، ممکنه خیلی از آب بریزه بیرون. 20 | - با لیوان، می‌تونی با دقت و آروم آروم این کار رو انجام بدی. 21 | 22 | 3. **توی دنیای کامپیوترها:** 23 | - در واقع Buffer مثل همون لیوانه. 24 | - وقتی داده‌ها (مثل آب) از یه جا به جای دیگه منتقل میشن، اول میان توی buffer. 25 | - بعد از buffer به مقصد نهایی میرن. 26 | 27 | کیان 🌈 : اوه، پس buffer مثل یه ظرف موقته که کمک می‌کنه چیزها رو بهتر جابجا کنیم؟ 28 | 29 | حسین: 👍 دقیقاً! خیلی خوب فهمیدی. مثلاً وقتی داری یه ویدیو آنلاین می‌بینی: 30 | - کامپیوتر اول یه مقدار از ویدیو رو توی یه buffer می‌ریزه. 31 | - بعد شروع می‌کنه به نمایش دادن. 32 | - همزمان، بقیه ویدیو رو هم کم کم میاره و توی buffer می‌ریزه. 33 | 34 | این کار باعث میشه که ویدیو بدون وقفه و یکنواخت پخش بشه، حتی اگه اینترنت یکم کند بشه. 35 | 36 | کیان 🌈 : 😃 وای چه باحال! پس وقتی ویدیو یهو وایمیسته و اون دایره می‌چرخه، داره buffer پر میشه؟ 37 | 38 | حسین: 🎉 آفرین کیان! دقیقاً همینطوره. اون موقع، buffer داره پر میشه تا مطمئن بشه که می‌تونه ویدیو رو بدون مکث نشون بده. 39 | 40 | کیان 🌈 : 😮 حالا فهمیدم! مرسی حسین که اینقدر قشنگ توضیح میدی. 41 | 42 | حسین: 😊 خواهش می‌کنم کیان جان. خیلی خوشحالم که تونستم کمکت کنم. سوال‌های خیلی خوبی می‌پرسی! 43 | 44 |
45 | -------------------------------------------------------------------------------- /Circuit Breaker Pattern - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | 6 | **پیمان:** توی سرویس درخواست سفر اوبر، وقتی کاربر درخواست سفر می‌ده، ما باید به سرویس تخصیص راننده درخواست بزنیم. ولی گاهی اوقات این سرویس از کار می‌افته یا خیلی کند جواب می‌ده. این باعث می‌شه که کاربرها منتظر بمونن و تجربه کاربری خراب بشه. نمی‌دونم چطور می‌تونیم این مشکل رو حل کنیم. 7 | 8 | **حسین:** سلام پیمان، مرسی که مشکل رو مطرح کردی. من فکر می‌کنم اینجا می‌تونیم از الگوی Circuit Breaker استفاده کنیم. این الگو به ما کمک می‌کنه تا وقتی که سرور به مشکل می‌خوره، به جای اینکه درخواست‌ها رو ادامه بدیم، به صورت موقت درخواست‌ها رو قطع کنیم تا سرور بتونه به حالت عادی برگرده. 🔗[Circuit Breaker](https://martinfowler.com/bliki/CircuitBreaker.html) 9 | 10 | **مارال:** حسین، می‌تونی بیشتر توضیح بدی که چطور این الگو کار می‌کنه؟ 🤓 11 | 12 | **حسین:** بله، حتماً. Circuit Breaker به این صورت کار می‌کنه که وقتی تعداد مشخصی از درخواست‌ها با خطا مواجه می‌شن، مدار رو قطع می‌کنه و دیگه درخواست‌های جدید رو به سرور نمی‌فرسته. در عوض، یه پیام خطا به کاربر برمی‌گردونه. بعد از یه مدت زمان مشخص، دوباره مدار رو باز می‌کنه تا ببینه آیا سرور به حالت عادی برگشته یا نه. 🔗[Circuit Breaker Pattern](https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker) 13 | 14 | **ماهان:** حسین، می‌تونی یه مثال توی کد بزنی که بهتر متوجه بشم؟ 😅 15 | 16 | **حسین:** بله، حتماً. فرض کن یه تابع داریم که درخواست‌ها رو به سرور می‌فرسته. ما می‌تونیم از یه کتابخونه مثل `pybreaker` استفاده کنیم. این یه مثال ساده از استفاده از Circuit Breaker هست: 17 | 18 | ```python 19 | import pybreaker 20 | import requests 21 | 22 | # تعریف Circuit Breaker 23 | breaker = pybreaker.CircuitBreaker(fail_max=5, reset_timeout=60) 24 | 25 | @breaker 26 | def call_server(url): 27 | response = requests.get(url) 28 | if response.status_code != 200: 29 | raise Exception("Server Error!") 30 | return response 31 | 32 | try: 33 | response = call_server("http://example.com/api") 34 | print(response.json()) 35 | except pybreaker.CircuitBreakerError: 36 | print("Circuit Breaker فعال شده، لطفاً بعداً دوباره امتحان کنید.") 37 | ``` 38 | 39 | 🔗[pybreaker](https://pypi.org/project/pybreaker/) 40 | 41 | **پیمان:** این خیلی خوبه حسین، ولی چطور می‌تونیم مطمئن بشیم که این راه‌حل توی محیط واقعی هم کار می‌کنه؟ 🤔 42 | 43 | **حسین:** سوال خوبی پرسیدی پیمان. ما باید این رو توی محیط تست و استیجینگ امتحان کنیم و ببینیم که چطور عمل می‌کنه. همچنین باید لاگ‌ها رو بررسی کنیم تا مطمئن بشیم که Circuit Breaker به درستی فعال می‌شه و درخواست‌ها رو مدیریت می‌کنه. 🔗[Testing Circuit Breaker](https://docs.microsoft.com/en-us/azure/architecture/patterns/circuit-breaker#testing-the-pattern) 44 | 45 | --- 46 | ### پیمان کنجکاوتر میشه: 47 | 48 | **پیمان:** این مفهوم توی رشته مهندسی برق هم هست؟ 🤔 49 | 50 | **حسین:** بله پیمان، دقیقاً همینطوره. در واقع، ایده Circuit Breaker از مهندسی برق گرفته شده. توی مهندسی برق، Circuit Breaker یه دستگاه حفاظتیه که وقتی جریان برق از حد مجاز بیشتر می‌شه، مدار رو قطع می‌کنه تا از آسیب به تجهیزات جلوگیری کنه. توی نرم‌افزار هم همین مفهوم رو داریم، فقط به جای جریان برق، با درخواست‌های شبکه سر و کار داریم. 🔗[Circuit Breaker in Electrical Engineering](https://en.wikipedia.org/wiki/Circuit_breaker) 51 | 52 | **مارال:** دقیقاً حسین، این یکی از مثال‌های خوبیه که نشون می‌ده چطور مفاهیم از یک رشته به رشته دیگه منتقل می‌شن و کاربرد دارن. 😊 53 | 54 | **ماهان:** خیلی جالبه! من همیشه فکر می‌کردم این مفاهیم فقط توی نرم‌افزار هستن. 🤯 55 | 56 | **حسین:** بله ماهان، خیلی از الگوها و مفاهیم توی مهندسی نرم‌افزار از رشته‌های دیگه مثل مهندسی برق، مکانیک و حتی مدیریت گرفته شدن. این نشون می‌ده که چقدر رشته‌های مختلف می‌تونن از همدیگه یاد بگیرن. 57 | 58 | 59 | -------------------------------------------------------------------------------- /Cold Start - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | پیمان: 😕 بچه‌ها، من یه مشکل جدی پیدا کردم توی سیستم مسیریابی‌مون. هر وقت که سرویس‌مون رو ری‌استارت می‌کنیم، یا وقتی که یه نود جدید به کلاستر Redis اضافه می‌شه، برای چند دقیقه اول عملکرد سیستم خیلی کند می‌شه. انگار که Redis داره از صفر شروع می‌کنه به ساختن کش. این مشکل باعث می‌شه که کاربرا توی اون زمان تجربه خیلی بدی داشته باشن و ممکنه حتی نتونن از سرویس استفاده کنن. من نمی‌دونم چطور باید حلش کنیم. 5 | 6 | حسین: 🤔 آها، فهمیدم پیمان جان. این مشکلی که داری توصیف می‌کنی، در دنیای مهندسی نرم‌افزار به "Cold Start" معروفه. این مشکل خصوصاً در سیستم‌های کش مثل Redis خیلی رایجه. 7 | 8 | ماهان: 🙋‍♂️ ببخشید که می‌پرم وسط حرفتون، ولی می‌شه یه کم بیشتر توضیح بدین این Cold Start چیه؟ ترجیحاً با یه مثال کد؟ 9 | 10 | حسین: 😊 البته ماهان جان. ببین، Cold Start زمانی اتفاق می‌افته که سیستم کش ما، در این مورد Redis، خالیه یا داده‌های قدیمی داره. بذار با یه مثال کد توضیح بدم: 11 | 12 | ```python 13 | import redis 14 | import time 15 | 16 | r = redis.Redis(host='localhost', port=6379, db=0) 17 | 18 | def get_user_data(user_id): 19 | # سعی می‌کنیم داده رو از کش بگیریم 20 | cached_data = r.get(f"user:{user_id}") 21 | 22 | if cached_data is None: 23 | # اگه داده توی کش نباشه، از دیتابیس می‌گیریم 24 | # این عملیات معمولاً کنده 25 | db_data = fetch_from_database(user_id) # فرض کنید این تابع وجود داره 26 | 27 | # داده رو توی کش ذخیره می‌کنیم 28 | r.set(f"user:{user_id}", db_data) 29 | 30 | return db_data 31 | 32 | return cached_data 33 | 34 | # شبیه‌سازی درخواست‌های کاربر 35 | start_time = time.time() 36 | for i in range(1000): 37 | get_user_data(i) 38 | end_time = time.time() 39 | 40 | print(f"زمان اجرا: {end_time - start_time} ثانیه") 41 | ``` 42 | 43 | توی این مثال، اولین بار که برنامه اجرا می‌شه، کش خالیه و برای هر کاربر باید از دیتابیس داده بگیریم. این باعث می‌شه که اجرای برنامه خیلی کند باشه. 44 | 45 | پیمان: 😯 آها، حالا فهمیدم. پس مشکل ما اینه که وقتی سرویس رو ری‌استارت می‌کنیم، کش خالی می‌شه و باید از اول پر بشه. این باعث می‌شه که برای مدتی سیستم کند کار کنه. درسته؟ 46 | 47 | حسین: 👍 دقیقاً پیمان جان. حالا، برای حل این مشکل، ما می‌تونیم از تکنیک‌هایی به اسم "Cache Warming" یا "گرم کردن کش" استفاده کنیم. این تکنیک‌ها کمک می‌کنن که قبل از اینکه ترافیک واقعی به سیستم برسه، کش رو با داده‌های مهم پر کنیم. [🔗](https://aws.amazon.com/caching/best-practices/) 48 | 49 | ماهان: 🤓 می‌شه یه مثال کد از این Cache Warming هم بزنید؟ 50 | 51 | حسین: 😃 حتماً ماهان جان. ببین، ما می‌تونیم یه اسکریپت بنویسیم که موقع راه‌اندازی سیستم اجرا بشه و کش رو با داده‌های پرکاربرد پر کنه. مثلاً: 52 | 53 | ```python 54 | import redis 55 | import threading 56 | 57 | r = redis.Redis(host='localhost', port=6379, db=0) 58 | 59 | def warm_cache(): 60 | # لیستی از آیدی‌های کاربران پرکاربرد 61 | popular_user_ids = get_popular_user_ids() # فرض کنید این تابع وجود داره 62 | 63 | def warm_user_data(user_id): 64 | if not r.exists(f"user:{user_id}"): 65 | data = fetch_from_database(user_id) 66 | r.set(f"user:{user_id}", data) 67 | 68 | # استفاده از چند thread برای سرعت بیشتر 69 | threads = [] 70 | for user_id in popular_user_ids: 71 | t = threading.Thread(target=warm_user_data, args=(user_id,)) 72 | t.start() 73 | threads.append(t) 74 | 75 | for t in threads: 76 | t.join() 77 | 78 | # این تابع رو موقع راه‌اندازی سیستم صدا می‌زنیم 79 | warm_cache() 80 | ``` 81 | 82 | این کد، کش رو با داده‌های کاربران پرکاربرد پر می‌کنه، که باعث می‌شه سیستم سریع‌تر به حالت بهینه برسه. 83 | 84 | مارال: 🧐 این ایده خوبیه حسین. ولی آیا این روش می‌تونه مقیاس‌پذیری سیستم رو تحت تأثیر قرار بده؟ 85 | 86 | حسین: 🤔 سؤال خوبیه مارال جان. بله، این روش می‌تونه روی مقیاس‌پذیری تأثیر بذاره، خصوصاً اگه تعداد داده‌هایی که می‌خوایم پیش‌گرم کنیم زیاد باشه. برای حل این مسئله، ما می‌تونیم از چند تا تکنیک استفاده کنیم: 87 | 88 | 1. **Incremental Warming**: به جای اینکه همه داده‌ها رو یکجا گرم کنیم، می‌تونیم این کار رو به تدریج انجام بدیم. 89 | 90 | 2. **Prioritized Warming**: داده‌های مهم‌تر رو اول گرم کنیم. 91 | 3. **Distributed Warming**: از چند نود برای گرم کردن کش استفاده کنیم. 92 | 93 | پیمان: 😃 وای چقدر عالی! حسین جان، می‌شه یه کم بیشتر در مورد Incremental Warming توضیح بدی؟ فکر کنم این روش برای سیستم ما مناسب‌تر باشه. 94 | 95 | حسین: 👨‍🏫 البته پیمان جان. Incremental Warming یعنی ما کش رو به تدریج و در طول زمان گرم می‌کنیم، نه یکهو. این روش کمک می‌کنه که فشار روی سیستم کمتر بشه. بذار یه مثال کد بزنم: 96 | 97 | ```python 98 | import redis 99 | import time 100 | import schedule 101 | 102 | r = redis.Redis(host='localhost', port=6379, db=0) 103 | 104 | def incremental_warm(): 105 | # گرفتن لیست آیدی‌های کاربران که هنوز کش نشدن 106 | users_to_cache = get_users_not_in_cache() # فرض کنید این تابع وجود داره 107 | 108 | # گرم کردن 100 کاربر در هر اجرا 109 | for user_id in users_to_cache[:100]: 110 | if not r.exists(f"user:{user_id}"): 111 | data = fetch_from_database(user_id) 112 | r.set(f"user:{user_id}", data) 113 | 114 | print(f"{len(users_to_cache[:100])} کاربر به کش اضافه شدند.") 115 | 116 | # اجرای تابع هر 5 دقیقه 117 | schedule.every(5).minutes.do(incremental_warm) 118 | 119 | while True: 120 | schedule.run_pending() 121 | time.sleep(1) 122 | ``` 123 | 124 | این کد هر 5 دقیقه 100 کاربر رو به کش اضافه می‌کنه. این روش از overload شدن سیستم جلوگیری می‌کنه و اجازه می‌ده که سیستم به تدریج بهینه بشه. 125 | 126 | ماهان: 🤯 وای چقدر جالب! ولی اگه یه کاربر درخواست داده‌ای رو بده که هنوز کش نشده چی می‌شه؟ 127 | 128 | حسین: 😊 سؤال خوبیه ماهان جان. در این حالت، ما از یه تکنیک به اسم "Cache-Aside" یا "Lazy Loading" استفاده می‌کنیم. یعنی اگه داده توی کش نبود، اون رو از دیتابیس می‌گیریم و بعد توی کش ذخیره می‌کنیم. بذار یه مثال کد بزنم: 129 | 130 | ```python 131 | import redis 132 | 133 | r = redis.Redis(host='localhost', port=6379, db=0) 134 | 135 | def get_user_data(user_id): 136 | # سعی می‌کنیم داده رو از کش بگیریم 137 | cached_data = r.get(f"user:{user_id}") 138 | 139 | if cached_data is None: 140 | # اگه داده توی کش نبود، از دیتابیس می‌گیریم 141 | db_data = fetch_from_database(user_id) 142 | 143 | # داده رو توی کش ذخیره می‌کنیم 144 | r.set(f"user:{user_id}", db_data) 145 | 146 | return db_data 147 | 148 | return cached_data 149 | ``` 150 | 151 | این روش اطمینان می‌ده که حتی اگه داده‌ای هنوز کش نشده باشه، کاربر می‌تونه بهش دسترسی داشته باشه. البته اولین درخواست ممکنه کمی کندتر باشه، ولی درخواست‌های بعدی سریع خواهند بود. [🔗](https://docs.microsoft.com/en-us/azure/architecture/patterns/cache-aside) 152 | 153 | مارال: 👏 عالیه حسین. فکر می‌کنم با ترکیب Incremental Warming و Cache-Aside، ما می‌تونیم مشکل Cold Start رو حل کنیم و در عین حال مقیاس‌پذیری سیستم رو هم حفظ کنیم. پیمان، می‌تونی این راه‌حل رو پیاده‌سازی کنی و نتایج رو به تیم گزارش بدی؟ 154 | 155 | پیمان: 😃 حتماً مارال جان. ممنون حسین برای توضیحات کامل. من الان می‌رم روی پیاده‌سازی این راه‌حل کار می‌کنم و نتایج رو به زودی به همه گزارش می‌دم. 156 | 157 | حسین: 🙌 خواهش می‌کنم پیمان جان. اگه حین پیاده‌سازی به مشکلی برخوردی، حتماً بهم بگو. موفق باشی! 158 | 159 | -------------------------------------------------------------------------------- /Correlation ID in Headers - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | 6 | 7 |
8 | 9 | --- 10 | 11 | 12 | 13 | مارال: 14 | سلام بچه‌ها! حالتون چطوره؟ 😊 15 | 16 | می‌خواستم درباره یه مشکلی که داریم صحبت کنم. 17 | 18 | ما نیاز داریم که ریکوئست‌هایی که به سمت ما میان و وارد سرویس‌های مختلف می‌شن رو ردیابی کنیم. 19 | 20 | حسین: 21 | این موضوع خیلی مهمه. 22 | چطوری می‌خواهید این کار رو انجام بدید؟ 23 | 24 | مارال: 25 | به نظر من، بهترین راه اینه که از correlation ID استفاده کنیم. 26 | 27 | اینطوری می‌تونیم هر درخواست رو با یه شماره منحصر به فرد ردیابی کنیم. 28 | 29 | پیمان: 30 | آره، correlation ID خیلی کارآمده! 31 | 32 | این شناسه می‌تونه توی هدر ریکوئست قرار بگیره و در تمام سرویس‌ها منتقل بشه. 🚀 33 | 34 | کیان 🌈: 35 | ببخشید، میشه بیشتر توضیح بدید که این چطوری کار می‌کنه؟ 36 | 37 | حسین: 38 | البته! کیان، تصور کن هر بار که تو یه درخواست اوبر می‌دی، یه شماره مخصوص به اون درخواست بهش تعلق می‌گیره. 39 | 40 | مثل وقتی که تو مدرسه یه کارت شناسایی داری که اسم و عکس تو روش هست. 41 | 42 | ماهان: 43 | دقیقاً! بعد این شماره به همه معلم‌هایی که تو درس می‌دی، منتقل میشه. 44 | 45 | مثلاً معلم ریاضی، معلم علوم، معلم ورزش و... 46 | 47 | حسین: 48 | حالا، برای پیاده‌سازی این موضوع، ما می‌تونیم از یک middleware استفاده کنیم. 49 | 50 | این middleware توی پایتون نوشته میشه و وظیفه‌اش اینه که correlation ID رو به هدر ریکوئست اضافه کنه. 51 | 52 | پیمان: 53 | درست می‌گی. ما می‌تونیم از فریمورک‌هایی مثل Flask یا Django استفاده کنیم. 54 | 55 | حسین: 56 | دقیقاً! وقتی یک ریکوئست جدید به سرور میاد، middleware ما یه correlation ID تولید می‌کنه و اون رو به هدر ریکوئست اضافه می‌کنه. 57 | 58 | مثلاً می‌تونیم از کتابخانه `uuid` برای تولید این شناسه استفاده کنیم. 59 | 60 | ماهان: 61 | و بعد این شناسه به تمام سرویس‌هایی که ریکوئست بهشون ارسال میشه، منتقل میشه. 🔍 62 | 63 | حسین: 64 | درست همینه! و وقتی که مشکلی پیش میاد، می‌تونیم با استفاده از این correlation ID تمام لاگ‌ها و درخواست‌ها رو بررسی کنیم. 65 | 66 | پیمان: 67 | اینطوری می‌تونیم بفهمیم که ریکوئست از کجا شروع شده و چه مراحلی رو طی کرده. 68 | 69 | مارال: 70 | این کار به ما کمک می‌کنه تا مشکلات رو سریع‌تر شناسایی و حل کنیم. 71 | 72 | آیا کسی می‌تونه یک نمونه کد برای پیاده‌سازی این موضوع آماده کنه؟ 73 | 74 | ماهان: 75 | من این کار رو انجام میدم! 76 | 77 | می‌تونم یه middleware بنویسم که correlation ID رو به هدر ریکوئست اضافه کنه. 💻 78 | 79 | حسین: 80 | عالیه! و همچنین باید مطمئن بشیم که این شناسه توی لاگ‌ها هم ثبت میشه تا بعداً بتونیم به راحتی ردیابی کنیم. 81 | 82 | 83 | --- 84 | 85 | 86 | 87 | 88 | 89 | 90 |
-------------------------------------------------------------------------------- /Database Sharding.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | پیمان: حسین، یه مشکلی دارم که نمی‌دونم چطور حلش کنم. ما توی سرویس بک‌اند، وقتی تعداد درخواست‌ها زیاد میشه، دیتابیس‌مون خیلی کند میشه و عملاً سیستم از کار می‌افته. 😕 6 | 7 | حسین: سلام پیمان! خب، بذار ببینم دقیقاً چیه مشکل. می‌گی وقتی تعداد درخواست‌ها زیاد میشه، دیتابیس کند میشه؟ می‌تونی بیشتر توضیح بدی که چه نوع درخواست‌هایی داریم و چطور دیتابیس کند میشه؟ 📉 8 | 9 | پیمان: بله، دقیقاً. مثلاً وقتی تعداد درخواست‌های خواندن و نوشتن همزمان زیاد میشه، دیتابیس نمی‌تونه به همه‌شون جواب بده و سرعتش خیلی پایی ن میاد. این باعث میشه که کاربرها منتظر بمونن و تجربه کاربری بدی داشته باشن. 😟 10 | 11 | حسین: فهمیدم. خب، یکی از راه‌حل‌هایی که می‌تونیم استفاده کنیم، *Database Sharding* هست. این روش به ما کمک می‌کنه که دیتابیس رو به چندین بخش کوچکتر تقسیم کنیم و هر بخش رو روی سرورهای مختلف مدیریت کنیم. اینجوری بار روی هر سرور کمتر میشه و سرعت پاسخ‌دهی افزایش پیدا می‌کنه. 💡 12 | 13 | پیمان: آها، جالبه! ولی میشه بیشتر توضیح بدی که چطور می‌تونیم این کار رو انجام بدیم؟ 🤔 14 | 15 | حسین: حتماً! ببین، اول باید دیتابیس‌مون رو به چندین shard تقسیم کنیم. هر shard شامل یک بخش از داده‌هاست. مثلاً می‌تونیم بر اساس User ID یا هر فیلد دیگری که مناسب باشه، داده‌ها رو تقسیم کنیم. بعد از اون، هر shard رو روی یک سرور مجزا قرار می‌دیم. اینجوری هر سرور فقط مسئول یک بخش از داده‌هاست و بار روی سرورها تقسیم میشه. 📂 16 | 17 | ماهان: حسین، میشه یه مثال توی کد بزنی که بهتر متوجه بشم؟ 🌟 18 | 19 | حسین: حتماً ماهان! فرض کن ما یک جدول کاربران داریم. می‌خوایم بر اساس User ID داده‌ها رو تقسیم کنیم. می‌تونیم اینجوری عمل کنیم: 20 | 21 | ```python 22 | def get_shard(user_id): 23 | # فرض که ما ۴ تا شارد داریم 24 | return user_id % 4 25 | 26 | def save_user(user): 27 | shard_id = get_shard(user.id) 28 | shard_db = get_database_connection(shard_id) 29 | shard_db.save(user) 30 | ``` 31 | 32 | اینجوری هر کاربر بر اساس User ID به یک shard اختصاص داده میشه و داده‌ها توی shard مربوطه ذخیره میشن. این فقط یک مثال ساده بود، توی عمل باید بیشتر به جزئیات توجه کنیم. 🧑‍💻 33 | 34 | مارال: خیلی خوب توضیح دادی حسین! من فکر می‌کنم این راه‌حل می‌تونه مشکل ما رو حل کنه. فقط باید مطمئن بشیم که همه‌ی تیم با این روش آشنا بشن و بتونن به درستی پیاده‌سازیش کنن. 👏 35 | 36 | پیمان: مرسی حسین! خیلی خوب توضیح دادی. حالا می‌تونم شروع کنم به پیاده‌سازی این راه‌حل. اگه به مشکلی برخوردم، دوباره ازت کمک می‌گیرم. 😃 37 | 38 | حسین: خواهش می‌کنم پیمان! هر وقت سوالی داشتی، من اینجام. موفق باشی! 👍 39 | 40 | 41 | مارال: حسین، لطفا برای صحبت‌هات رفرنس (لینک) بده. 42 | 43 | حسین: حتماً مارال! برای اطلاعات بیشتر در مورد _Database Sharding_، می‌تونید به این منابع مراجعه کنید: 44 | 45 | - مقاله‌ای از **MongoDB** که مفاهیم و مثال‌های شاردینگ رو توضیح میده: [Database Sharding: Concepts & Examples - MongoDB](https://www.mongodb.com/resources/products/capabilities/database-sharding-explained)[](https://www.mongodb.com/resources/products/capabilities/database-sharding-explained) 46 | - آموزش **DigitalOcean** که به درک بهتر شاردینگ کمک می‌کنه: [Understanding Database Sharding | DigitalOcean](https://www.digitalocean.com/community/tutorials/understanding-database-sharding)[](https://www.digitalocean.com/community/tutorials/understanding-database-sharding) 47 | - مقاله‌ای از **GeeksforGeeks** که به بررسی سیستم طراحی شاردینگ می‌پردازه: [Database Sharding | System Design - GeeksforGeeks](https://www.geeksforgeeks.org/database-sharding-a-system-design-concept/)[](https://www.geeksforgeeks.org/database-sharding-a-system-design-concept/) 48 | 49 | -------------------------------------------------------------------------------- /Distance Anomaly Issue - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | 6 | 7 |
8 | 9 | 10 | [صدای در زدن] 11 | 12 | مدیر اوپریشن: 13 | سلام بچه‌ها، ببخشید مزاحم کارتون شدم. یه مشکل جدی پیش اومده که باید فوری بررسی کنیم. 14 | 15 | یکی از مشتری‌ها با پشتیبانی تماس گرفته. میگه درخواست اوبر داده، یه راننده هم قبول کرده، ولی وقتی به نقشه نگاه کرده، دیده فاصله راننده تا خودش از فاصله خودش تا مقصد بیشتره! حتی اسکرین‌شات هم فرستاده. 16 | 17 | پیمان: 18 | اوه، این خیلی عجیبه! میشه اسکرین‌شات رو ببینیم؟ 19 | 20 | مدیر اوپریشن: 21 | البته، الان براتون ایمیل می‌کنم. 22 | 23 | [چند لحظه سکوت حین بررسی اسکرین‌شات] 24 | 25 | ماهان: 26 | واقعاً عجیبه! به نظرتون مشکل از کجاست؟ 27 | 28 | حسین: 29 | خب، چند تا احتمال به ذهنم می‌رسه. اول از همه، ممکنه مشکل از الگوریتم تخصیص راننده باشه. 30 | 31 | پیمان: 32 | آره، یا شاید مشکل از نحوه محاسبه فاصله‌هاست. ممکنه داریم فاصله مستقیم رو حساب می‌کنیم نه فاصله واقعی مسیر رو. 33 | 34 | کیان: 35 | ببخشید، یه سوال دارم. مگه قرار نبود سیستم، نزدیک‌ترین راننده رو انتخاب کنه؟ 36 | 37 | حسین: 38 | درسته، کیان جان. اما گاهی فاکتورهای دیگه‌ای هم دخیل میشن. مثلاً ترافیک، یا اینکه راننده در حال اتمام سفر قبلیشه. 39 | 40 | ماهان: 41 | راستی، نکنه مشکل از داده‌های نقشه‌مونه؟ شاید اطلاعات مسیرها به‌روز نیست. 42 | 43 | پیمان: 44 | اوه، یه چیز دیگه هم هست. ممکنه باگی توی نمایش موقعیت راننده روی نقشه باشه. یعنی راننده واقعاً اونجایی نیست که نقشه نشون میده. 45 | 46 | حسین: 47 | همه این‌ها احتمالات خوبی هستن. میشه جزئیات بیشتری از این اتفاق به ما بدید؟ مثلاً اینکه کی و کجا اتفاق افتاده؟ 48 | 49 | مدیر اوپریشن: 50 | این اتفاق دیشب حوالی ساعت 11 شب در منطقه شمال شهر رخ داده. راننده حدود 7 کیلومتر با مسافر فاصله داشته، در حالی که مقصد مسافر فقط 5 کیلومتر دورتر بوده. 51 | 52 | ماهان: 53 | 11 شب؟ نکنه به خاطر ساعت کاری راننده‌ها باشه؟ شاید تعداد راننده‌های فعال کم بوده. 54 | 55 | پیمان: 56 | یا شاید به خاطر ترافیک شبانه و مسیرهای یک‌طرفه، راننده نزدیک‌تر مجبور بوده مسیر طولانی‌تری رو طی کنه. 57 | 58 | مارال: 59 | خب، بیاید همه احتمالات رو جمع‌بندی کنیم. 60 | 61 | 1. ممکنه مشکل از الگوریتم تخصیص راننده باشه. 62 | 2. ممکنه نحوه محاسبه فاصله‌ها اشتباه باشه. 63 | 3. احتمال داره داده‌های نقشه به‌روز نباشن. 64 | 4. ممکنه باگی در نمایش موقعیت راننده روی نقشه وجود داشته باشه. 65 | 5. تعداد راننده‌های فعال ممکنه در ساعت‌های خاص کم باشه. 66 | 6. ترافیک و مسیرهای یک‌طرفه هم می‌تونن تأثیر بذارند. 67 | 7. ممکنه راننده به اشتباه مقصد رو وارد کرده باشه و سیستم این رو در نظر نگرفته باشه. 68 | 8. شاید راننده در حال انجام یک سفر دیگه بوده و سیستم نتونسته به درستی این رو مدیریت کنه. 69 | 9. ممکنه مشکل از GPS دستگاه راننده باشه که موقعیت دقیق رو نشون نداده. 70 | 10. شاید راننده به دلایلی مثل تعمیرات جاده‌ای مجبور به تغییر مسیر شده باشه. 71 | 72 | حسین: 73 | عالیه مارال! حالا که همه احتمالات رو داریم، می‌تونیم کار رو شروع کنیم. پیمان، میشه لطفاً لاگ‌های سیستم تخصیص راننده رو برای اون زمان چک کنی؟ ماهان، تو هم لطفاً داده‌های نقشه و ترافیک اون منطقه رو بررسی کن. من هم میرم سراغ بررسی الگوریتم محاسبه فاصله. 74 | 75 | 76 | 77 | 78 | 79 |
-------------------------------------------------------------------------------- /Feature Flags (Feature Toggle) - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 |
6 | 7 | 8 | مارال: 9 | سلام بچه‌ها! 😊 امروز می‌خوام یه موضوع جدید رو باهاتون در میون بذارم. 10 | 11 | حسین: 12 | سلام مارال! 🤔 چی شده؟ 13 | 14 | مارال: 15 | می‌دونید که ما همیشه در حال توسعه و بهبود اپلیکیشن اوبر هستیم. حالا یه ایده جدید به ذهنمون رسیده که می‌خوایم پیاده‌سازیش کنیم. ولی مشکل اینجاست که نمی‌دونیم این ایده چقدر موفق میشه و مشتری‌ها ازش استقبال می‌کنن یا نه. 😕 16 | 17 | پیمان: 18 | خب چیکار می‌خواید بکنید؟ 🤨 19 | 20 | مارال: 21 | به نظر من بهترین راه اینه که از Feature Flags استفاده کنیم. 🚀 22 | 23 | حسین: 24 | Feature Flags؟ 🤔 یعنی چی؟ 25 | 26 | مارال: 27 | Feature Flags یا Feature Toggle به ما امکان می‌ده که ویژگی‌های جدید رو بدون نیاز به ریلیز مجدد، فعال یا غیرفعال کنیم. 🌟 28 | 29 | ماهان: 30 | 😮 واقعاً عجیبه! یعنی می‌تونیم ویژگی‌های جدید رو به صورت آزمایشی در اختیار بخشی از کاربرا قرار بدیم؟ 31 | 32 | مارال: 33 | دقیقاً! اینطوری می‌تونیم ببینیم این ویژگی‌ها چقدر موفق هستن و بر اساس بازخورد کاربرا تصمیم بگیریم که فعالش نگه داریم یا نه. 👍 34 | 35 | کیان: 36 | واااای، پس می‌تونیم به راحتی ویژگی‌های جدید رو امتحان کنیم؟ 😍 37 | 38 | مارال: 39 | بله کیان جان! و اگه دیدیم که ویژگی خاصی مورد استقبال قرار نگرفت، می‌تونیم به سرعت اون رو غیرفعال کنیم. ⚡ 40 | 41 | پیمان: 42 | 🤔 ولی چطوری می‌خوایم این کار رو انجام بدیم؟ یعنی چه تغییراتی باید توی کد ایجاد کنیم؟ 43 | 44 | حسین: 45 | خب، برای پیاده‌سازی Feature Flags، ما باید یه جایی توی کد خودمون شرط بذاریم که چک کنه آیا اون ویژگی فعال هست یا نه. 🔍 46 | 47 | مارال: 48 | دقیقاً! و این شرط می‌تونه بر اساس یه `Environment variable` یا یه فایل تنظیمات باشه. 📄 49 | 50 | ماهان: 51 | 🤔 یعنی مثلاً توی یه فایل جداگانه مقدار این متغیر رو تغییر بدیم؟ 52 | 53 | حسین: 54 | بله! مثلاً می‌تونیم یه فایل JSON یا YAML داشته باشیم که توش تنظیمات مربوط به Feature Flags رو نگه داریم. 🗂️ 55 | 56 | پیمان: 57 | 😮 پس هر بار که بخوایم یه ویژگی رو فعال یا غیرفعال کنیم، فقط کافیه توی این فایل تنظیمات تغییر ایجاد کنیم؟ 58 | 59 | مارال: 60 | بله پیمان! اینطوری دیگه نیازی نیست که کل برنامه رو ریلیز کنیم. 👍 61 | 62 | کیان: 63 | واااای، پس همه چی خیلی راحت میشه! 😃 64 | 65 | حسین: 66 | دقیقاً! و یه نکته مهم اینه که باید مراقب باشیم که کد مربوط به ویژگی‌های غیرفعال رو از برنامه پاک نکنیم. ⚠️ 67 | 68 | ماهان: 69 | 🤔 چرا؟ مگه چه اتفاقی می‌افته؟ 70 | 71 | حسین: 72 | خب، اگه کد اون ویژگی‌ها رو پاک کنیم و بعداً بخوایم دوباره فعالش کنیم، باید دوباره برنامه رو توسعه بدیم و ریلیز کنیم. 😕 73 | 74 | مارال: 75 | دقیقاً! به همین دلیل همیشه باید کد ویژگی‌های غیرفعال رو توی برنامه نگه داریم، ولی اجراش نکنیم. 🛠️ 76 | 77 | 78 | 79 | 80 |
-------------------------------------------------------------------------------- /Graceful Shutdown - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | #### مدیر اوپریشن (با عجله وارد اتاق می‌شه): 6 | 7 | بچه‌ها، یه مشکل خیلی جدی داریم! 😰 چند تا از مشتری‌ها‌مون تماس گرفتن و گفتن که پرداخت‌هاشون ناقص مونده. 8 | 9 | یکیشون، آقای محمدی، گفته که ۲۰۰ هزار تومن از حسابش کم شده ولی کیف پولش شارژ نشده. خانم رضایی هم گفته که دو بار پول از حسابش رفته. 10 | 11 | حتی یکی از رانندگان هم زنگ زده و گفته که کرایه‌ی آخرین سفرش رو دریافت نکرده، در حالی که مسافر گفته پول پرداخت شده. 🚕💸 12 | 13 | این داره اعتبار ما رو زیر سوال می‌بره. باید سریع حلش کنیم! 😓 14 | 15 | #### پیمان: 16 | 17 | اوه اوه، این خیلی بده. بذارید من یه نگاهی به لاگ‌های سیستم بندازم. 🧐 18 | 19 | (بعد از چند دقیقه بررسی) 20 | 21 | خب، به نظر میاد مشکل از سرور پرداخت ماست. وقتی سرور ری‌استارت می‌شه یا به هر دلیلی قطع می‌شه، تراکنش‌های در حال انجام نیمه‌کاره رها می‌شن و این باعث می‌شه که گاهی پول از حساب کاربر کم بشه ولی سفر ثبت نشه، یا برعکس. 😓 22 | 23 | #### حسین: 24 | 25 | ممنون پیمان جان که بررسی کردی. این دقیقاً همون مشکلیه که با Graceful Shutdown می‌تونیم حلش کنیم. 💡 26 | 27 | #### پیمان: 28 | 29 | می‌شه بیشتر توضیح بدی؟ 🤔 30 | 31 | #### حسین: 32 | 33 | البته. Graceful Shutdown یه تکنیکه که به سرور اجازه می‌ده قبل از خاموش شدن، کارهای در حال انجام رو تموم کنه. 🔗 در مورد سرویس پرداخت ما، این یعنی: 34 | 35 | 1. وقتی سیگنال خاموشی یا ری‌استارت دریافت می‌شه، سرور دیگه تراکنش جدید قبول نمی‌کنه. 36 | 2. به تراکنش‌های در حال انجام اجازه می‌ده تا کامل بشن. 37 | 3. اگه تراکنشی نیمه‌کاره موند، اون رو توی یه صف ذخیره می‌کنه تا بعد از راه‌اندازی مجدد، اون تراکنش‌ها رو پردازش کنه. 38 | 4. بعد از اتمام همه تراکنش‌ها، سرور به طور کامل خاموش می‌شه. 39 | 40 | این روش باعث می‌شه هیچ تراکنشی نیمه‌کاره رها نشه و مشکلاتی که الان داریم پیش نیاد. 41 | 42 | 43 | #### مدیر اوپریشن: 44 | 45 | واو، این خیلی عالی به نظر می‌رسه! چقدر طول می‌کشه تا این رو پیاده‌سازی کنیم و مشکل مشتری‌هامون رو حل کنیم؟ 🕒 46 | 47 | #### حسین: 48 | 49 | با توجه به پیچیدگی سیستم فعلی‌مون، فکر می‌کنم بتونیم ظرف 2-3 روز این تغییرات رو اعمال کنیم و تست کنیم. بعد از اون، باید: 50 | 51 | 1. یه اسکریپت بنویسیم که تراکنش‌های ناتموم رو شناسایی و تصحیح کنه. 52 | 2. با تیم پشتیبانی مشتری هماهنگ کنیم تا با مشتری‌هایی که مشکل داشتن تماس بگیرن و مشکلشون رو حل کنن. 53 | 3. یه سیستم مانیتورینگ قوی‌تر راه بندازیم که این جور مشکلات رو سریع‌تر شناسایی کنه. 54 | 55 | کل این پروسه احتمالاً حدود یک هفته طول می‌کشه. 56 | 57 | #### مارال: 58 | 59 | عالیه. این باید اولویت اصلی تیم باشه. لطفاً همین الان شروع کنید. حسین، تو مسئول این پروژه هستی. هر منبعی که نیاز داری در اختیارت می‌ذارم. 👏 60 | 61 | #### پیمان: 62 | 63 | حتماً، من و ماهان از همین الان شروع می‌کنیم به پیاده‌سازی. مرسی حسین جان برای راهنمایی‌هات. 😊 64 | 65 | #### ماهان: 66 | 67 | منم می‌تونم روی اون اسکریپت تصحیح تراکنش‌ها کار کنم. فکر کنم بتونم تا فردا یه نسخه اولیه آماده کنم. 💪 68 | 69 | #### حسین: 70 | 71 | عالیه بچه‌ها. من یه جلسه با تیم پشتیبانی مشتری می‌ذارم تا فرآیند رسیدگی به مشکلات مشتری‌ها رو هماهنگ کنیم. هر سوالی داشتید در خدمتم. بریم که یه سرویس پرداخت مطمئن‌تر بسازیم! 💪 72 | 73 | #### مدیر اوپریشن: 74 | 75 | ممنون از همگی. لطفاً هر روز یه آپدیت از پیشرفت کار به من بدید. من می‌رم که به مدیرعامل گزارش بدم. امیدوارم بتونیم اعتماد مشتری‌هامون رو دوباره جلب کنیم. 🙏 76 | 77 | -------------------------------------------------------------------------------- /Hash Table Data Structure - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 |
6 | 7 | ### 8 | 9 | #### کیان: 10 | 11 | بچه‌ها، میشه یکی بهم توضیح بده که Hash Tables چیه؟ 🤔 12 | 13 | #### پیمان: 14 | 15 | البته کیان جان. Hash Table یه ساختار داده‌ست که برای ذخیره‌سازی و بازیابی داده‌ها با سرعت بالا استفاده می‌شه. 🗂️🔗 [Hash Table](https://en.wikipedia.org/wiki/Hash_table) 16 | 17 | #### ماهان: 18 | 19 | بذار یه جور ساده‌تر بگم. فرض کن یه دفترچه تلفن داری که توش اسم و شماره تلفن آدم‌ها رو می‌نویسی. حالا اگه بخوای شماره تلفن یه نفر رو پیدا کنی، باید همه دفترچه رو بگردی، درسته؟ ولی اگه از Hash Table استفاده کنی، می‌تونی خیلی سریع شماره رو پیدا کنی. 📒🔗 20 | 21 | #### حسین: 22 | 23 | دقیقاً. در Hash Table، از یه تابع به نام Hash Function استفاده می‌کنیم که یه مقدار ورودی (مثل اسم) رو به یه عدد تبدیل می‌کنه. این عدد به عنوان کلید استفاده می‌شه و داده‌ها رو توی یه آرایه ذخیره می‌کنیم. مثلاً اگه اسم "علی" رو داشته باشیم، تابع Hash یه عدد مثل 5 تولید می‌کنه و ما شماره تلفن علی رو توی خونه 5 آرایه ذخیره می‌کنیم 24 | 25 | #### مارال: 26 | 27 | یه مثال ساده بزنم. فرض کن داریم یه لیست از دانشجوها و نمراتشون. اگه بخوایم نمره یه دانشجو رو سریع پیدا کنیم، می‌تونیم از Hash Table استفاده کنیم. اسم دانشجو رو به عنوان کلید و نمره رو به عنوان مقدار ذخیره می‌کنیم. اینجوری هر وقت بخوایم نمره یه دانشجو رو پیدا کنیم، فقط کافیه کلید رو به تابع Hash بدیم و مستقیماً به مقدار دسترسی پیدا کنیم. 🎓🔗 28 | 29 | #### کیان: 30 | 31 | آها، حالا فهمیدم. ولی اگه دو تا اسم مختلف همون کلید رو تولید کنن، چی می‌شه؟ 🤨 32 | 33 | #### حسین: 34 | 35 | این یه مسئله به نام Collision هست. برای حل این مشکل، روش‌های مختلفی وجود داره. یکی از رایج‌ترین روش‌ها، استفاده از Linked List هست. یعنی اگه دو تا کلید یه مقدار Hash یکسان تولید کنن، اون‌ها رو به صورت یه لیست توی همون خونه آرایه ذخیره می‌کنیم. 36 | 37 | #### پیمان: 38 | 39 | یه روش دیگه هم Open Addressing هست. توی این روش، اگه یه خونه پر باشه، دنبال خونه بعدی خالی می‌گردیم تا داده رو ذخیره کنیم. این روش‌ها کمک می‌کنن که Hash Table بهینه‌تر عمل کنه و سرعت دسترسی به داده‌ها بالا بمونه. 🔗 [Open Addressing](https://www.geeksforgeeks.org/hashing-set-3-open-addressing/) 40 | 41 | #### کیان: 42 | 43 | مرسی بچه‌ها، خیلی خوب توضیح دادید. حالا می‌فهمم چرا Hash Table اینقدر مفیده. 😊 44 | 45 | ### لینک‌های مرتبط: 46 | 47 | - [Hash Table](https://en.wikipedia.org/wiki/Hash_table) 48 | - [Hash Function](https://www.geeksforgeeks.org/hashing-data-structure/) 49 | - [Open Addressing](https://www.geeksforgeeks.org/hashing-set-3-open-addressing/) 50 | 51 | 52 | 53 | 54 |
-------------------------------------------------------------------------------- /KISS Principle.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | ### 6 | 7 | #### کیان: 8 | 9 | بچه‌ها، یکی بهم میگه اصل KISS یعنی چی؟ 😅 یه جا خوندم "Keep It Simple, Stupid"، ولی گیج شدم! 10 | 11 | #### پیمان: 12 | 13 | کیان جان، نترس! اون "Stupid" توهین نیست، بیشتر یه شوخیه برای این‌که یادت بمونه ساده نگه داشتن چیزها بهتره. 😄 14 | 15 | #### ماهان: 16 | 17 | آره دقیقاً! بذار برات یه داستان بگم. فرض کن می‌خوای یه دوچرخه بسازی. 🚲 18 | 19 | #### کیان: 20 | 21 | خب، دارم گوش می‌دم! 🎧 22 | 23 | #### حسین: 24 | 25 | حالا فکر کن یه نفر می‌خواد این دوچرخه رو خیلی خفن کنه. مثلاً براش دکمه‌ی تنظیم سرعت وای‌فای بزاره، یا چراغ‌هایی که با صدا روشن شن! 😅 26 | 27 | #### مارال: 28 | 29 | آخرش چی میشه؟ دوچرخه‌ش اینقدر پیچیده میشه که دیگه حتی رکاب زدن هم سخت میشه! 😵 30 | 31 | #### کیان: 32 | 33 | اوه، یعنی انقدر شلوغش کرده که دیگه نمی‌شه ازش استفاده کرد؟ 34 | 35 | #### پیمان: 36 | 37 | دقیقاً! اصل KISS می‌گه: «همیشه تا جایی که می‌تونی، ساده نگهش دار!» چون طراحی ساده‌تر، بهتر کار می‌کنه و راحت‌تر هم می‌فهمیش. 💡 38 | 39 | #### ماهان: 40 | 41 | توی برنامه‌نویسی هم همینه. مثلاً اگه قراره یه تابع فقط جمع دو عدد رو حساب کنه، دیگه لازم نیست توش ۵۰ تا شرط و حلقه بذاری! 😂 42 | 43 | #### حسین: 44 | 45 | هر چی کدت ساده‌تر باشه، کمتر باگ می‌خوره، راحت‌تر تست میشه، و آدمای دیگه هم سریع‌تر می‌تونن بخوننش. ✨ 46 | 47 | #### کیان: 48 | 49 | پس یعنی اصل KISS می‌گه پیچیدگی اضافه نکنیم؟ 50 | 51 | #### مارال: 52 | 53 | آفرین! بذار مثل یه آشپز ماهر فکر کنیم. اگه یه غذای خوشمزه رو می‌تونی با ۳ تا ماده درست کنی، چرا ۱۰ تا بریزی که فقط طعمش رو خراب کنه؟ 🍳 54 | 55 | #### کیان: 56 | 57 | چه باحال! یعنی تو کدنویسی هم باید مثل آشپزای ماهر عمل کنیم! ساده و خوشمزه! 😋 58 | 59 | #### پیمان: 60 | 61 | 62 | آره کیان جان! حالا اگه دیدی یه چیزی خیلی پیچیده شد، یه نفس بکش و بپرس: «می‌تونم ساده‌ترش کنم؟» این میشه روح KISS! 🧘‍♂️ 63 | بذار برات یه مثال ساده هم بزنم که کامل جا بیفته: 64 | 65 | فرض کن توی یه برنامه می‌خوایم یه تابع داشته باشیم که دو عدد `x` و `y` رو می‌گیره و حاصل جمعشون رو برمی‌گردونه. 66 | 67 | در ساده‌ترین حالت ممکن، این تابع می‌تونه این‌طوری باشه: 68 | 69 |
70 | 71 | ```python 72 | def sum(x, y): 73 | return x + y 74 | ``` 75 | 76 |
77 | 78 | این تابع خیلی ساده و سرراسته، معلومه چی‌کار می‌کنه و همون کار رو به بهترین شکل انجام می‌ده. 79 | 80 | اما بعضی‌ها همین تابع رو اینطوری می‌نویسن: 81 | 82 |
83 | 84 | 85 | ```python 86 | def sum(*args): 87 | sum_value = 0 88 | for i in args: 89 | sum_value += i 90 | return sum_value 91 | ``` 92 | 93 |
94 | درسته که این نسخه هم کار می‌کنه و حتی انعطاف‌پذیرتره، ولی برای هدف ساده‌ای مثل جمع دو عدد، پیچیدگی غیرضروری داره. 95 | هر چی کد ساده‌تر باشه، در آینده نگهداری و توسعه‌ش هم راحت‌تره. 96 | 97 | 98 | 99 | #### کیان: 100 | 101 | مرسی بچه‌ها! دیگه این KISS رو هیچ‌وقت فراموش نمی‌کنم. از حالا هر وقت یه چیز طراحی می‌کنم، می‌پرسم: آیا این واقعاً ساده‌ست؟ 🤓 102 | 103 | -------------------------------------------------------------------------------- /Lazy Loading vs Eager Loading - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | 6 | پیمان: 😕 بچه‌ها، من یه مشکل جدی پیدا کردم توی اپلیکیشن Uber ما. وقتی کاربرها لیست سفرهاشون رو لود می‌کنن، سیستم خیلی کند میشه. انگار داره همه اطلاعات رو یکجا می‌کشه بالا. نمی‌دونم چجوری باید حلش کنم. 7 | 8 | حسین: 🤔 اوه، این می‌تونه مشکل بزرگی باشه پیمان جان. بذار ببینم دقیقاً مشکل کجاست. میشه یکم بیشتر توضیح بدی که چه اتفاقی میفته؟ 9 | 10 | پیمان: 😟 آره حتماً. ببین، وقتی کاربر وارد صفحه تاریخچه سفرهاش میشه، ما داریم تمام سفرهای قبلی رو با جزئیات کامل از دیتابیس می‌کشیم بیرون. این شامل اطلاعات راننده، مسیر، قیمت و حتی نظرات هم میشه. برای کاربرهایی که سفرهای زیادی دارن، این پروسه خیلی طول می‌کشه و اپ کند میشه. 11 | 12 | حسین: 🧐 آهان، متوجه شدم. ببین پیمان جان، به نظرم ما اینجا می‌تونیم از تکنیک Lazy Loading در مقابل Eager Loading استفاده کنیم. [🔗](https://docs.microsoft.com/en-us/ef/core/querying/related-data/eager) 13 | 14 | ماهان: 😅 ببخشید که می‌پرم وسط حرفتون، ولی میشه یکم بیشتر توضیح بدین؟ من تازه شروع کردم و این اصطلاحات برام جدیده. 15 | 16 | حسین: 😊 البته ماهان جان، خوشحالم که می‌پرسی. ببین، Eager Loading یعنی ما همه داده‌های مرتبط رو یکجا و همون اول کار لود می‌کنیم. [🔗](https://www.entityframeworktutorial.net/eager-loading-in-entity-framework.aspx) این همون کاریه که الان داریم انجام میدیم و باعث کندی سیستم شده. اما Lazy Loading یعنی ما داده‌ها رو فقط وقتی که لازم داریم، لود می‌کنیم. 17 | 18 | پیمان: 🤨 خب این چطوری می‌تونه به ما کمک کنه؟ 19 | 20 | حسین: 👨‍🏫 ببینید بچه‌ها، ایده اینه که ما اول فقط اطلاعات اصلی سفرها رو لود کنیم، مثل تاریخ و مقصد. بعد وقتی کاربر روی یه سفر خاص کلیک کرد، اون موقع جزئیات بیشتر رو لود می‌کنیم. این باعث میشه که صفحه اصلی خیلی سریع‌تر لود بشه. 21 | 22 | ماهان: 🙋‍♂️ میشه یه مثال کد بزنید؟ اینجوری بهتر متوجه میشم. 23 | 24 | حسین: 😃 حتماً ماهان جان. ببین، الان کد ما احتمالاً چیزی شبیه این هست: 25 | 26 | ```python 27 | def get_user_trips(user_id): 28 | return Trip.objects.filter(user_id=user_id).select_related('driver').prefetch_related('reviews') 29 | ``` 30 | 31 | این کد همه چیز رو یکجا میاره. اما می‌تونیم اینطوری تغییرش بدیم: 32 | 33 | ```python 34 | def get_user_trips(user_id): 35 | return Trip.objects.filter(user_id=user_id).only('id', 'date', 'destination') 36 | 37 | def get_trip_details(trip_id): 38 | return Trip.objects.select_related('driver').prefetch_related('reviews').get(id=trip_id) 39 | ``` 40 | 41 | حالا `get_user_trips` فقط اطلاعات اصلی رو میاره، و `get_trip_details` رو وقتی صدا می‌زنیم که کاربر جزئیات یه سفر خاص رو خواست. [🔗](https://docs.djangoproject.com/en/3.2/ref/models/querysets/#select-related) 42 | 43 | پیمان: 🤯 وای، این عالیه! فکر کنم خیلی به بهبود عملکرد کمک کنه. 44 | 45 | مارال: 👩‍💼 سلام بچه‌ها، ببخشید که دیر اومدم. حسین جان، این ایده‌ت خیلی خوبه. فقط یه سوال، این تغییر روی API ما هم تاثیر میذاره؟ 46 | 47 | حسین: 🤓 سلام مارال جان، سوال خوبیه. بله، احتمالاً باید API رو هم آپدیت کنیم. می‌تونیم دو اندپوینت جدا داشته باشیم: 48 | 49 | 1. `/api/trips/` برای لیست کلی سفرها 50 | 2. `/api/trips//` برای جزئیات هر سفر 51 | 52 | اینجوری کلاینت‌ها هم می‌تونن داده‌ها رو به صورت تدریجی دریافت کنن. [🔗](https://www.django-rest-framework.org/api-guide/viewsets/#readonlymodelviewset) 53 | 54 | مارال: 👍 عالیه. پیمان جان، می‌تونی این تغییرات رو اعمال کنی و یه تست پرفورمنس بگیری؟ می‌خوام ببینم چقدر بهبود حاصل میشه. 55 | 56 | پیمان: 😊 حتماً! من همین الان شروع می‌کنم. ممنون حسین جان بابت راهنمایی‌ت. 57 | 58 | حسین: 🙌 خواهش می‌کنم. یادتون باشه، گاهی اوقات بهینه‌سازی یعنی انجام ندادن کارها تا وقتی که واقعاً لازم بشن. Lazy Loading دقیقاً همین کار رو می‌کنه. [🔗](https://en.wikipedia.org/wiki/Lazy_loading) 59 | 60 | ماهان: 🤓 من خیلی یاد گرفتم. مرسی که اینقدر خوب توضیح دادید. 61 | 62 | مارال: 😄 خیلی خوبه که تیم اینقدر خوب با هم کار می‌کنه. حسین جان، لطفاً یه داکیومنت هم در مورد این تغییر بنویس تا بقیه تیم هم در جریان باشن. 63 | -------------------------------------------------------------------------------- /Lowest Common Ancestor in a Binary Tree (LCA) - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | ### 14 | 15 | #### کیان: 16 | 17 | بچه‌ها، میشه بهم بگید Lowest Common Ancestor in a Binary Tree چیه؟ 🤔 18 | 19 | #### پیمان: 20 | 21 | کیان جان، بذار یه جوری برات توضیح بدم که راحت‌تر متوجه بشی. فکر کن یه درخت خانوادگی داریم. 🌳👨‍👩‍👧‍👦 22 | 23 | ``` 24 | Grandfather 25 | / \ 26 | Father Uncle 27 | | | 28 | Kian Cousin 29 | ``` 30 | 31 | #### ماهان: 32 | 33 | آره، مثل درخت خانوادگی خودت. تو، مامان و بابات، و مامان بزرگ و بابابزرگت. 👪 34 | 35 | #### کیان: 36 | 37 | آها، فهمیدم. خب بعدش چی؟ 38 | 39 | #### حسین: 40 | 41 | ببین کیان جان، حالا فرض کن می‌خوایم بدونیم نزدیک‌ترین جد مشترک تو و دختر عموت کیه. یعنی اولین نفری که هم جد توئه، هم جد دختر عموت. 🕵️‍♂️ 42 | 43 | #### مارال: 44 | 45 | دقیقاً! و این تو درخت‌های دودویی (Binary Tree) هم همینطوره. ما دنبال نزدیک‌ترین گره مشترک بین دو گره هستیم. 🌿 46 | 47 | #### کیان: 48 | 49 | اوه، پس یعنی تو مثال خانواده ما، جد مشترک من و دختر عموم میشه بابابزرگمون؟ 50 | 51 | #### پیمان: 52 | 53 | آفرین کیان! دقیقاً همینطوره. تو درخت‌های کامپیوتری هم ما دنبال همچین چیزی می‌گردیم. 🖥️ 54 | 55 | #### ماهان: 56 | 57 | بذار یه مثال دیگه بزنم. فرض کن یه درخت داریم که توش عددها رو گذاشتیم. مثلاً یه درخت که این شکلیه: 58 | ``` 59 | 10 60 | / \ 61 | 5 15 62 | / \ / \ 63 | 3 7 12 18 64 | ``` 65 | 66 | حالا اگه بخوایم نزدیک‌ترین جد مشترک بین عدد 3 و 7 رو پیدا کنیم، باید ببینیم اولین عددی که هم به 3 و هم به 7 می‌رسه چیه. تو این مثال، عدد 5 هست. 🧮 67 | 68 | #### کیان: 69 | 70 | آها، پس عدد 5 میشه همون "بابابزرگ" مشترک بین 3 و 7! 😊 71 | 72 | #### حسین: 73 | 74 | آفرین کیان! دقیقاً همینطوره. توی درخت‌های کامپیوتری، ما دنبال نزدیک‌ترین گره مشترک بین دو گره می‌گردیم. این گره رو می‌گیم Lowest Common Ancestor یا LCA. 🌳 75 | 76 | #### مارال: 77 | 78 | حالا فکر کن این درخت رو داریم: 79 | ``` 80 | 10 81 | / \ 82 | 5 15 83 | / \ / \ 84 | 3 7 12 18 85 | ``` 86 | اگه بخوایم نزدیک‌ترین جد مشترک بین عدد 3 و 12 رو پیدا کنیم، باید ببینیم اولین عددی که هم به 3 و هم به 12 می‌رسه چیه. تو این مثال، عدد 10 هست. 🧩 87 | 88 | #### کیان: 89 | 90 | وای چه جالب! یعنی کامپیوترها هم مثل ما دنبال فامیل‌هاشون می‌گردن؟ 😃 91 | 92 | #### حسین: 93 | 94 | دقیقاً کیان جان! کامپیوترها هم گاهی نیاز دارن "فامیل‌های" نزدیک اطلاعات رو پیدا کنن. این کمک می‌کنه که سریع‌تر و بهتر کار کنن. 🚀 95 | 96 | #### مارال: 97 | 98 | آفرین کیان، خیلی خوب متوجه شدی. حالا هر وقت درباره LCA یا Lowest Common Ancestor شنیدی، یادت میاد که داریم دنبال نزدیک‌ترین "بابابزرگ" مشترک می‌گردیم! 👴 99 | 100 | #### کیان: 101 | 102 | مرسی بچه‌ها! خیلی جالب بود. حالا می‌تونم به دوستام هم توضیح بدم! 😊 103 | 104 | ### لینک‌های مرتبط: 105 | 106 | - [Lowest Common Ancestor (توضیح ساده)](https://www.geeksforgeeks.org/lowest-common-ancestor-binary-tree-set-1/) 🔗 107 | 108 | 109 | 110 |
-------------------------------------------------------------------------------- /Map Matching and Sensor Fusion for Improved Driver Navigation.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 |
6 | 7 | 8 | #### پیمان: 9 | 10 | بچه‌ها، من یه مشکل جدید توی سیستم نظارت بر رانندگان پیدا کردم. 😟 وقتی رانندگان به مناطقی با سیگنال GPS ضعیف می‌رسن، نمی‌تونیم موقعیت دقیقشون رو تشخیص بدیم. این باعث می‌شه که گاهی اوقات مسیر اشتباه نشون داده بشه یا زمان رسیدن به مقصد اشتباه محاسبه بشه. 🛑 11 | 12 | #### مارال: 13 | 14 | این واقعاً مشکل مهمیه پیمان. می‌تونی بیشتر توضیح بدی که چه اتفاقی می‌افته؟ 🤔 15 | 16 | #### پیمان: 17 | 18 | البته. مثلاً وقتی راننده وارد یه منطقه با ساختمون‌های بلند می‌شه، سیگنال GPS ضعیف می‌شه و ما نمی‌تونیم دقیقاً بفهمیم راننده کجاست. گاهی اوقات حتی به نظر می‌رسه راننده از جاده خارج شده، در حالی که در واقع روی جاده در حال حرکته. 🏙️🚗 19 | 20 | #### حسین: 21 | 22 | پیمان جان، این مشکل به نظر میاد مربوط به "GPS Signal Loss in Urban Areas" باشه. برای حل این مشکل، می‌تونیم از ترکیبی از تکنیک‌های "Map Matching" و "Sensor Fusion" استفاده کنیم. 23 | 24 | #### پیمان: 25 | 26 | Map Matching و Sensor Fusion؟ می‌شه بیشتر توضیح بدی؟ 🤔 27 | 28 | #### حسین: 29 | 30 | البته. Map Matching یک تکنیکه که موقعیت تقریبی وسیله نقلیه رو با نقشه‌های دیجیتال تطبیق می‌ده تا مطمئن بشیم که ماشین روی جاده قرار داره. Sensor Fusion هم ترکیب داده‌های مختلف از سنسورهای گوشی راننده مثل GPS، شتاب‌سنج و ژیروسکوپ هست. 🗺️📱 31 | 32 | #### مارال: 33 | 34 | این خیلی جالب به نظر می‌رسه. حسین، می‌تونی یه مثال کد بزنی که ببینیم چطور می‌شه این رو پیاده‌سازی کرد؟ 📋 35 | 36 | #### حسین: 37 | 38 | حتماً. این یه نمونه کد ساده برای پیاده‌سازی Map Matching و Sensor Fusion در Python هست: 39 | 40 | ```python 41 | import numpy as np 42 | from sklearn.neighbors import KDTree 43 | 44 | class MapMatcher: 45 | def __init__(self, road_network): 46 | self.road_network = road_network 47 | self.kdtree = KDTree(road_network) 48 | 49 | def match_to_road(self, gps_position): 50 | # Find the closest point on the road network 51 | distance, index = self.kdtree.query([gps_position], k=1) 52 | return self.road_network[index[0][0]] 53 | 54 | class SensorFusion: 55 | def __init__(self): 56 | self.last_position = None 57 | self.last_velocity = np.array([0, 0]) 58 | 59 | def update(self, gps, accelerometer, gyroscope, time_delta): 60 | if self.last_position is None: 61 | self.last_position = gps 62 | return gps 63 | 64 | # Predict new position based on last velocity 65 | predicted_position = self.last_position + self.last_velocity * time_delta 66 | 67 | # Update velocity based on accelerometer data 68 | acceleration = np.array(accelerometer[:2]) # Only use x and y 69 | self.last_velocity += acceleration * time_delta 70 | 71 | # Combine GPS and predicted position 72 | if gps is not None: 73 | alpha = 0.7 # Weight for GPS vs prediction 74 | fused_position = alpha * np.array(gps) + (1 - alpha) * predicted_position 75 | else: 76 | fused_position = predicted_position 77 | 78 | self.last_position = fused_position 79 | return fused_position.tolist() 80 | 81 | # Usage 82 | road_network = np.array([[0, 0], [1, 1], [2, 2], [3, 3]]) # Simplified road network 83 | map_matcher = MapMatcher(road_network) 84 | sensor_fusion = SensorFusion() 85 | 86 | # Simulate some sensor readings 87 | gps_reading = [1.1, 0.9] 88 | accelerometer_reading = [0.1, 0.1, 9.8] # x, y, z 89 | gyroscope_reading = [0, 0, 0.1] # x, y, z 90 | time_delta = 1.0 # 1 second 91 | 92 | fused_position = sensor_fusion.update(gps_reading, accelerometer_reading, gyroscope_reading, time_delta) 93 | matched_position = map_matcher.match_to_road(fused_position) 94 | 95 | print(f"Fused position: {fused_position}") 96 | print(f"Matched position on road: {matched_position}") 97 | ``` 98 | 99 | این کد یک نمونه ساده از ترکیب Map Matching و Sensor Fusion رو نشون می‌ده. ما از داده‌های GPS، شتاب‌سنج و ژیروسکوپ استفاده می‌کنیم تا موقعیت دقیق‌تری به دست بیاریم و بعد اون رو با نقشه جاده تطبیق می‌دیم. 🔗 [Sensor Fusion](https://en.wikipedia.org/wiki/Sensor_fusion) 100 | 101 | #### ماهان: 102 | 103 | وای حسین، این خیلی جالبه! یعنی با این روش می‌تونیم حتی وقتی GPS ضعیفه، موقعیت دقیق راننده رو روی جاده پیدا کنیم؟ 😃 104 | 105 | #### حسین: 106 | 107 | دقیقاً ماهان جان! این روش به ما کمک می‌کنه که حتی در شرایطی که سیگنال GPS ضعیف می‌شه، بتونیم موقعیت راننده رو با دقت بیشتری تخمین بزنیم و مطمئن بشیم که این موقعیت روی جاده قرار داره. 🚗 108 | 109 | #### مارال: 110 | 111 | عالیه. این راه‌حل خیلی مناسب برای سیستم ما به نظر می‌رسه. حسین، لطفاً با تیم توسعه همکاری کن تا این سیستم رو پیاده‌سازی کنیم. پیمان، ممنون که این مسئله رو مطرح کردی. این می‌تونه دقت سیستم ناوبری ما رو خیلی بهبود بده. 👏 112 | 113 | #### پیمان: 114 | 115 | خیلی ممنون حسین. این راه‌حل واقعاً هوشمندانه‌ست. من و ماهان آماده‌ایم که روی پیاده‌سازیش کار کنیم. 😊 116 | 117 | ### لینک‌های مرتبط: 118 | 119 | - [Map Matching](https://en.wikipedia.org/wiki/Map_matching) 🔗 120 | - [Sensor Fusion](https://en.wikipedia.org/wiki/Sensor_fusion) 🔗 121 | - [GPS and Map Matching for Navigation](https://www.mdpi.com/1424-8220/20/17/4685) 🔗 122 | 123 |
-------------------------------------------------------------------------------- /Multiplexing vs Demultiplexing - uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | کیان: 🌈 حسین، من یه سوال دیگه دارم. میشه Multiplexing و Demultiplexing رو بهم توضیح بدی؟ اینا چی هستن و کجاها ازشون استفاده میشه؟ 13 | 14 | حسین: 😊 سلام کیان جان! سوال خیلی جالبی پرسیدی. بذار برات توضیح بدم که Multiplexing و Demultiplexing چی هستن و کجا کاربرد دارن. 15 | 16 | 1. **Multiplexing (ترکیب کردن):** 17 | فکر کن داری با دوستات توی یه اتاق بازی می‌کنی. هر کدوم از شما یه اسباب بازی داره و می‌خواید همه رو به اتاق دیگه ببرید. به جای اینکه هر کدوم جداگانه برید، همه اسباب بازی‌ها رو توی یه جعبه بزرگ می‌ذارید و با هم می‌برید. 18 | 19 | در دنیای کامپیوترها: 20 | - Multiplexing یعنی ترکیب کردن چند سیگنال یا داده مختلف در یک سیگنال واحد. 21 | - این کار باعث میشه بتونیم از یک مسیر ارتباطی برای انتقال چندین نوع داده استفاده کنیم. 22 | 23 | 2. **Demultiplexing (جدا کردن):** 24 | حالا وقتی به اتاق جدید می‌رسید، باید اسباب بازی‌ها رو از جعبه دربیارید و به هر کس اسباب بازی خودش رو بدید. 25 | 26 | در دنیای کامپیوترها: 27 | - Demultiplexing یعنی جدا کردن سیگنال‌های ترکیب شده و رسوندن هر کدوم به مقصد خودش. 28 | - این کار در طرف گیرنده انجام میشه تا هر داده به برنامه یا دستگاه مربوط به خودش برسه. 29 | 30 | کیان: 🌈 اوه، پس مثل اینه که همه چیز رو با هم بفرستیم و بعد جداشون کنیم؟ 31 | 32 | حسین: دقیقاً! آفرین کیان. حالا بذار چند تا مثال از کاربردهاش بزنم: 33 | 34 | 1. **تلویزیون کابلی:** 35 | - Multiplexing: چندین کانال تلویزیونی رو با هم از یک کابل می‌فرستن. 36 | - Demultiplexing: تلویزیون شما کانال مورد نظرتون رو از بین همه کانال‌ها انتخاب می‌کنه. 37 | 38 | 2. **اینترنت:** 39 | - Multiplexing: وقتی چند تا برنامه همزمان از اینترنت استفاده می‌کنن (مثل مرورگر، برنامه چت، بازی آنلاین)، همه داده‌ها با هم فرستاده میشن. 40 | - Demultiplexing: کامپیوتر شما داده‌های دریافتی رو جدا می‌کنه و به هر برنامه می‌فرسته. 41 | 42 | 3. **تلفن همراه:** 43 | - Multiplexing: چندین تماس تلفنی از یک آنتن مخابراتی فرستاده میشن. 44 | - Demultiplexing: هر گوشی فقط تماس مربوط به خودش رو دریافت می‌کنه. 45 | 46 | کیان: 🌈 وای چه باحال! یعنی این باعث میشه از فضا و امکانات بهتر استفاده کنیم؟ 47 | 48 | حسین: 👍 دقیقاً کیان جان! این تکنیک‌ها کمک می‌کنن تا از منابع محدود (مثل کابل‌ها یا فرکانس‌های رادیویی) بهتر استفاده کنیم و اطلاعات بیشتری رو منتقل کنیم. 49 | 50 | کیان: 🌈 مرسی حسین جون! حالا خیلی بهتر فهمیدم. میشه یه روز بریم و از نزدیک ببینیم چطوری کار می‌کنه؟ 51 | 52 | حسین: 😊 حتماً کیان جان! خیلی خوشحالم که اینقدر مشتاقی. شاید بتونیم یه روز از یه مرکز مخابراتی بازدید کنیم تا از نزدیک ببینی چطور کار می‌کنه. 53 | 54 | کیان: 🌈 وای چه عالی! راستی، این Multiplexing و Demultiplexing توی زندگی روزمره ما هم استفاده میشه؟ مثلاً توی گوشی‌های هوشمند یا لپ‌تاپ‌ها؟ 55 | 56 | حسین: 😃 سوال خیلی خوبیه کیان! بله، این تکنیک‌ها تقریباً همه جا استفاده میشن. مثلاً: 57 | 58 | 1. **گوشی هوشمند:** 59 | - وقتی همزمان داری موزیک گوش میدی، پیام می‌فرستی و تو اینترنت می‌گردی، گوشیت داره از Multiplexing استفاده می‌کنه تا همه این داده‌ها رو با هم بفرسته و دریافت کنه. 60 | 61 | 2. **لپ‌تاپ:** 62 | - وقتی چند تا برنامه رو همزمان باز می‌کنی، سیستم عامل از Multiplexing استفاده می‌کنه تا منابع کامپیوتر (مثل CPU و حافظه) رو بین برنامه‌های مختلف تقسیم کنه. 63 | 64 | 3. **وای‌فای خونه:** 65 | - وقتی چند نفر همزمان از وای‌فای استفاده می‌کنن، روتر از Multiplexing استفاده می‌کنه تا داده‌های همه دستگاه‌ها رو با هم ارسال و دریافت کنه. 66 | 67 |
-------------------------------------------------------------------------------- /NDA - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 |
6 | 7 | #### پیمان: 8 | 9 | بچه‌ها، من یه مشکل جدی دارم. شرکت رقیبمون، مپسی، بهم پیشنهاد همکاری داده با حقوق خیلی بهتر. ولی من NDA امضا کردم و نمی‌دونم باید این پیشنهاد رو قبول کنم یا نه. علاوه بر این، نگرانم که این کار اخلاقی نباشه و رزومه‌ام خراب بشه. ممکنه اتفاق دیگه‌ای هم بیوفته؟ 😕 10 | 11 | #### مارال: 12 | 13 | پیمان جان، اول از همه باید بگم که این یه تصمیم خیلی مهمه و باید همه جوانب رو بسنجی. NDA یه قرارداد محرمانگیه که تو رو ملزم می‌کنه اطلاعاتی که در طول کار در این شرکت به دست آوردی رو فاش نکنی. 🔗 [NDA](https://en.wikipedia.org/wiki/Non-disclosure_agreement) 14 | 15 | به نظرم باید اول مطمئن بشی که پیشنهاد مپسی شامل اطلاعات محرمانه‌ای که توی شرکت فعلی به دست آوردی نمی‌شه. اگه اینطور باشه، ممکنه بتونی بدون نقض NDA به مپسی بپیوندی. 16 | 17 | یه نکته دیگه هم اینه که می‌تونی با مدیر یا HR شرکت فعلی‌ت صحبت کنی و ببینی آیا می‌تونن شرایط بهتری بهت پیشنهاد بدن یا نه. شاید اینطوری بتونی بدون نیاز به تغییر شرکت، شرایط بهتری برای خودت فراهم کنی. 18 | #### حسین: 19 | 20 | دقیقاً. اگه NDA رو نقض کنی، ممکنه شرکت فعلی‌ت ازت شکایت کنه و این می‌تونه به اعتبارت آسیب بزنه. علاوه بر این، نقض NDA می‌تونه توی رزومه‌ت هم تأثیر منفی بذاره، چون کارفرماهای آینده ممکنه بهت اعتماد نکنن. 21 | پیمان جان، یه چیز دیگه هم که باید در نظر بگیری، فرهنگ سازمانی و محیط کاریه. تو الان با ما راحتی و ما رو می‌شناسی. آیا مطمئنی که توی مپسی هم همین حس رو خواهی داشت؟ گاهی اوقات پول بیشتر به قیمت از دست دادن یه محیط کاری خوب تموم می‌شه. 22 | 23 | #### مارال: 24 | 25 | درسته حسین، و علاوه بر این، به پروژه‌هایی که روشون کار می‌کنی هم فکر کن پیمان. شاید پروژه‌های ما برات جذاب‌تر باشن یا فرصت‌های یادگیری بیشتری داشته باشن. اینا چیزایی هستن که نمی‌شه فقط با پول مقایسه‌شون کرد. 26 | 27 | یه نکته دیگه هم هست. تو الان توی تیم ما جایگاه خودت رو داری و همه می‌شناسنت. توی شرکت جدید باید از اول شروع کنی و خودت رو ثابت کنی. این می‌تونه استرس‌زا باشه. البته شاید هم برات هیجان‌انگیز باشه. بستگی به خودت داره. 28 | 29 | 30 | این نکته خیلی مهمیه پیمان! سبک زندگی و علایق شخصی هم باید توی تصمیم‌گیری‌ت دخیل باشن. شاید بتونی از مپسی درباره این جور امکانات بپرسی. 31 | 32 | #### حسین: 33 | 34 | درسته، و فراموش نکن که موقعیت مکانی شرکت جدید هم مهمه. اگه مسیرش دورتر باشه، ممکنه زمان بیشتری رو توی ترافیک بگذرونی که می‌تونه روی کیفیت زندگیت تأثیر بذاره. 35 | 36 | #### پیمان: 37 | 38 | مرسی بچه‌ها، واقعاً کمک کردید. حالا می‌دونم که باید به چه چیزایی فکر کنم. قول می‌دم هر تصمیمی که گرفتم، اول با شما در میون بذارم. 😊 39 | 40 | 41 |
-------------------------------------------------------------------------------- /PEMIDI solutions.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 |
-------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | # داستان چیه؟ 5 | پیمان، حسین، ماهان و مارال توی تیم فنی شرکت Uber کار می‌کنن. 6 | 7 | پیمان: دو سال سابقه برنامه‌نویسی بک-اند با پایتون داره. 8 | 9 | حسین: سینیور تیم با ده سال سابقه مهندسی نرم‌افزار. حسین همیشه به بقیه کمک می‌کنه. 10 | 11 | ماهان: ماهان جونیور تیم هستش. ماهان همیشه وسط حرفای بقیه میپره و سوال میپرسه. 12 | 13 | مارال: مدیر فنی تیم هستش و بیشتر دغدغه بیزینس رو داره. 14 | 15 | 16 | این تیم در طول روز، به مشکلات فنی زیادی برمیخورن و یه سری راه‌حل براش ارائه میدن. 17 | مثلا بعضی وقت‌ها یه مشکل از سمت پیمان گزارش میشه، یا مدیر بخش اوپرشن یه مشکل بزرگ سریعا به تیم اطلاع میده. 18 | 19 | # هدف از این داستان‌ها چیه؟ 20 | هدف اینه که مفاهیم مهندسی نرم‌افزار رو با داستان یاد بگیریم. می‌خواییم این فضا رو تا جایی که می‌تونیم شبیه به یه تیم فنی قوی کنیم و از صحبت‌هاشون کلی چیز یاد بگیریم. 21 | 22 | 23 | **داستان‌ها به کمک AI همراه با رفرنس هستش. برای اصلاح هر داستان می‌تونید از طریق لینک داستان، Pull Request بفرستید تا بررسی بشه.** 24 | 25 | ## آدرس چنل تلگرام [ 🔗 PEMIDI Solutions](https://t.me/PEMIDI_Solutions) 26 | 27 | 28 | -------------------------------------------------------------------------------- /Race Condition - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 |
6 | 7 | 8 | 9 | پیمان: 10 | 😕 بچه‌ها، من یه مشکل عجیب پیدا کردم. 11 | وقتی چند تا کاربر همزمان درخواست تاکسی می‌زنن، بعضی وقت‌ها تعداد تاکسی‌های موجود اشتباه میشه. 12 | مثلاً وقتی دو نفر همزمان درخواست می‌زنن، ممکنه هر دو فکر کنن که تاکسی موجود هست و در نهایت یکی از اون‌ها بی‌تاکسی بمونه. 13 | 14 | حسین: 15 | 🤔 اوه، این می‌تونه نشونه یک race condition باشه. 16 | می‌تونی بیشتر توضیح بدی که دقیقاً چه اتفاقی میفته؟ 17 | 18 | پیمان: 19 | خب، فرض کن 5 تا تاکسی داریم. 20 | کاربر A و کاربر B همزمان درخواست می‌زنن. 21 | هر دو همزمان تعداد تاکسی‌های موجود رو می‌خونن (که 5 تاست). 22 | هر دو فکر می‌کنن که می‌تونن یکی از تاکسی‌ها رو بگیرن. 23 | اما در نهایت، یکی از اون‌ها ممکنه بی‌تاکسی بمونه! 24 | 25 | ماهان: 26 | 😮 یعنی یکی از درخواست‌ها گم میشه؟ 27 | چطور همچین چیزی ممکنه؟ 28 | 29 | حسین: 30 | 👨‍🏫 این دقیقاً یه نمونه کلاسیک از race condition هست. 31 | بذارید براتون توضیح بدم. 32 | 33 | کیان: 34 | 🤔 ببخشید حسین جون، میشه اول بگی race condition چیه؟ 35 | چرا بهش میگن "race"? 36 | 37 | حسین: 38 | 😊 البته کیان جان! خوشحالم که پرسیدی. 39 | 40 | این Race condition یه وضعیته که توش، نتیجه یه عملیات به ترتیب یا زمان‌بندی رویدادهای دیگه بستگی داره. 41 | مثل اینه که دو تا دونده با هم مسابقه بدن و نتیجه به این بستگی داشته باشه که کی زودتر به خط پایان برسه. 42 | در برنامه‌نویسی، این اتفاق معمولاً وقتی میفته که چند تا thread یا process سعی می‌کنن همزمان به یه منبع مشترک دسترسی پیدا کنن یا اون رو تغییر بدن. 43 | 44 | حالا، بذارید مشکل پیمان رو با یه مثال ساده توضیح بدم: 45 | 46 | 1. فرض کنید ما 5 تا تاکسی داریم. 47 | 2. کاربر A و کاربر B همزمان درخواست می‌زنن. 48 | 3. هر دو همزمان تعداد تاکسی‌ها رو می‌خونن (که 5 تاست). 49 | 4. هر دو فکر می‌کنن که می‌تونن یک تاکسی بگیرن. 50 | 5. هر دو موجودی رو 1 تا کم می‌کنن. 51 | 6. در نهایت، به جای اینکه 4 تا بمونه، ممکنه هر دو فکر کنن که درخواستشون پذیرفته شده و یکی از اون‌ها بی‌تاکسی بمونه! 52 | 53 | پیمان: 54 | 😲 دقیقاً! همین اتفاق داره میفته. 55 | چطور می‌تونیم حلش کنیم؟ 56 | 57 | حسین: 58 | برای حل این مشکل، ما نیاز داریم که عملیات خواندن و نوشتن موجودی رو "اتمیک" کنیم. 59 | یعنی مطمئن بشیم که هیچ عملیات دیگه‌ای نمی‌تونه وسط این فرآیند مداخله کنه. 60 | 61 | ماهان: 62 | 🤔 چطوری می‌تونیم این کار رو انجام بدیم؟ 63 | 64 | حسین: 65 | یکی از راه‌حل‌ها استفاده از "lock" یا "mutex" هست. 66 | اینا مکانیزم‌هایی هستن که اجازه میدن فقط یک thread در یک زمان به یه منبع خاص دسترسی داشته باشه. 67 | 68 | کیان: 69 | 😃 یعنی مثل اینه که روی در انبار یه قفل بذاریم و هر کی می‌خواد وارد بشه، باید صبر کنه تا نفر قبلی بیاد بیرون؟ 70 | 71 | حسین: 72 | 😃 آفرین کیان! دقیقاً همینطوره. 73 | خیلی خوب متوجه شدی. 74 | 75 | پیمان: 76 | این عالیه! 77 | می‌تونی یه مثال کد بزنی که نشون بده چطور می‌تونیم این رو پیاده‌سازی کنیم؟ 78 | 79 | حسین: 80 | البته! بذارید یه مثال ساده با پایتون بزنم. 81 | 82 | فرض کنید ما از threading و Lock استفاده می‌کنیم: 83 | 84 | ```python 85 | import threading 86 | 87 | class TaxiService: 88 | def __init__(self): 89 | self.available_taxis = 5 90 | self.lock = threading.Lock() 91 | 92 | def request_taxi(self): 93 | with self.lock: 94 | if self.available_taxis > 0: 95 | print("Taxi has been allocated.") 96 | self.available_taxis -= 1 97 | print(f"Remaining taxis: {self.available_taxis}") 98 | else: 99 | print("No taxis available.") 100 | 101 | # ایجاد یک شیء از کلاس TaxiService 102 | taxi_service = TaxiService() 103 | 104 | # تعریف یک فانکشن برای درخواست تاکسی 105 | def make_request(): 106 | taxi_service.request_taxi() 107 | 108 | # ایجاد دو thread برای شبیه‌سازی درخواست همزمان 109 | thread1 = threading.Thread(target=make_request) 110 | thread2 = threading.Thread(target=make_request) 111 | 112 | # شروع threadها 113 | thread1.start() 114 | thread2.start() 115 | 116 | # منتظر ماندن برای اتمام threadها 117 | thread1.join() 118 | thread2.join() 119 | ``` 120 | 121 | حسین: 122 | توی این مثال، ما از یک `Lock` استفاده کردیم تا مطمئن بشیم که فقط یک thread در هر زمان می‌تونه به تعداد تاکسی‌ها دسترسی داشته باشه. 123 | 124 | این کار باعث میشه که race condition اتفاق نیفته. 125 | 126 | کیان: 127 | 😮 وای، حالا فهمیدم! 128 | یعنی با این قفل، هیچ دو نفری نمی‌تونن همزمان به تعداد تاکسی‌ها دسترسی پیدا کنن. 129 | 130 | حسین: 131 | 👍 دقیقاً کیان جان! 132 | این یکی از راه‌های مهم برای جلوگیری از race condition هست. 133 | هر وقت سوال دیگه‌ای داشتی، حتماً بپرس! 134 | 135 | پیمان: 136 | مرسی حسین! 137 | این خیلی کمک کرد. 138 | حالا می‌تونم این مشکل رو توی کدمون حل کنم. 139 | 140 |
-------------------------------------------------------------------------------- /SoC.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | 🧒 کیان: 6 | 7 | بچه‌ها! توی یه مقاله برنامه‌نویسی خوندم چیزی به اسم "Separation of Concerns"، کسی می‌تونه بهم بگه یعنی چی؟ 🤔 8 | 9 | 10 | 👨‍🏫 پیمان: 11 | 12 | آفرین کیان جان، سؤال خوبی پرسیدی! 13 | اصل **Separation of Concerns** یا به‌اختصار **SoC** یعنی اینکه هر بخش از برنامه فقط باید یک وظیفه‌ی مشخص داشته باشه. 🎯 14 | 15 | 🍳 ماهان: 16 | 17 | بذار یه داستان برات تعریف کنم. 18 | فرض کن ما یه رستوران راه انداختیم. قراره غذا درست کنیم، سفارش بگیریم و به مشتری‌ها بدیم. حالا اگه فقط یک نفر بخواد همه‌ی این کارها رو انجام بده، چی میشه؟ 19 | 20 | 21 | 😓 کیان: 22 | 23 | وای! حتماً خیلی خسته میشه و همه چی قاطی پاتی میشه! 😅 24 | 25 | 26 | 👩‍🍳 مارال: 27 | 28 | دقیقاً! برای همین توی رستوران همه مسئولیت‌ها جداست: 29 | 30 | = 🧾 یکی سفارش می‌گیره 31 | = 🍲 یکی آشپزی می‌کنه 32 | = 🧍‍♂️ یکی هم غذا رو می‌بره برای مشتری 33 | 34 | برنامه‌نویس‌ها هم دقیقاً همین کارو می‌کنن؛ یعنی بخش‌های مختلف رو از هم جدا می‌کنن تا کد تمیزتر و قابل‌فهم‌تر باشه. 35 | 36 | 37 | 38 | ### 🧠 پیمان: 39 | 40 | ببین این مثالو با پایتون: 41 | 42 | #### ❌ اگه همه کارها تو یه تابع باشه: 43 | 44 | ```python 45 | def handle_order(): 46 | order = input("چی می‌خوای؟ ") 47 | food = f"غذای آماده شده: {order}" 48 | print(f"بفرمایید: {food}") 49 | ``` 50 | تغییر دادن یا تست این تابع سخته، چون چند تا کارو با هم انجام می‌ده. 51 | 52 | ✅ ولی با اصل SoC اینطوریه: 53 | ```python 54 | def take_order(): 55 | return input("چی می‌خوای؟ ") 56 | 57 | def prepare_food(order): 58 | return f"غذای آماده شده: {order}" 59 | 60 | def serve_customer(food): 61 | print(f"بفرمایید: {food}") 62 | ``` 63 | و حالا میتونیم به صورت گام به گام و مرحله ای فرایند رو انجام بدیم 64 | و الان هر بخش تنها و تنها مسئول یک بخشه و هر بخش هم باید یک کار رو انجام بده. 65 | 66 | 67 | ```python 68 | order = take_order() 69 | food = prepare_food(order) 70 | serve_customer(food) 71 | ``` 72 | 73 | ### 😊 کیان: 74 | اوه! چه باحال! یعنی الان هر بخش فقط کار خودش رو می‌کنه. مثل یه تیم واقعی! 75 | 76 | ### 👩 مارال: 77 | آفرین کیان! حالا اگه یه روز فقط خواستی بخش گرفتن سفارش رو تغییر بدی، لازم نیست بقیه‌ی بخش‌ها رو دست بزنی. این یعنی جداسازی مسئولیت! -------------------------------------------------------------------------------- /TCP Slow Start Restart Algorithm - Uber.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | 6 | ماهان: 🤔 بچه‌ها، من داشتم یه چیزایی درباره شبکه می‌خوندم و به یه اصطلاح برخوردم که برام جالب بود. TCP Slow Start. کسی می‌دونه این چیه؟ 7 | 8 | حسین: 😊 اوه، سوال خیلی خوبیه ماهان جان! TCP Slow Start یکی از مکانیزم‌های مهم در شبکه‌هاست. می‌خوای یه توضیح ساده بدم؟ 9 | 10 | ماهان: 🙋‍♂️ آره حتماً! اگه میشه طوری توضیح بدید که منم بفهمم. 11 | 12 | حسین: 👨‍🏫 باشه، بذار یه مثال ساده بزنم. فرض کن می‌خوای 10 تا توپ رو به دوستت که یه کم دورتره پرتاب کنی. چجوری این کار رو می‌کنی؟ 13 | 14 | ماهان: 🤔 خب، شاید اول یکی بندازم ببینم می‌تونه بگیره یا نه. 15 | 16 | حسین: 👍 دقیقاً! و اگه بتونه بگیره، بعدش چی کار می‌کنی؟ 17 | 18 | ماهان: 😃 احتمالاً دو تا می‌ندازم، و اگه باز هم بتونه بگیره، شاید بیشتر. 19 | 20 | حسین: 🎉 آفرین! این دقیقاً همون کاریه که TCP Slow Start انجام میده. اول کم شروع می‌کنه و بعد کم کم سرعتش رو زیاد می‌کنه. [🔗](https://en.wikipedia.org/wiki/TCP#Slow_start) 21 | 22 | پیمان: 🤨 جالبه! ولی چرا اینکار رو می‌کنه؟ چرا از همون اول با سرعت بالا شروع نمی‌کنه؟ 23 | 24 | حسین: 🧠 سوال خوبیه پیمان. ببین، تو شبکه ما نمی‌دونیم چقدر ظرفیت داریم. اگه یهو با سرعت بالا شروع کنیم، ممکنه باعث ازدحام و از دست رفتن داده‌ها بشیم. 25 | 26 | مارال: 👩‍💼 این خیلی جالبه. حسین، میشه یکم بیشتر در مورد جزئیات فنیش توضیح بدی؟ 27 | 28 | حسین: 🤓 البته. ببینید، TCP از یه چیزی به اسم "Congestion Window" یا cwnd استفاده می‌کنه. این در واقع تعداد بسته‌هاییه که می‌تونه بفرسته قبل از اینکه منتظر تایید بمونه. Slow Start با یه cwnd کوچیک شروع می‌کنه و کم کم بزرگش می‌کنه. 29 | 30 | ماهان: 🤔 یعنی چی؟ میشه بیشتر توضیح بدی؟ 31 | 32 | حسین: 👨‍🏫 البته. ببین، وقتی یه ارتباط TCP شروع میشه، cwnd خیلی کوچیکه، مثلاً 1 یا 2 بسته. هر بار که یه تایید (ACK) از گیرنده می‌گیریم، cwnd رو دو برابر می‌کنیم. این افزایش نمایی ادامه داره تا وقتی که یا به حداکثر ظرفیت شبکه برسیم یا یه بسته گم بشه. [🔗](https://www.geeksforgeeks.org/tcp-congestion-control/) 33 | 34 | پیمان: 🤯 وای، چقدر جالب! یعنی هر بار تعداد بسته‌ها رو دو برابر می‌کنه؟ 35 | 36 | حسین: 👍 دقیقاً! البته این یه مدل ساده شده‌ست. تو دنیای واقعی، مکانیزم‌های پیچیده‌تری هم وجود داره. مثلاً ممکنه بعد از یه مدت، افزایش cwnd به صورت خطی بشه تا از ازدحام جلوگیری کنیم. 37 | 38 | مارال: 🤔 این مفهوم می‌تونه توی برنامه‌نویسی وب هم کاربرد داشته باشه؟ 39 | 40 | حسین: 😊 صد در صد! مثلاً وقتی داریم یه اپلیکیشن وب طراحی می‌کنیم، می‌تونیم از این ایده استفاده کنیم تا داده‌های مهم‌تر رو زودتر بفرستیم و بعد کم کم بقیه چیزها رو لود کنیم. 41 | 42 | ماهان: 😃 وای، خیلی ممنون حسین! حالا خیلی بهتر فهمیدم TCP Slow Start چیه و چرا مهمه. 43 | 44 | پیمان: 🤔 حسین، یه سوال دیگه. اگه ارتباط TCP برای یه مدت طولانی بی‌کار بمونه، چی میشه؟ آیا این مکانیزم دوباره اجرا میشه؟ 45 | 46 | حسین: 🤓 آره، دقیقاً. این بهش میگن "TCP Slow Start Restart". وقتی یه ارتباط TCP برای مدتی بی‌کار بمونه، TCP فرض می‌کنه که شرایط شبکه ممکنه تغییر کرده باشه. بنابراین، وقتی دوباره داده‌ها رو ارسال می‌کنه، دوباره از Slow Start استفاده می‌کنه. [🔗](https://en.wikipedia.org/wiki/TCP_congestion_control#Slow-start) 47 | 48 | ماهان: 🤨 یعنی دوباره از همون مقدار کم شروع می‌کنه و کم کم زیاد میشه؟ 49 | 50 | حسین: 👍 دقیقاً. این کار کمک می‌کنه که از ازدحام ناگهانی جلوگیری بشه و شبکه به صورت بهینه‌تر عمل کنه. 51 | 52 | مارال: 🤔 این خیلی جالبه. حسین، مکانیزم‌های دیگه‌ای هم وجود داره که برای کنترل ازدحام استفاده بشه؟ 53 | 54 | حسین: 😊 بله، مکانیزم‌های دیگه‌ای هم هستن مثل "TCP Tahoe" و "TCP Reno". هر کدوم از این مکانیزم‌ها روش‌های مختلفی برای مدیریت ازدحام دارن. مثلاً TCP Reno بعد از اینکه یه بسته گم شد، به جای اینکه cwnd رو به مقدار اولیه برگردونه، اونو نصف می‌کنه و بعد به صورت خطی افزایش میده. [🔗](https://www.geeksforgeeks.org/tcp-tahoe-and-tcp-reno/) 55 | 56 | پیمان: 🤯 وای، این خیلی جالبه! یعنی هر کدوم از این مکانیزم‌ها مزایا و معایب خودشون رو دارن؟ 57 | 58 | حسین: 👍 دقیقاً. هر کدوم از این مکانیزم‌ها برای شرایط خاصی طراحی شدن و بسته به نیاز و شرایط شبکه، می‌تونیم از یکی از اونا استفاده کنیم. 59 | 60 | ماهان: 😃 حسین، می‌تونی یه منبع خوب معرفی کنی که بیشتر درباره این مکانیزم‌ها بخونم؟ 61 | 62 | حسین: 😊 البته ماهان جان. یکی از منابع خوب برای شروع، کتاب "TCP/IP Illustrated" نوشته "Richard Stevens" هست. همچنین می‌تونی به سایت‌های آموزشی مثل GeeksforGeeks و Cloudflare هم سر بزنی. [🔗](https://www.amazon.com/TCP-Illustrated-Vol-1-Prot/dp/0201633469) [🔗](https://www.geeksforgeeks.org/tcp-congestion-control/) 63 | -------------------------------------------------------------------------------- /YAGNI.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | # 🧠 اصل YAGNI - "You Aren't Gonna Need It" 6 | 7 | --- 8 | 9 | ### 🧒 کیان: 10 | 11 | بچه‌ها! امروز تو یه مقاله دیدم نوشته بود "YAGNI"! یعنی چی دقیقاً؟ 🤔 12 | 13 | --- 14 | 15 | ### 👨‍💻 پیمان: 16 | 17 |
18 | 19 | YAGNI یعنی 20 | 21 | **"تو قراره بهش نیاز نداشته باشی!"** 22 | یعنی چیزایی رو نساز که الان نیاز نداری، چون احتمال زیاد **هیچ‌وقت** هم لازم نمی‌شن. 23 | 24 |
25 | 26 | --- 27 | 28 | ### 🍰 ماهان: 29 | 30 | بذار برات یه داستان بگم که بهتر متوجه بشی! 31 | فرض کن کیان می‌خواد یه کیک ساده درست کنه. 🎂 32 | 33 | --- 34 | 35 | ### 😋 کیان: 36 | 37 | آره! من فقط می‌خوام یه کیک شکلاتی ساده برای تولد دوستم درست کنم. 38 | 39 | --- 40 | 41 | ### 👩‍🍳 مارال: 42 | 43 | خب، حالا تصور کن قبل از اینکه اصلاً تخم‌مرغ بشکنی، بری یه فر صنعتی بخری، دستگاه اتومات برای تزئین خامه، و یه ربات آشپز کمک‌کار! 😅 44 | 45 | --- 46 | 47 | ### 😵 کیان: 48 | 49 | عهههه! آخه من فقط یه کیک می‌خواستم، نه یه کارخانه کیک‌سازی! 😂 50 | 51 | --- 52 | 53 | ### 👨‍🏫 حسین: 54 | 55 | دقیقاً! این یعنی تو یه عالمه چیز ساختی که **الان بهشون نیاز نداری**. 56 | و شاید هیچ‌وقت هم نیاز نشه. 57 | تو برنامه‌نویسی هم همینطوره. 58 | 59 | --- 60 | 61 | ### 👨‍💻 پیمان: 62 | 63 | مثلاً فرض کن قراره یه اپ بنویسی که فقط یه فرم ثبت‌نام داره. 64 | ولی بیای الان واسش سیستم پرداخت، نوتیفیکیشن پیامکی، پنل ادمین حرفه‌ای و API GraphQL هم بسازی! 🤯 65 | 66 | --- 67 | 68 | ### 👨‍🔧 مثال کدنویسی: 69 | 70 | #### ❌ پیاده‌سازی بر خلاف YAGNI: 71 | 72 | ```python 73 | def create_user(username, password, email, phone, address, profile_picture, timezone, dark_mode, favorite_color): 74 | # هنوز هیچ‌کدوم از اینا لازم نیست 75 | pass 76 | ``` 77 | 78 | ✅ پیروی از YAGNI: 79 | ```python 80 | def create_user(username, password): 81 | # فقط چیزایی که الان نیاز داریم 82 | pass 83 | ``` 84 | 85 | وقتی واقعاً خواستی timezone و favorite_color اضافه کنی، اون موقع برو سراغش. 86 | 87 | --- 88 | 89 | ### 😎 کیان: 90 | آهاااا! فهمیدم! یعنی YAGNI می‌گه فعلاً همون دو تا تخم‌مرغ رو بشکن، کیک رو درست کن، 91 | اگه بعداً خواستی تزئینش کنی، اون موقع فکر کن به دستگاه خامه‌زن! 😂 92 | 93 | --- 94 | 95 | ### 👩 مارال: 96 | آفرین کیان! درست فهمیدی. 97 | سادگی یعنی تمرکز روی نیازهای واقعی فعلی، نه احتمالات آینده. 98 | 99 | --- 100 | 101 | ### ✅ خلاصه: 102 | اصل YAGNI می‌گه: 103 | 104 | 👇 «چیزی رو که هنوز بهش نیاز نداری، پیاده‌سازی نکن!» 105 | 106 | چون ممکنه فقط وقت، انرژی، و پیچیدگی بی‌مورد بسازه. 107 | -------------------------------------------------------------------------------- /git reset command.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | پیمان: 😓 بچه‌ها، من یه مشکل جدی پیدا کردم. داشتم روی یه فیچر جدید کار می‌کردم و یه سری تغییرات اعمال کردم، ولی الان متوجه شدم که این تغییرات اشتباه بودن و می‌خوام برگردم به حالت قبل. مشکل اینجاست که من این تغییرات رو کامیت کردم ولی هنوز پوش نکردم. چطوری می‌تونم این تغییرات رو برگردونم بدون اینکه هیستوری گیت خراب بشه؟ 6 | 7 | حسین: 🤔 آها، متوجه شدم پیمان جان. این یه سناریوی نسبتاً رایجه که برای خیلی از توسعه‌دهنده‌ها پیش میاد. خوشبختانه، گیت ابزارهای قدرتمندی برای مدیریت این جور موقعیت‌ها داره. 8 | 9 | حسین: 😊 راه حلی که من پیشنهاد می‌کنم استفاده از دستور "git reset --soft" هست. این دستور به ما اجازه میده که به یک کامیت قبلی برگردیم، بدون اینکه تغییرات فعلی رو از دست بدیم. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---soft) 10 | 11 | پیمان: 🤨 چطوری این کار رو انجام بدم؟ می‌شه بیشتر توضیح بدی؟ 12 | 13 | حسین: 💡 البته! اول از همه، باید شماره کامیتی که می‌خوای بهش برگردی رو پیدا کنی. می‌تونی از دستور "git log" استفاده کنی تا تاریخچه کامیت‌هات رو ببینی. [🔗](https://git-scm.com/docs/git-log) 14 | 15 | حسین: 🖥️ بعد از اینکه شماره کامیت مورد نظرت رو پیدا کردی، این دستور رو اجرا کن: 16 | ``` 17 | git reset --soft HEAD~1 18 | ``` 19 | این دستور شما رو به کامیت قبلی برمی‌گردونه. عدد 1 نشون میده که می‌خوای یک کامیت به عقب برگردی. اگه بخوای بیشتر برگردی، می‌تونی این عدد رو تغییر بدی. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt-emgitresetem) 20 | 21 | ماهان: 🙋‍♂️ ببخشید که می‌پرم وسط حرفتون، ولی میشه یه مثال عملی بزنید؟ من اینجوری بهتر متوجه میشم. 22 | 23 | حسین: 😃 حتماً ماهان جان. فرض کن ما یه فایل به اسم `app.py` داریم و توش این تغییرات رو اعمال کردیم و کامیت کردیم: 24 | 25 | ```python 26 | def calculate_total(items): 27 | total = sum(item.price for item in items) 28 | return total * 1.1 # اضافه کردن 10% مالیات 29 | ``` 30 | 31 | حالا فهمیدیم که این تغییر اشتباهه و می‌خوایم برگردیم به حالت قبل. پس این دستور رو اجرا می‌کنیم: 32 | 33 | ``` 34 | git reset --soft HEAD~1 35 | ``` 36 | 37 | حالا اگه `git status` رو اجرا کنیم، می‌بینیم که تغییرات هنوز توی Staging Area هستن، ولی کامیت نشدن. [🔗](https://git-scm.com/docs/git-status) 38 | 39 | پیمان: 🤔 خب، حالا که برگشتیم به حالت قبل، چطوری می‌تونیم تغییرات رو اصلاح کنیم؟ 40 | 41 | حسین: 👨‍🏫 خوشحالم که این سوال رو پرسیدی پیمان. حالا که تغییرات در Staging Area هستن، می‌تونی فایل رو ویرایش کنی و تغییرات جدید رو اعمال کنی. مثلاً: 42 | 43 | ```python 44 | def calculate_total(items): 45 | return sum(item.price for item in items) # حذف مالیات اضافه 46 | ``` 47 | 48 | بعد از اینکه تغییرات رو اعمال کردی، می‌تونی دوباره فایل رو add کنی و یه کامیت جدید بسازی: 49 | 50 | ``` 51 | git add app.py 52 | git commit -m "اصلاح محاسبه مجموع بدون اعمال مالیات" 53 | ``` 54 | 55 | ماهان: 🤯 وای، چقدر جالب! یعنی با این روش می‌تونیم اشتباهاتمون رو اصلاح کنیم بدون اینکه تاریخچه گیت رو خراب کنیم؟ 56 | 57 | حسین: 😎 دقیقاً ماهان جان! این یکی از قدرت‌های گیته. البته یادت باشه که اگه قبلاً تغییرات رو push کرده باشی، باید از force push استفاده کنی که البته در تیم‌های بزرگ توصیه نمیشه و باید با احتیاط انجام بشه. [🔗](https://git-scm.com/docs/git-push#Documentation/git-push.txt---force) 58 | 59 | مارال: 👩‍💼 بچه‌ها، من داشتم به مکالمه‌تون گوش می‌دادم. حسین، ممنون که این موضوع رو اینقدر خوب توضیح دادی. پیشنهاد می‌کنم یه جلسه آموزشی درباره این موضوعات گیت برای کل تیم بذاریم. فکر می‌کنم همه می‌تونن از این اطلاعات استفاده کنن. 60 | 61 | حسین: 🙌 ایده عالیه مارال جان! من خوشحال میشم که این جلسه رو برگزار کنم. می‌تونیم درباره انواع مختلف reset در گیت صحبت کنیم، مثل --soft، --mixed، و --hard، و اینکه هر کدوم چه کاربردی دارن. [🔗](https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified) 62 | 63 | پیمان: 😅 وای، ممنونم حسین! واقعاً کمک بزرگی کردی. فکر کنم باید بیشتر درباره این ویژگی‌های گیت یاد بگیرم. 64 | 65 | ماهان: 🤓 منم خیلی مشتاقم که بیشتر یاد بگیرم. مخصوصاً اینکه چطور می‌تونیم از این تکنیک‌ها توی workflow روزانه‌مون استفاده کنیم. 66 | 67 | حسین: 💪 خوشحالم که تونستم کمک کنم. یادتون باشه، گیت یه ابزار قدرتمنده و هر چقدر بیشتر باهاش کار کنید، راحت‌تر می‌تونید مشکلات رو حل کنید. اگه سوال دیگه‌ای دارید، حتماً بپرسید! 68 | 69 | مارال: 👏 عالیه بچه‌ها! من هماهنگ می‌کنم که این جلسه آموزشی رو هفته آینده داشته باشیم. فکر می‌کنم این جور بحث‌ها واقعاً به پیشرفت تیم کمک می‌کنه. 70 | 71 | پیمان: 🙏 ممنون از همگی. واقعاً خوشحالم که توی همچین تیمی کار می‌کنم که همه به هم کمک می‌کنن. 72 | 73 | ---- 74 | 75 | 76 | پیمان: خب فرق soft با hard و mixed چیه؟ 🤔 77 | 78 | حسین: 🤓 خیلی خوبه که این سوال رو پرسیدی پیمان. اجازه بده برات توضیح بدم. 79 | 80 | ### git reset --soft 81 | این دستور فقط HEAD رو به کامیت مشخص شده برمی‌گردونه و تغییرات رو در Staging Area نگه می‌داره. یعنی فایل‌ها همچنان برای کامیت بعدی آماده هستن، ولی کامیت قبلی از تاریخچه حذف میشه. به این ترتیب، تغییراتت رو از دست نمی‌دی و می‌تونی اونا رو دوباره کامیت کنی. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---soft) 82 | 83 | ### git reset --mixed 84 | این دستور هم مثل --soft، HEAD رو به کامیت مشخص شده برمی‌گردونه، ولی تغییرات رو از Staging Area خارج می‌کنه و فقط در Working Directory نگه می‌داره. این یعنی تغییراتت همچنان در فایل‌ها هستن، ولی دیگه برای کامیت آماده نیستن. این حالت پیش‌فرض git reset هست. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---mixed) 85 | 86 | ### git reset --hard 87 | این دستور همه چیز رو به حالت کامیت مشخص شده برمی‌گردونه، یعنی هم HEAD، هم Staging Area و هم Working Directory. به این ترتیب، همه تغییراتت از بین می‌رن و دیگه قابل بازیابی نیستن. باید با احتیاط از این دستور استفاده کنی چون تغییراتت رو به طور کامل از دست می‌دی. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---hard) 88 | 89 | حسین: 😅 یه مثال بزنم که بهتر متوجه بشی. فرض کن سه تا کامیت داریم به ترتیب `A`, `B`, `C` و HEAD روی `C` هست. اگه از `git reset --soft B` استفاده کنی، HEAD به `B` برمی‌گرده ولی تغییرات `C` همچنان در Staging Area هستن. اگه از `git reset --mixed B` استفاده کنی، HEAD به `B` برمی‌گرده و تغییرات `C` در Working Directory باقی می‌مونن ولی از Staging Area خارج می‌شن. و اگه از `git reset --hard B` استفاده کنی، همه چیز به حالت `B` برمی‌گرده و تغییرات `C` کاملاً از بین می‌رن. [🔗](https://www.gitkraken.com/learn/git/git-reset) 90 | 91 | ماهان: 😮 وای، چقدر جالب! یعنی با --soft تغییراتمون رو حفظ می‌کنیم ولی با --hard همه چیز رو از دست می‌دیم؟ 92 | 93 | حسین: دقیقاً! به همین دلیل باید بدونی که هر کدوم از این دستورات چه کاری انجام می‌دن و در چه مواقعی باید ازشون استفاده کنی. همیشه قبل از استفاده از --hard مطمئن شو که تغییراتت رو نمی‌خوای. [🔗](https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/Git-reset-hard-vs-soft-Whats-the-difference) 94 | 95 | مارال: 👩‍💼 خیلی خوب توضیح دادی حسین. این اطلاعات برای همه اعضای تیم خیلی مفیده. پیشنهاد می‌کنم یه مستند داخلی هم درباره این موضوعات تهیه کنیم تا همه بتونن بهش دسترسی داشته باشن. 96 | 97 | حسین: 🙌 حتماً مارال جان. من می‌تونم یه مستند تهیه کنم و توش این موارد رو به همراه مثال‌های عملی قرار بدم. اینطوری همه می‌تونن بهتر یاد بگیرن و از این ابزارها به درستی استفاده کنن. 98 | 99 | Citations: 100 | [1] https://stackoverflow.com/questions/3528245/whats-the-difference-between-git-reset-mixed-soft-and-hard 101 | [2] https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/Git-reset-hard-vs-soft-Whats-the-difference 102 | [3] https://www.gitkraken.com/learn/git/git-reset 103 | [4] https://github.com/orgs/community/discussions/68224 104 | [5] https://git-scm.com/docs/git-reset 105 | [6] https://www.youtube.com/watch?v=FklX-5_0qik -------------------------------------------------------------------------------- /git rest.md: -------------------------------------------------------------------------------- 1 | --- 2 | github: "true" 3 | --- 4 | 5 | پیمان: 😓 بچه‌ها، من یه مشکل جدی پیدا کردم. داشتم روی یه فیچر جدید کار می‌کردم و یه سری تغییرات اعمال کردم، ولی الان متوجه شدم که این تغییرات اشتباه بودن و می‌خوام برگردم به حالت قبل. مشکل اینجاست که من این تغییرات رو کامیت کردم ولی هنوز پوش نکردم. چطوری می‌تونم این تغییرات رو برگردونم بدون اینکه هیستوری گیت خراب بشه؟ 6 | 7 | حسین: 🤔 آها، متوجه شدم پیمان جان. این یه سناریوی نسبتاً رایجه که برای خیلی از توسعه‌دهنده‌ها پیش میاد. خوشبختانه، گیت ابزارهای قدرتمندی برای مدیریت این جور موقعیت‌ها داره. 8 | 9 | حسین: 😊 راه حلی که من پیشنهاد می‌کنم استفاده از دستور "git reset --soft" هست. این دستور به ما اجازه میده که به یک کامیت قبلی برگردیم، بدون اینکه تغییرات فعلی رو از دست بدیم. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---soft) 10 | 11 | پیمان: 🤨 چطوری این کار رو انجام بدم؟ می‌شه بیشتر توضیح بدی؟ 12 | 13 | حسین: 💡 البته! اول از همه، باید شماره کامیتی که می‌خوای بهش برگردی رو پیدا کنی. می‌تونی از دستور "git log" استفاده کنی تا تاریخچه کامیت‌هات رو ببینی. [🔗](https://git-scm.com/docs/git-log) 14 | 15 | حسین: 🖥️ بعد از اینکه شماره کامیت مورد نظرت رو پیدا کردی، این دستور رو اجرا کن: 16 | ``` 17 | git reset --soft HEAD~1 18 | ``` 19 | این دستور شما رو به کامیت قبلی برمی‌گردونه. عدد 1 نشون میده که می‌خوای یک کامیت به عقب برگردی. اگه بخوای بیشتر برگردی، می‌تونی این عدد رو تغییر بدی. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt-emgitresetem) 20 | 21 | یزدان: 🙋‍♂️ ببخشید که می‌پرم وسط حرفتون، ولی میشه یه مثال عملی بزنید؟ من اینجوری بهتر متوجه میشم. 22 | 23 | حسین: 😃 حتماً یزدان جان. فرض کن ما یه فایل به اسم `app.py` داریم و توش این تغییرات رو اعمال کردیم و کامیت کردیم: 24 | 25 | ```python 26 | def calculate_total(items): 27 | total = sum(item.price for item in items) 28 | return total * 1.1 # اضافه کردن 10% مالیات 29 | ``` 30 | 31 | حالا فهمیدیم که این تغییر اشتباهه و می‌خوایم برگردیم به حالت قبل. پس این دستور رو اجرا می‌کنیم: 32 | 33 | ``` 34 | git reset --soft HEAD~1 35 | ``` 36 | 37 | حالا اگه `git status` رو اجرا کنیم، می‌بینیم که تغییرات هنوز توی Staging Area هستن، ولی کامیت نشدن. [🔗](https://git-scm.com/docs/git-status) 38 | 39 | پیمان: 🤔 خب، حالا که برگشتیم به حالت قبل، چطوری می‌تونیم تغییرات رو اصلاح کنیم؟ 40 | 41 | حسین: 👨‍🏫 خوشحالم که این سوال رو پرسیدی پیمان. حالا که تغییرات در Staging Area هستن، می‌تونی فایل رو ویرایش کنی و تغییرات جدید رو اعمال کنی. مثلاً: 42 | 43 | ```python 44 | def calculate_total(items): 45 | return sum(item.price for item in items) # حذف مالیات اضافه 46 | ``` 47 | 48 | بعد از اینکه تغییرات رو اعمال کردی، می‌تونی دوباره فایل رو add کنی و یه کامیت جدید بسازی: 49 | 50 | ``` 51 | git add app.py 52 | git commit -m "اصلاح محاسبه مجموع بدون اعمال مالیات" 53 | ``` 54 | 55 | یزدان: 🤯 وای، چقدر جالب! یعنی با این روش می‌تونیم اشتباهاتمون رو اصلاح کنیم بدون اینکه تاریخچه گیت رو خراب کنیم؟ 56 | 57 | حسین: 😎 دقیقاً یزدان جان! این یکی از قدرت‌های گیته. البته یادت باشه که اگه قبلاً تغییرات رو push کرده باشی، باید از force push استفاده کنی که البته در تیم‌های بزرگ توصیه نمیشه و باید با احتیاط انجام بشه. [🔗](https://git-scm.com/docs/git-push#Documentation/git-push.txt---force) 58 | 59 | مارال: 👩‍💼 بچه‌ها، من داشتم به مکالمه‌تون گوش می‌دادم. حسین، ممنون که این موضوع رو اینقدر خوب توضیح دادی. پیشنهاد می‌کنم یه جلسه آموزشی درباره این موضوعات گیت برای کل تیم بذاریم. فکر می‌کنم همه می‌تونن از این اطلاعات استفاده کنن. 60 | 61 | حسین: 🙌 ایده عالیه مارال جان! من خوشحال میشم که این جلسه رو برگزار کنم. می‌تونیم درباره انواع مختلف reset در گیت صحبت کنیم، مثل --soft، --mixed، و --hard، و اینکه هر کدوم چه کاربردی دارن. [🔗](https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified) 62 | 63 | پیمان: 😅 وای، ممنونم حسین! واقعاً کمک بزرگی کردی. فکر کنم باید بیشتر درباره این ویژگی‌های گیت یاد بگیرم. 64 | 65 | یزدان: 🤓 منم خیلی مشتاقم که بیشتر یاد بگیرم. مخصوصاً اینکه چطور می‌تونیم از این تکنیک‌ها توی workflow روزانه‌مون استفاده کنیم. 66 | 67 | حسین: 💪 خوشحالم که تونستم کمک کنم. یادتون باشه، گیت یه ابزار قدرتمنده و هر چقدر بیشتر باهاش کار کنید، راحت‌تر می‌تونید مشکلات رو حل کنید. اگه سوال دیگه‌ای دارید، حتماً بپرسید! 68 | 69 | مارال: 👏 عالیه بچه‌ها! من هماهنگ می‌کنم که این جلسه آموزشی رو هفته آینده داشته باشیم. فکر می‌کنم این جور بحث‌ها واقعاً به پیشرفت تیم کمک می‌کنه. 70 | 71 | پیمان: 🙏 ممنون از همگی. واقعاً خوشحالم که توی همچین تیمی کار می‌کنم که همه به هم کمک می‌کنن. 72 | 73 | ---- 74 | 75 | 76 | پیمان: خب فرق soft با hard و mixed چیه؟ 🤔 77 | 78 | حسین: 🤓 خیلی خوبه که این سوال رو پرسیدی پیمان. اجازه بده برات توضیح بدم. 79 | 80 | ### git reset --soft 81 | این دستور فقط HEAD رو به کامیت مشخص شده برمی‌گردونه و تغییرات رو در Staging Area نگه می‌داره. یعنی فایل‌ها همچنان برای کامیت بعدی آماده هستن، ولی کامیت قبلی از تاریخچه حذف میشه. به این ترتیب، تغییراتت رو از دست نمی‌دی و می‌تونی اونا رو دوباره کامیت کنی. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---soft) 82 | 83 | ### git reset --mixed 84 | این دستور هم مثل --soft، HEAD رو به کامیت مشخص شده برمی‌گردونه، ولی تغییرات رو از Staging Area خارج می‌کنه و فقط در Working Directory نگه می‌داره. این یعنی تغییراتت همچنان در فایل‌ها هستن، ولی دیگه برای کامیت آماده نیستن. این حالت پیش‌فرض git reset هست. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---mixed) 85 | 86 | ### git reset --hard 87 | این دستور همه چیز رو به حالت کامیت مشخص شده برمی‌گردونه، یعنی هم HEAD، هم Staging Area و هم Working Directory. به این ترتیب، همه تغییراتت از بین می‌رن و دیگه قابل بازیابی نیستن. باید با احتیاط از این دستور استفاده کنی چون تغییراتت رو به طور کامل از دست می‌دی. [🔗](https://git-scm.com/docs/git-reset#Documentation/git-reset.txt---hard) 88 | 89 | حسین: 😅 یه مثال بزنم که بهتر متوجه بشی. فرض کن سه تا کامیت داریم به ترتیب `A`, `B`, `C` و HEAD روی `C` هست. اگه از `git reset --soft B` استفاده کنی، HEAD به `B` برمی‌گرده ولی تغییرات `C` همچنان در Staging Area هستن. اگه از `git reset --mixed B` استفاده کنی، HEAD به `B` برمی‌گرده و تغییرات `C` در Working Directory باقی می‌مونن ولی از Staging Area خارج می‌شن. و اگه از `git reset --hard B` استفاده کنی، همه چیز به حالت `B` برمی‌گرده و تغییرات `C` کاملاً از بین می‌رن. [🔗](https://www.gitkraken.com/learn/git/git-reset) 90 | 91 | یزدان: 😮 وای، چقدر جالب! یعنی با --soft تغییراتمون رو حفظ می‌کنیم ولی با --hard همه چیز رو از دست می‌دیم؟ 92 | 93 | حسین: دقیقاً! به همین دلیل باید بدونی که هر کدوم از این دستورات چه کاری انجام می‌دن و در چه مواقعی باید ازشون استفاده کنی. همیشه قبل از استفاده از --hard مطمئن شو که تغییراتت رو نمی‌خوای. [🔗](https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/Git-reset-hard-vs-soft-Whats-the-difference) 94 | 95 | مارال: 👩‍💼 خیلی خوب توضیح دادی حسین. این اطلاعات برای همه اعضای تیم خیلی مفیده. پیشنهاد می‌کنم یه مستند داخلی هم درباره این موضوعات تهیه کنیم تا همه بتونن بهش دسترسی داشته باشن. 96 | 97 | حسین: 🙌 حتماً مارال جان. من می‌تونم یه مستند تهیه کنم و توش این موارد رو به همراه مثال‌های عملی قرار بدم. اینطوری همه می‌تونن بهتر یاد بگیرن و از این ابزارها به درستی استفاده کنن. 98 | 99 | Citations: 100 | [1] https://stackoverflow.com/questions/3528245/whats-the-difference-between-git-reset-mixed-soft-and-hard 101 | [2] https://www.theserverside.com/blog/Coffee-Talk-Java-News-Stories-and-Opinions/Git-reset-hard-vs-soft-Whats-the-difference 102 | [3] https://www.gitkraken.com/learn/git/git-reset 103 | [4] https://github.com/orgs/community/discussions/68224 104 | [5] https://git-scm.com/docs/git-reset 105 | [6] https://www.youtube.com/watch?v=FklX-5_0qik --------------------------------------------------------------------------------