#تصمیمهای_مهندسی (Engineering Decisions)
یکی از سختترین تصمیمهای مهندسی، انتخاب بین درست بودن و در دسترس بودن است.
فرض کنید Database اصلی شما از دسترس خارج شده است.
یک Replica دارید که چند ثانیه از دیتای اصلی عقبتر است.
حالا دو انتخاب دارید.
انتخاب اول:
کاربر را منتظر نگه دارید یا حتی درخواست را Fail کنید، تا مطمئن شوید دادهای که نمایش میدهید کاملاً بهروز است.
انتخاب دوم:
درخواست را از Replica پاسخ دهید.
کاربر سرویس را دریافت میکند...
اما شاید اطلاعاتی را ببیند که چند ثانیه قدیمی است.
کدام تصمیم درست است؟
اگر در حال نمایش تعداد لایک یک پست باشید،
احتمالاً چند ثانیه اختلاف اهمیتی ندارد.
اما اگر موجودی حساب بانکی یا تعداد باقیمانده بلیت یک کنسرت را نمایش میدهید،
همان چند ثانیه میتواند یک فاجعه ایجاد کند.
به همین دلیل، مهندسان باتجربه هیچوقت نمیپرسند:
«ءConsistency بهتر است یا Availability؟»
بلکه میپرسند:
«در این Domain، هزینهی کدام اشتباه بیشتر است؟»
چون هیچ معماریای وجود ندارد که در هر شرایطی، هم بیشترین Availability را داشته باشد و هم قویترین Consistency را.
هر تصمیم، یک Trade-off است.
و ارزش یک مهندس، در انتخاب تکنولوژی نیست.
در درک هزینهی انتخابها است.
چون در مهندسی نرمافزار،
بهترین تصمیم، تصمیمی نیست که هیچ هزینهای نداشته باشد.
بهترین تصمیم، تصمیمی است که هزینهی درست را بپردازد.
یکی از سختترین تصمیمهای مهندسی، انتخاب بین درست بودن و در دسترس بودن است.
فرض کنید Database اصلی شما از دسترس خارج شده است.
یک Replica دارید که چند ثانیه از دیتای اصلی عقبتر است.
حالا دو انتخاب دارید.
انتخاب اول:
کاربر را منتظر نگه دارید یا حتی درخواست را Fail کنید، تا مطمئن شوید دادهای که نمایش میدهید کاملاً بهروز است.
انتخاب دوم:
درخواست را از Replica پاسخ دهید.
کاربر سرویس را دریافت میکند...
اما شاید اطلاعاتی را ببیند که چند ثانیه قدیمی است.
کدام تصمیم درست است؟
اگر در حال نمایش تعداد لایک یک پست باشید،
احتمالاً چند ثانیه اختلاف اهمیتی ندارد.
اما اگر موجودی حساب بانکی یا تعداد باقیمانده بلیت یک کنسرت را نمایش میدهید،
همان چند ثانیه میتواند یک فاجعه ایجاد کند.
به همین دلیل، مهندسان باتجربه هیچوقت نمیپرسند:
«ءConsistency بهتر است یا Availability؟»
بلکه میپرسند:
«در این Domain، هزینهی کدام اشتباه بیشتر است؟»
چون هیچ معماریای وجود ندارد که در هر شرایطی، هم بیشترین Availability را داشته باشد و هم قویترین Consistency را.
هر تصمیم، یک Trade-off است.
و ارزش یک مهندس، در انتخاب تکنولوژی نیست.
در درک هزینهی انتخابها است.
چون در مهندسی نرمافزار،
بهترین تصمیم، تصمیمی نیست که هیچ هزینهای نداشته باشد.
بهترین تصمیم، تصمیمی است که هزینهی درست را بپردازد.
Forwarded from thisisnabi.dev [Farsi]
8. Leaderless replication
—-
1. Designing Data Intensive Applications
- Replication [6]
@thisisnabi_dev
—-
1. Designing Data Intensive Applications
- Replication [6]
/three-lens-tutor Leaderless replication
@thisisnabi_dev
#باور_غلط_یا_واقعیت؟
«هرچه معماری تمیزتر باشد، سیستم بهتر است.»
معماری تمیز، همیشه معماری مناسب نیست.
گاهی یک تیم، هفتهها زمان صرف میکند تا:
همه چیز Interface داشته باشد.
هر کلاس فقط یک مسئولیت داشته باشد. Dependencyها کاملاً از هم جدا شوند.
همه چیز "طبق اصول" باشد.
نتیجه؟
کدی که از نظر تئوری فوقالعاده است...
اما توسعهدهنده جدید برای پیدا کردن یک منطق ساده باید از میان ۱۲ فایل عبور کند.
گاهی آنقدر روی تمیز بودن معماری تمرکز میکنیم که فراموش میکنیم هدف اصلی چیست.
کم کردن هزینهی تغییر.
اگر یک معماری:
فهم سیستم را سختتر کند،
ءDebug کردن را طولانیتر کند،
ءOnboarding اعضای جدید را دشوار کند،
و هر تغییر کوچک را به دهها فایل بکشاند،
شاید بیش از حد «تمیز» شده باشد.
معماری خوب، معماریای نیست که بیشترین Pattern را داشته باشد.
معماری خوب، معماریای است که حل مسئله را سادهتر کند، نه اینکه خودش به مسئله تبدیل شود.
بین «کد تمیز» و «سیستم قابلفهم» همیشه علامت مساوی وجود ندارد.
در مهندسی نرمافزار،
زیبایی معماری را با تعداد Patternها نسنج.
با سرعتی بسنج که تیم میتواند با اطمینان آن را تغییر دهد.
❌ باور غلط
«هرچه معماری تمیزتر باشد، سیستم بهتر است.»
✅ واقعیت
معماری تمیز، همیشه معماری مناسب نیست.
گاهی یک تیم، هفتهها زمان صرف میکند تا:
همه چیز Interface داشته باشد.
هر کلاس فقط یک مسئولیت داشته باشد. Dependencyها کاملاً از هم جدا شوند.
همه چیز "طبق اصول" باشد.
نتیجه؟
کدی که از نظر تئوری فوقالعاده است...
اما توسعهدهنده جدید برای پیدا کردن یک منطق ساده باید از میان ۱۲ فایل عبور کند.
گاهی آنقدر روی تمیز بودن معماری تمرکز میکنیم که فراموش میکنیم هدف اصلی چیست.
کم کردن هزینهی تغییر.
اگر یک معماری:
فهم سیستم را سختتر کند،
ءDebug کردن را طولانیتر کند،
ءOnboarding اعضای جدید را دشوار کند،
و هر تغییر کوچک را به دهها فایل بکشاند،
شاید بیش از حد «تمیز» شده باشد.
معماری خوب، معماریای نیست که بیشترین Pattern را داشته باشد.
معماری خوب، معماریای است که حل مسئله را سادهتر کند، نه اینکه خودش به مسئله تبدیل شود.
💡 جمعبندی
بین «کد تمیز» و «سیستم قابلفهم» همیشه علامت مساوی وجود ندارد.
در مهندسی نرمافزار،
زیبایی معماری را با تعداد Patternها نسنج.
با سرعتی بسنج که تیم میتواند با اطمینان آن را تغییر دهد.
#فرمون_دادن
یک اشتباه رایج در تیمهای نرمافزاری این است که فکر میکنیم برای سریعتر شدن، باید آدمهای بیشتری را وارد یک کار کنیم.
پروژه عقب افتاده؟ آدم اضافه کن.
تسک زیاد شده؟Developer اضافه کن.
ءDeadline نزدیک است؟ تیم را بزرگتر کن.
روی کاغذ منطقی به نظر میرسد.
اما نرمافزار مثل خط تولید کارخانه نیست که با اضافه کردن آدم، خروجی همیشه بیشتر شود.
فرض کنید یک تیم ۴ نفره روی یک Feature کار میکند.
حالا برای اینکه سریعتر تمام شود، ۶ نفر دیگر هم اضافه میشوند.
ناگهان باید:
جلسههای بیشتری برگزار شود. Context بیشتری منتقل شود. Code Reviewهای بیشتری انجام شود.
تصمیمهای بیشتری هماهنگ شود.
و افراد بیشتری منتظر یکدیگر بمانند.
یعنی بخشی از زمانی که قرار بود صرف ساختن شود، صرف هماهنگ شدن میشود.
مشکل از آدمهای جدید نیست.
مشکل این است که Complexity ارتباطی هم همراه آنها رشد میکند.
برای همین، قبل از اینکه بگویی:
«آدم بیشتری اضافه کنیم.»
یک سؤال مهمتر بپرس:
«مشکل واقعاً کمبود آدم است یا کمبود تمرکز؟»
گاهی یک تیم کوچک که دقیقاً میداند چه چیزی باید بسازد، از یک تیم بزرگ که مدام در حال هماهنگ شدن است، سریعتر حرکت میکند.
در مهندسی نرمافزار، تعداد بیشتر، همیشه به معنی سرعت بیشتر نیست.
گاهی برای سریعتر شدن،باید بهجای اضافه کردن آدم، موانع را کم کنیم.
یک اشتباه رایج در تیمهای نرمافزاری این است که فکر میکنیم برای سریعتر شدن، باید آدمهای بیشتری را وارد یک کار کنیم.
پروژه عقب افتاده؟ آدم اضافه کن.
تسک زیاد شده؟Developer اضافه کن.
ءDeadline نزدیک است؟ تیم را بزرگتر کن.
روی کاغذ منطقی به نظر میرسد.
اما نرمافزار مثل خط تولید کارخانه نیست که با اضافه کردن آدم، خروجی همیشه بیشتر شود.
فرض کنید یک تیم ۴ نفره روی یک Feature کار میکند.
حالا برای اینکه سریعتر تمام شود، ۶ نفر دیگر هم اضافه میشوند.
ناگهان باید:
جلسههای بیشتری برگزار شود. Context بیشتری منتقل شود. Code Reviewهای بیشتری انجام شود.
تصمیمهای بیشتری هماهنگ شود.
و افراد بیشتری منتظر یکدیگر بمانند.
یعنی بخشی از زمانی که قرار بود صرف ساختن شود، صرف هماهنگ شدن میشود.
مشکل از آدمهای جدید نیست.
مشکل این است که Complexity ارتباطی هم همراه آنها رشد میکند.
برای همین، قبل از اینکه بگویی:
«آدم بیشتری اضافه کنیم.»
یک سؤال مهمتر بپرس:
«مشکل واقعاً کمبود آدم است یا کمبود تمرکز؟»
گاهی یک تیم کوچک که دقیقاً میداند چه چیزی باید بسازد، از یک تیم بزرگ که مدام در حال هماهنگ شدن است، سریعتر حرکت میکند.
در مهندسی نرمافزار، تعداد بیشتر، همیشه به معنی سرعت بیشتر نیست.
گاهی برای سریعتر شدن،باید بهجای اضافه کردن آدم، موانع را کم کنیم.
🎯 ایده اصلی کتاب چیست؟
مهمترین ایده کتاب این است که Engineering Management ادامهی طبیعی Senior Software Engineering نیست؛ یک نقش متفاوت با مسئلهای متفاوت است.
وقتی Engineer هستی، بخش زیادی از خروجی تو مستقیماً از چیزهایی میآید که خودت میسازی:
اما وقتی Manager میشوی، دیگر قرار نیست خودت بیشترین کد را بنویسی.
خروجی تو بیشتر از این مسیر میآید:
بنابراین کتاب تلاش میکند به کسی که تازه وارد Management شده یاد بدهد چگونه از حالت «خودم انجام میدهم» به «شرایطی ایجاد میکنم که تیم بتواند انجام دهد» تغییر کند.
1. 🧭 ورود به نقش Manager
🧠 2. اول خودت را مدیریت کن
👥 3. مدیریت افراد
🎯 4. ءDelegation؛ یکی از مهمترین مهارتها
🔥 5. ءMicromanagement
🗣 6. ءFeedback و Performance
🧑🏫 7. ءCoaching و Mentoring
🏗 8. ساختن یک Team خوب
📈 9. رشد شغلی افراد
🧩 10. فقط تیم خودت مهم نیست
اگر بخواهم کتاب را خیلی خلاصه کنم:
مهمترین ایده کتاب این است که Engineering Management ادامهی طبیعی Senior Software Engineering نیست؛ یک نقش متفاوت با مسئلهای متفاوت است.
وقتی Engineer هستی، بخش زیادی از خروجی تو مستقیماً از چیزهایی میآید که خودت میسازی:
Code → Feature → System → Result
اما وقتی Manager میشوی، دیگر قرار نیست خودت بیشترین کد را بنویسی.
خروجی تو بیشتر از این مسیر میآید:
People → Team → Environment → Engineering Output
بنابراین کتاب تلاش میکند به کسی که تازه وارد Management شده یاد بدهد چگونه از حالت «خودم انجام میدهم» به «شرایطی ایجاد میکنم که تیم بتواند انجام دهد» تغییر کند.
📚 کتاب چه چیزهایی را آموزش میدهد؟
1. 🧭 ورود به نقش Manager
🧠 2. اول خودت را مدیریت کن
👥 3. مدیریت افراد
🎯 4. ءDelegation؛ یکی از مهمترین مهارتها
🔥 5. ءMicromanagement
🗣 6. ءFeedback و Performance
🧑🏫 7. ءCoaching و Mentoring
🏗 8. ساختن یک Team خوب
📈 9. رشد شغلی افراد
🧩 10. فقط تیم خودت مهم نیست
📌 در یک جمله
اگر بخواهم کتاب را خیلی خلاصه کنم:
این کتاب به تو یاد نمیدهد چگونه Developerهای بیشتری مدیریت کنی؛ به تو یاد میدهد چگونه محیطی بسازی که Developerها بتوانند بهتر کار کنند، رشد کنند و خروجی بهتری بهعنوان یک تیم داشته باشند.
#تحلیل_و_طرز_تفکر (Engineering Mindset)
گاهی یک سؤال ساده میتواند کیفیت یک طراحی را مشخص کند:
«اگر این بخش سیستم فردا خراب شود، چه چیزی باید بتواند بدون آن ادامه دهد؟»
خیلی از سیستمها برای حالت سالم طراحی میشوند.
ءDatabase در دسترس است.
ءRedis سالم است.
ءMessage Broker کار میکند.
ءExternal API پاسخ میدهد.
ءNetwork پایدار است.
همهچیز طبق انتظار پیش میرود.
اما Production دقیقاً جایی است که این فرضها شروع به شکستن میکنند.
ءDatabase ممکن است ۳۰ ثانیه کند شود.
ءRedis ممکن است از دسترس خارج شود.
یک Message ممکن است دوبار Deliver شود.
یک External API ممکن است Timeout کند.
و Network ممکن است Packet Loss داشته باشد.
اینجاست که تفاوت بین یک سیستم معمولی و یک سیستم Resilient مشخص میشود.
سیستم خوب فقط نمیگوید:
«اگر همهچیز سالم باشد، چه اتفاقی میافتد؟»
بلکه میپرسد:
«اگر یکی از وابستگیهای من خراب شود، دقیقاً چه چیزی باید همچنان کار کند؟»
مثلاً اگر Notification Service از دسترس خارج شد،
آیا ثبت سفارش هم باید Fail شود؟
اگر Analytics Service Down شد،
آیا کاربر باید نتواند وارد سیستم شود؟
اگر Recommendation Service پاسخ نداد، آیا صفحه محصول باید Error بدهد؟
پاسخ این سؤالها را نمیتوان با یک Pattern آماده داد.
باید از Business Requirement بیاید.
به همین دلیل، Resilience فقط اضافه کردن Retry و Circuit Breaker نیست.
اول باید مشخص کنی:
کدام شکستها قابل تحملاند و کدامها نیستند.
بعد برایشان طراحی کنی.
چون در سیستمهای واقعی، خرابی Exception نیست.
بخشی از شرایط عادی سیستم است که باید برایش طراحی شده باشی.
گاهی یک سؤال ساده میتواند کیفیت یک طراحی را مشخص کند:
«اگر این بخش سیستم فردا خراب شود، چه چیزی باید بتواند بدون آن ادامه دهد؟»
خیلی از سیستمها برای حالت سالم طراحی میشوند.
ءDatabase در دسترس است.
ءRedis سالم است.
ءMessage Broker کار میکند.
ءExternal API پاسخ میدهد.
ءNetwork پایدار است.
همهچیز طبق انتظار پیش میرود.
اما Production دقیقاً جایی است که این فرضها شروع به شکستن میکنند.
ءDatabase ممکن است ۳۰ ثانیه کند شود.
ءRedis ممکن است از دسترس خارج شود.
یک Message ممکن است دوبار Deliver شود.
یک External API ممکن است Timeout کند.
و Network ممکن است Packet Loss داشته باشد.
اینجاست که تفاوت بین یک سیستم معمولی و یک سیستم Resilient مشخص میشود.
سیستم خوب فقط نمیگوید:
«اگر همهچیز سالم باشد، چه اتفاقی میافتد؟»
بلکه میپرسد:
«اگر یکی از وابستگیهای من خراب شود، دقیقاً چه چیزی باید همچنان کار کند؟»
مثلاً اگر Notification Service از دسترس خارج شد،
آیا ثبت سفارش هم باید Fail شود؟
اگر Analytics Service Down شد،
آیا کاربر باید نتواند وارد سیستم شود؟
اگر Recommendation Service پاسخ نداد، آیا صفحه محصول باید Error بدهد؟
پاسخ این سؤالها را نمیتوان با یک Pattern آماده داد.
باید از Business Requirement بیاید.
به همین دلیل، Resilience فقط اضافه کردن Retry و Circuit Breaker نیست.
اول باید مشخص کنی:
کدام شکستها قابل تحملاند و کدامها نیستند.
بعد برایشان طراحی کنی.
چون در سیستمهای واقعی، خرابی Exception نیست.
بخشی از شرایط عادی سیستم است که باید برایش طراحی شده باشی.