توضیحات

نظر

نظر

  • امتیاز : 00/10
  • به دیگران توصیه می‌کنم :
  • دوباره می‌خوانم :
  • ایده برجسته :
  • تاثیر در من :
  • نکات مثبت :
  • نکات منفی :

مشخصات

  • نویسنده : Tom Manshreck, Hyrum Wright, Titus Winters
  • انتشارات : O’Reilly

بخش‌هایی از کتاب

برنامه فصل ۱ (What Is Software Engineering?)

فصل ۱ محورش تفاوت «برنامه‌نویسی» و «مهندسی نرم‌افزار» است؛ سه محور اصلی: زمان، مقیاس، و تصمیم‌گیری/تریدآف‌ها. برای این فصل، این تقسیم را پیشنهاد می‌کنم:

  1. بخش ۱: تعریف مهندسی نرم‌افزار و سه مزیت/تفاوت اصلی (زمان، مقیاس، تریدآف‌ها).
  2. بخش ۲: محور «زمان و تغییر» و مفهوم طول عمر کد، پروژه‌های کوتاه‌عمر vs بلندمدت، و شروع درد ارتقا.
  3. بخش 3: پایداری (sustainability) و این‌که چه زمانی یک پروژه مجبور می‌شود به تغییرات محیط واکنش نشان دهد.
  4. بخش ۴: «قانون هایروم» (Hyrum’s Law) و اثراتش روی طراحی API و تغییرات.
  5. بخش ۵: جمع‌بندی فصل ۱ و چند سؤال تفکری (متمرکز روی تجربه خودت در پروژه‌های دات‌نت).

بخش ۱ فصل ۱ – تعریف مهندسی نرم‌افزار

ایده‌ی مرکزی فصل

کتاب در ابتدای فصل ۱ می‌گوید چیزی که مهندسی نرم‌افزار را از «صرفاً برنامه‌نویسی» جدا می‌کند سه چیز است: زمان، مقیاس، و نوع تصمیم‌هایی که باید بگیری. در یک تمرین دانشگاهی یا اسکریپت یک‌بار مصرف، فقط کافی است «الآن» کار کند، اما در مهندسی نرم‌افزار واقعی باید فکر کنی این سیستم در طول سال‌ها چه تغییری می‌کند، چند نفر روی آن کار خواهند کرد و هر تصمیم امروز چه هزینه‌ای در آینده ایجاد می‌کند.

برای توضیح این تفاوت، نویسنده‌ها از یک جمله درون گوگل استفاده می‌کنند: «مهندسی نرم‌افزار یعنی برنامه‌نویسی که روی محور زمان انتگرال گرفته شده است»؛ یعنی برنامه‌نویسی فقط لحظه تولید نرم‌افزار است، اما مهندسی نرم‌افزار شامل توسعه اولیه، تغییرات بعدی، نگه‌داری، ارتقا و زندگی طولانی‌مدت سیستم است.

محور «زمان»

یکی از اولین سؤال‌هایی که مطرح می‌شود این است: «طول عمر مورد انتظار کد تو چقدر است؟».

  • بعضی کدها چند دقیقه یا چند ساعت عمر دارند (مثلاً یک اسکریپت یک‌باره).
  • بعضی کدها باید دهه‌ها زندگی کنند (مثلاً گوگل سرچ، هسته لینوکس، سرورهای مهم).

برای کد کوتاه‌عمر، تغییرات محیط (ورژن زبان، سیستم‌عامل، کتابخانه‌ها) تأثیر چندانی ندارد؛ چون قبل از این‌که آن تغییر برسد، کد دیگر استفاده نمی‌شود. اما هرچه طول عمر نرم‌افزار بیشتر می‌شود، احتمال تغییر وابستگی‌ها، نیازهای کسب‌وکار، معماری و زیرساخت بیشتر می‌شود، و همین جاست که مهندسی نرم‌افزار از برنامه‌نویسی جدا می‌شود.

نویسنده این را به یک مثال هندسی تشبیه می‌کند: همان‌طور که یک مکعب با فشرده شدن در یک بعد به مربع تبدیل می‌شود، یک سیستم نرم‌افزاری که بُعد «زمان» برایش نادیده گرفته شود، در حد یک مسئله‌ی ساده برنامه‌نویسی باقی می‌ماند.

محور «مقیاس»

محور دوم، مقیاس است: چند نفر درگیرند، چقدر کد وجود دارد و چقدر طول می‌کشد تا از توسعه اولیه فراتر بروی. در یک کار چندروزه انفرادی، بیشتر با مسائل فردی سر و کار داری؛ اما در یک سازمان بزرگ، توسعه نرم‌افزار به یک کار چندنفره، چندنسخه‌ای و بلندمدت تبدیل می‌شود.

کتاب به یک تعریف قدیمی از مهندسی نرم‌افزار اشاره می‌کند: «توسعه چندنفره‌ی برنامه‌های چندنسخه‌ای»؛ یعنی از همان ابتدا مفهوم تیم و نسخه‌نسخه تکامل کد، جزئی از تعریف است. این‌جا عواملی مثل ساختار تیم، سیاست‌های کنترل نسخه، استراتژی تست، فرایند کدریویو و هزینه ارتباطات بین آدم‌ها روی پیچیدگی کار اثر می‌گذارند و با بزرگ‌تر شدن سازمان باید مراقب باشی «هزینه تولید نرم‌افزار» همراه با اندازه سازمان، منفجر نشود.

محور «تریدآف‌ها و تصمیم‌گیری»

محور سوم، نوع تصمیم‌هایی است که در مقیاس مهندسی نرم‌افزار باید بگیری. در این سطح، معمولاً چند گزینه مختلف پیش رو داری که هرکدام هزینه‌ها و ریسک‌های متفاوت دارند و داده‌هایت هم همیشه کامل یا دقیق نیست؛ باید بین «سرعت»، «کیفیت»، «هزینه»، و «آینده‌پذیری» تعادل برقرار کنی.

نویسنده روی مفهوم «پایداری» تأکید می‌کند: شغل مهندس نرم‌افزار و رهبر فنی این است که سازمان، محصول و فرایند توسعه را طوری مدیریت کنند که در طول زمان بتوانند به تغییرات مهم پاسخ دهند، بدون این‌که سیستم فلج شود. گاهی آگاهانه تصمیم می‌گیری یک بدهی فنی را فعلاً نپردازی یا یک سیاست غیرمقیاس‌پذیر را موقتاً بپذیری، اما باید بدانی بعداً باید به این تصمیم برگردی و هزینه‌اش را بدهی.

نتیجه بخش ۱ – تفاوت «کد زدن» و «مهندسی»

جمع‌بندی این بخش این است که «مهندسی نرم‌افزار» یعنی:

  • فکر کردن به طول عمر کد و امکان تغییر آن در طول سال‌ها، نه فقط لحظه تحویل.
  • کار در مقیاس تیم‌ها، سازمان‌ها و سیستم‌های چندنسخه‌ای، نه فقط پروژه فردی.
  • تصمیم‌گیری با در نظر گرفتن تریدآف‌ها، پایداری و هزینه‌های آینده، نه فقط رسیدن به خروجی امروز.

از دید کتاب، خیلی از تمرین‌های دانشگاهی، بوت‌کمپ‌ها و حتی بعضی استارتاپ‌ها بیشتر «برنامه‌نویسی» تمرین می‌کنند، در حالی که برای ساخت سیستم‌های ماندگار، باید این سه بُعد (زمان، مقیاس، تریدآف‌ها) را در مرکز کار قرار بدهی.


بخش ۲ فصل ۱ – زمان و تغییر (Time and Change)

مقدمه: چرا زمان اهمیت دارد؟

یکی از تفاوت‌های بنیادی بین «برنامه‌نویسی» و «مهندسی نرم‌افزار» این است که برنامه‌نویسی لحظه‌ای است، اما مهندسی نرم‌افزار درباره طول زمان است. بخش ۲ فصل ۱ تمام بحث را دور این محور می‌چرخاند: اگر کد تو باید ۱۰ سال عمر کند، نه فقط ۱۰ روز، همه چیز تغییر می‌کند.

سطح ابتدایی: کجا از کجا درست شروع کنیم؟

برای شروع، کتاب از این سؤال شروع می‌کند: «طول عمر مورد انتظار کد تو چقدر است؟»

جواب این سؤال می‌تواند چیزی از چند دقیقه تا چند دهه باشد. نویسنده‌ها می‌گویند این تفاوت حدود ۱۰۰,۰۰۰ برابر است! یعنی:

  • کد کوتاه‌عمر: یک اسکریپت تک‌بار مصرف، یک ابزار برای یک جلسه، یک آزمایش ریاضی.
  • کد بلندمدت: سیستم‌های اصلی گوگل (مثل Google Search)، هسته لینوکس، زیرساخت‌های کریتیکل.

اینجا کلید است: برای کد کوتاه‌عمر (مثل یک اسکریپت ۲ ساعتی)، توجه نکردن به تغییرات محیط (ورژن پایتون، سیستم‌عامل) ریسک نیست چون قبل از این که آن تغییر برسد، کد هم‌چنان استفاده نمی‌شود. اما برای کد بلندمدت، گذشت زمان معنی‌ش این است که تقریباً همه وابستگی‌ها (dependency) تغییر خواهند کرد.

مثال عملی: کتابخانه‌ها و سیستم‌عامل‌ها

فرض کن دات‌نت پروژه‌ای نوشتی که از کتابخانه‌ی X استفاده می‌کند و آن کتابخانه برای ۶ ماه آینده کافی است. خوب است، مشکلی نیست.

اما اگر این پروژه باید ۵ سال زندگی کند؟ در این ۵ سال:

  • کتابخانه‌ی X ۵ یا ۶ بار نسخه اپدیت می‌شود.
  • مایکروسافت شاید .NET رو از .NET 6 به .NET 12 و .NET 15 ارتقا دهد.
  • سیستم‌عامل‌های محیط اجرایی (Windows Server) تغییر می‌کند.
  • احتمالاً یک patch امنیتی عمومی (مثل Heartbleed در OpenSSL) اتفاق می‌افتد و باید آپدیت کنی.

هرچه مدت زمان بیشتر‌تر باشد، احتمال تغییر نمایی بالا می‌رود، نه خطی.

درک نقطه‌ی اول: تفاوت «کار می‌کند» و «قابل نگهداری است»

این یکی از بخش‌های مهم‌تر است.

شاید کد تو الآن «کار می‌کند»: تست‌ها پاس می‌کنند، فیچر‌ها کار می‌کنند، یوزر‌ها خوشحال‌اند. اما آیا این کد زمانی که نسخه جدید کتابخانه‌ی X منتشر شود، هنوز هم قابل نگهداری است؟ اینجا است که مسئله دوم شروع می‌شود: تفاوت بین «همین‌الان کار می‌کند» (works now) و «برای سال‌ها می‌توانم تغییرش بدم» (is maintainable).

برای کد کوتاه‌عمر، این تفاوت مهم نیست. برای کد بلندمدت، بسیار مهم است.

مثال: انتقال از نسخه‌ای موقتی و غیرمستقیم

اگر پروژه‌ات کوتاه‌عمر است و کد پر از ترفندها است (مثلاً نوشتن چند خط hack کوتاه‌مدت)، شاید خوب است. سریع و کار می‌کند.

اما اگر همین کد بعد از ۳ سال هنوز در production است و دیگر تیم‌ها هم وابسته‌اند؟ حالا هر ترفند می‌تواند یک بمب وقت‌گذار شود. کسی برای fix کردن‌اش، باید تمام context را دوباره یاد بگیرد.

پایداری (Sustainability): کلید مهندسی نرم‌افزار

نویسنده‌ها یک تعریف کلیدی می‌دهند:

پروژه‌ی شما پایدار است اگر برای طول عمر مورد انتظار نرم‌افزارتان، شما توانایی واکنش به تغییرات ارزشمند را داشته باشید، چه بخاطر دلایل فنی یا کسب‌وکاری.

توجه کن: این توانایی است، نه اجبار. ممکن است تصمیم بگیری که یک upgrade را نکنی چون ارزش ندارد. اما بدانی توانایی آن را داری.

اگر نتوانی upgrade کنی یا تغییر بدهی؟ آن‌وقت ریسک بالا می‌گیری: که امیدواری می‌کنی هیچ چیز critical تغییر نشود. برای پروژه‌های کوتاه‌عمر این bet ایمن است، اما برای دهه‌ها؟ نه.

نمودار: طول عمر و اهمیت upgrade

کتاب یک نمودار دارد (Figure 1-1) که نشان می‌دهد:

  • کد کوتاه‌عمر: upgrade ضروری نیست
  • کد بلندمدت: upgrade کریتیکال است

بین این دو، انتقال اتفاق می‌افتد. تقریباً بین ۵ تا ۱۰ سال است که یک پروژه باید شروع به واکنش به تغییرات کند.

مسئله‌ی «اولین upgrade»: اینجا درد است

اگر پروژه‌ای از ابتدا برای upgrade ریخته نشده باشد، اولین upgrade خیلی درد‌ناک است و سه دلیل دارد:

۱. Task جدید است: تا الآن هیچ کسی upgrade نکرده. فرض‌های زیادی در کد مخفی شده‌اند.

۲. Experience کم: مهندس‌های فعلی شاید هیچ‌گاه upgrade نکرده‌اند و نمی‌دانند چکار باید کنند.

۳. Size بزرگ: نه یک سال upgrade، بلکه ۵ سال upgrade یک‌باره (چون ۵ سال missed کردی!).

نتیجه‌ی درد‌ناک: «دوباره نه»

بعد از یک upgrade دردناک، مهندسان اغلب تصمیم می‌گیرند «دوباره هرگز نه» و یا تصمیم می‌گیرند تمام چیز را دوباره بنویسند. ولی این تصمیمات مشکل را بزرگ‌تر می‌کند، نه کوچک‌تر.

حل درست این است: سرمایه‌گذاری کن که upgrade را سهل‌تر کنی. اگر ۱ سال یک‌بار ۱۰ روز upgrade می‌کند (چه منطقی‌تر است)، درد نیست. رویتین است.

تجربه‌ی Google: Compiler Upgrade ۲۰۰۶

کتاب یک مثال واقعی می‌دهد. Google برای سال‌های زیادی compiler خود را upgrade نکرده بود. وقتی ناچار شدند (چون compiler قدیمی شد)، اول‌اش خیلی درد‌ناک بود:

  • هزاران مهندس
  • میلیون‌ها خط کد
  • هیچ کسی experience نداشت
  • Hyrum’s Law (که بعداً می‌رسیم) تمام فرض‌های مخفی را غافل‌گیر کرد

خلاصه‌ی بخش ۲

محور زمان کل تفاوت بین برنامه‌نویسی و مهندسی نرم‌افزار است. اگر کد طولانی‌مدت نیست، شاید ترفندها خوب است. اما اگر طولانی‌مدت است، باید تفکر کنی درباره‌ی پایداری (sustainability): آیا می‌توانم این کد را بعد از ۵ سال upgrade کنم؟ اگر جواب «نه» است، اینجا مشکل است.

کلید این است: اولین upgrade سخت است، اما اگر منظم برنامه‌ریزی کنی، هر upgrade بعدی آسان‌تر می‌شود.


بخش ۳ فصل ۱ – قانون هایروم (Hyrum’s Law)

مقدمه: از «کار می‌کند» تا «قابل نگهداری است»

شاید تا حالا فکر می‌کردی که اگر کد تو مطابق API contract باشد، همه چیز خوب است. اینجا به رسمیت شناخته می‌شود که این فرض غلط است. قانون هایروم یک عمل ساده اما قدرتمند است که به خصوص برای پروژه‌های طولانی‌مدت حیاتی است.

تعریف رسمی: قانون هایروم

اگر یک API تعداد کافی از کاربران داشته باشد، مهم نیست که چه چیز وعده می‌دهی در contract: تمام رفتارهای observable سیستم تو، توسط کسی وابسته خواهند شد.

یعنی؟ یعنی این که حتی رفتارهایی که قصد نداشتی expose کنی، یا حتی رفتارهایی که ناقص یا undefined هستند، کسی در project خود وابسته‌اش می‌کند. وقتی بخواهی آن رفتار را تغییر بدهی (چه خیلی منطقی باشد)، breaking change است و کل ecosystem تو صدمه می‌خوره.

ربط به پایداری و زمان

نویسنده‌ها این قانون را با Entropy مقایسه می‌کنند. همان‌طور که آنتروپی هرگز کاهش نمی‌یابد (ترمودینامیک)، Hyrum’s Law هم هرگز نمی‌شود “حل شود.” فقط می‌توانی آن را کاهش بدهی، نه حذف.

اینجا اهمیت زمان دوباره ظاهر می‌شود:

  • اگر کد کوتاه‌عمر باشد، اهمیتش کم است.
  • اگر کد بلندمدت باشد، هر رفتار observable (حتی تصادفی) احتمال‌اً کسی وابسته‌اش می‌شود.

مثال عملی: Hash Ordering

کتاب یک مثال خیلی خوب می‌دهد: ترتیب‌دهی Hash Table.

تصور کن: اگر ۵ عنصر را در یک set قرار بدهی، به چه ترتیبی بیرون می‌آید؟

for i in {"apple", "banana", "carrot", "durian", "eggplant"}: 
    print(i)
# Output:
# durian
# carrot  
# apple
# eggplant
# banana

حالا، هر programmer می‌داند که hash table ترتیب خاصی ندارد. اما در عمل چه اتفاق می‌افتد؟

اگر کد تو ۱۰ سال عمر بکند:

  • یک programmer، کدی می‌نویسد که وابسته این ترتیب است (شاید بدون دانستن!).
  • یک programmer دیگر، از library تو استفاده می‌کند و نتایج را serialize می‌کند (مثلاً برای RPC response).
  • Client آن RPC، حالا وابسته ترتیب موجود است (چه اینکه documented نبوده!).

مثال واقعی: چرا این اتفاق می‌افتد؟

نویسنده‌ها ۳ دلیل می‌دهند که چرا hash ordering می‌تواند تغییر کند:

۱. Hash Flooding attacks: اگر کسی بخواهد سیستم تو را attack کند، ترتیب deterministic hash خطرناک است.

۲. بهبود الگوریتم: محققان الگوریتم‌های بهتر hash می‌یابند; اگر بخواهی آن‌ها استفاده کنی، ترتیب تغییر می‌کند.

۳. Hyrum’s Law: اگر اسلحه‌ی جنگی hash ordering را ببینی، حتماً کسی براش استفاده خواهد کرد.

سطح تحلیل: «درست است» در مقابل «کار می‌کند»

اینجا فرق عمیق آمد:

  • برای کد کوتاه‌عمر: وابستگی بر ترتیب hash problem نیست; هر دو چیز (کد تو و hash implementation) با هم زندگی می‌کنند و می‌میرند.

  • برای کد بلندمدت: وابستگی بر ترتیب risk است. اگر ۵ سال بعد قصد کنی hash implementation تغییر بدهی:

    • باید تمام کد dependent را پیدا کنی (شاید dozens یا hundreds جا).
    • هر کدام broken است و باید fix شود.
    • هر کدام تست نیاز دارد تا مطمئن شوی خراب نشده.

تفاوت بین «hacky» و «clean»

نویسنده‌ها این تفاوت را خوب خلاصه می‌کنند:

«It’s programming if ‘clever’ is a compliment, but it’s software engineering if ‘clever’ is an accusation.»

یعنی:

  • برنامه‌نویسی کوتاه‌عمر: «clever» = خوب! “جالب، حسابی کاملاً بهینه است!”

  • مهندسی نرم‌افزار بلندمدت: «clever» = بدی! “این کد خیلی پر ترفند است؛ کسی بعداً نمی‌خواهد با این کار کند.”

راه‌حل: آیا می‌تونیم چیزها را «ثابت» کنیم؟

سؤال منطقی: آیا می‌تونیم یک API بسازیم که هیچ چیز تغییر نکند؟

جواب: برای بیشتر پروژه‌ها، نه.

چرا؟

۱. مسائل امنیتی: Heartbleed، Meltdown، Spectre - حتی اگر کد خوب بنویسی، dependencies تو vulnerability داشتند. باید patch کنی.

۲. بهبود عملکرد: الگوریتم‌های CPU از دهه ۱۹۹۰ تغییر کردند. Linked-list یا Binary search tree هنوز کار می‌کنند، اما خیلی slow هستند برای hardware امروز.

۳. تکامل ناشناخته: حتی اگر اشتباه نشده باشی، گذشت زمان و تکامل technology واپس‌ایی “ترجیح بهتر” را می‌آورد.

خلاصه بخش ۳: Hyrum’s Law و عملیات

Hyrum’s Law یعنی:

  1. تمام رفتارهای observable توسط کسی وابسته‌اند، نه فقط documented ones.

  2. هرچه کد طولانی‌تر زندگی کند، احتمال وابستگی بیشتر است.

  3. نمی‌توانی این را حذف کنی، فقط می‌توانی آن را بدتر یا بهتر مدیریت کنی.

  4. در «برنامه‌نویسی»: ترفند و clever خوب است.
    در «مهندسی نرم‌افزار»: ترفند یک بمب وقت‌گذار است.


بخش ۴ فصل ۱ – مقیاس و کارایی (Scale and Efficiency)

مقدمه: محور دوم مهندسی نرم‌افزار

تا اینجا درباره‌ی محور «زمان» صحبت کردیم. حالا به محور دوم می‌رسیم: «مقیاس» (Scale). اگر فقط یک نفر است، بسیاری از مسائل شاید خودبخود حل شوند. اما وقتی سازمان بزرگ شود و صدها یا هزاران مهندس وارد شوند، هزینه‌های پنهان بزرگ می‌شود و باید کار را متفاوت انجام دهی.

سوال بنیادی: مقیاس‌پذیری

سوال اساسی این است:

«آیا سازمان تو هرچه بزرگ‌تر شود، هم‌زمان در تولید نرم‌افزار کارآمدتر می‌شود؟ یا هزینه‌ها به همان نسبت بالا می‌روند؟»

یعنی اگر فقط ۱۰ مهندس داری، شاید برای یک فرایند ۵ ساعت لازم است. اگر ۱۰۰ مهندس داری، آیا ۵۰ ساعت لازم است (linear scale)؟ یا ۵۰۰ ساعت (superlinear، بدتر از خطی)؟ یا شاید ۲۵ ساعت (بهتر شده، sublinear)؟

مقیاس‌پذیری مثبت یعنی این که هزینه را بر اساس تعداد نمی‌شمارند؛ بلکه هم‌چنان ثابت می‌مانند یا حتی کاهش می‌یابند.

سه منبع موارد نیاز برای مقیاس

کتاب سه حوزه را نام می‌برد که باید مقیاس‌پذیر باشند:

۱. هزینه‌های انسانی (Human Costs)

اگر هر بار سازمان تو ۲ برابر شود، آیا تمام کارهایی که تکرار می‌شود (مثل code review، testing، refactoring) هم ۲ برابر می‌شود؟ این مشکل است.

مثال: اگر تو ۱۰۰ مهندس داری و ۱۰۰۰ مهندس شوی، آیا هزینه code review ۱۰ برابر می‌شود؟ اگر جواب بله است، این superlinear scaling problem است و نمی‌تونی اینطور ادامه بدهی.

۲. منابع محاسباتی (Computational Resources)

Build time، test time، version control operations - اگر اینها هر دفعه سازمان بزرگ‌تر شود superlinearly بالا بروند، مشکل است.

۳. اصول کدبیس (The Codebase Itself)

اگر build time، git clone time، یا هزینه upgrade language version superlinear بالا رود، در نهایت به نقطه‌ای می‌رسی که نمی‌تونی حرکت کنی (boiled frog problem).

مثال ۱: Deprecation – سیاستی که مقیاس ندارد

کتاب یک مثال واضح می‌دهد: deprecation کردن یک Widget.

رویکرد ساده (small team):

  • تصمیم: “Widget قدیمی را می‌حذفیم در ۱۵ اگست”
  • نتیجه: هر تیم خود‌بخود کار را انجام می‌دهد و migration می‌کند.
  • مشکل: نسبتاً خوب کار می‌کند.

با رشد سازمان:

  • حالا صدها Widget وجود دارد و هزاران وابستگی
  • هر تیم باید تمام Widgets خود را migrate کند (superlinear work)
  • ۱ error شامل ۲۰% تیم‌های سازمان می‌شود
  • کل فرایند broken است و نمقیاس‌پذیر است.

حل Google: Churn Rule

بجای اینکه مسئولیت را به teams push کنی، infrastructure team خود این کار را انجام می‌دهد (یا backward-compatible می‌کند):

مقیاس‌پذیر است چون:

  • فقط تیم infrastructure با artifact سر و کار دارد
  • Dependent projects بدون کار بیشتری می‌روند
  • Expertise در یک جا concentrated است

نتیجه: Expertise و centralization scale بیشتری دارد تا decentralized work distribution.

مثال ۲: Development Branches – سیاستی که مقیاس ندارد

رویکرد ساده:

  • ۵ تا ۱۰ development branch داری.
  • هر branch merge شدن expensive work می‌شود (resyncing و testing).
  • برای small team: OK است.

با رشد:

  • حالا ۱۰۰ branch یا بیشتر داری
  • هر merge بالقوه ۹۹ branch دیگر را تحت تأثیر می‌گذارد
  • سربار merge exponentially بالا می‌رود

حل: Monorepo + Trunk-Based Development (فصل بعدی در کتاب)

مثال عملی: Compiler Upgrade - تجربه Google ۲۰۰۶

کتاب یک مثال تاریخی خیلی معنادار می‌دهد: اولین compiler upgrade بزرگ Google.

وضعیت:

  • صدها تیم
  • millions خط کد
  • ۵ سال بدون compiler update
  • اکثر engineers هیچ compiler change نکرده بودند

نتیجه:

  • Extremely painful
  • Hyrum’s Law تمام implicit dependencies آشکار کرد
  • ۳ دلیل برای درد:
    • Task جدید بود
    • Experience نبود
    • Size بزرگ (۵ سال upgrade یکباره)

حل Google: تغییر سیاست و فرایند

بعد از درس سخت، Google روی ۵ عامل کار کرد:

عامل توضیح
Expertise اول compiler upgrade difficult است؛ ۱۰۰ها بار انجام دادن آن را routine می‌کند
Stability اگر هر ۱ هفته compiler update کنی (بجای ۵ سال)، delta کوچک است
Conformity زمانی که کد regularly upgrade می‌شود، brittle behavior کم می‌شود
Familiarity با تکرار، شاید فرایند را بتوانی automate کنی
Policy مثل “Beyoncé Rule” (اگر CI test نگذاشتی، infrastructure fault نیست)

نتیجه:

  • از ۱۰۰+ engineers volunteer به constant engineers برای perform کردن task
  • حتی هر sizebase grow کند، human effort constant باقی ماند (linear scaling!)

Beyoncé Rule: سیاستی که مقیاس‌پذیر است

«If you liked it, you should have put a CI test on it»

معنی:

  • اگر infrastructure change باعث bug شد اما CI test آن را گرفت نشد، infrastructure fault نیست.
  • This protects infrastructure teams از tracking down every bespoke test دیگر تیم‌ها.

چرا scale می‌کند؟

  • بدون این rule: infrastructure engineer باید هر تیم رو پیدا کند و آنها رو test کند (impossible)
  • با این rule: فقط tests داخل CI count می‌شود (centralized، scalable)

نتیجه:

  • ✅ Infrastructure teams می‌توانند upgrade انجام دهند بدون دسترسی به تمام bespoke tests
  • ✅ Dependent teams مسئول هستند که tests خود را در CI قرار دهند (accountability shift)

Shifting Left: سیاست درست انجام کار

نویسنده‌ها یک اصل کلی معرفی می‌کنند:

مشکلات را هرچه بیشتر به سمت «چپ» (early) developer workflow حرکت دهند، **هزینه کم‌تری دارد.

Timeline developer:

  • Design → Implementation → Code Review → Testing → Commit → Canary → Production

Shifting Left:

  • مسائل را در Design phase catch کنید: Cheapest
  • Code review سریع: Cheap
  • در Production: Expensive

چرا؟ چون developer هنوز کد در mind دارد، تغییرش سریع است. اگر ۶ ماه منتظر شوی، دیگر هیچ کسی نمی‌دانند code چکار می‌کند.

خلاصه بخش ۴

محور مقیاس:

۱. Superlinear costs are death: اگر هر دفعه سازمان ۱۰ برابر شود، کار تو ۱۰۰ برابر می‌شود، پایدار نیست.

۲. Centralize expertise: بجای اینکه ۱۰۰ تیم individually کار کنند، centralize expertise و economies of scale از آن بگیر.

۳. Policy > Procedure: درست سیاست‌های کارآمد می‌کند (Beyoncé Rule) تا هر فرایند اضافی نیز مقیاس ندارد.

۴. Shifting left: Catch مشکلات زودتر = کارایی بیشتر.


بخش ۵ فصل ۱ – تریدآف‌ها و تصمیم‌گیری (Trade-offs and Decision Making)

مقدمه: سه محور را کنار هم بیاور

تا اینجا سه محور را یاد گرفتی: زمان، مقیاس، و Hyrum’s Law. حالا بخش آخر فصل ۱ درباره‌ی چطور این سه محور را در عمل به کار ببری است تا تصمیم‌های درست بگیری.

سوال بنیادی: چرا تصمیم‌گیری مهم است؟

نویسنده‌ها می‌گویند:

«اگر بفهمی چطور برنامه‌نویسی کن، چطور نرم‌افزار را نگه‌دار، و چطور با سازمان بزرگ کار کن، تنها چیز باقی‌مانده تصمیم‌گیری خوب است.»

یعنی تکنیک‌های خوب، بدون تصمیم‌های درست، بیفایده‌اند. و برعکس، تصمیم‌های درست می‌تونند تکنیک‌های ضعیف‌تر را بهتر کند.

اصل اول: «دلیل برای همه چیز»

درون Google، یک distaste قوی برای «چون من گفتم» وجود دارد. هدف این است:

  • هر تصمیم‌ی باید دلیل داشته باشد.
  • باید consensus بجای unanimity باشد (نه همه توافق، بلکه بیشتری).
  • نه “چون همه انجام می‌دهند” یا “چون من گفتم.”

انواع هزینه‌ها: «Cost» چه معنی دارد؟

اینجا کلیدی است: «هزینه» فقط پول نیست. نویسنده‌ها ۶ نوع هزینه را نام می‌برند:

نوع هزینه توضیح
Financial مال (دلار، یورو)
Resource منابع محاسباتی (CPU، RAM، network)
Personnel تلاش مهندس (Engineer hours)
Transaction هزینه انجام‌دادن تغییر (چقدر طول می‌کشد؟)
Opportunity هزینه نکردن کار (چه خسارتی داریم؟)
Societal تأثیر جامعه‌ای (کدام users صدمه می‌خورند؟)

مثال واقعی: Markers در دفتر

نویسنده یک مثال ساده و معنادار می‌دهد:

شرکت A (control tight):

  • Markers را تحت کنترل قفل می‌کند
  • نتیجه: اکثر markers خشک و بیکار
  • هزینه: جلسات شکسته شده، تفکر مختل‌شده
  • Marker هزینه: <$1

Google:

  • Closets بازی پر از markers
  • نتیجه: brainstorming بدون مانع
  • Trade-off: شاید کسی ۲۰ marker ببرد؛ ولی focus بیشتر است

نتیجه: Google گفت: «بهتر است بر روی brainstorming بدون مانع تمرکز کنیم تا Markers را محافظت کنیم.» این یک تریدآف آگاهانه است.

دو نوع تصمیم‌گیری

نویسنده ۲ سناریو را نام می‌برد:

۱. تصمیم قابل اندازه‌گیری:

جایی که تمام مقادیر measurable یا estimated هستند.

مثال: «اگر ۲ هفته engineer-time بگذارم تا linked-list را به balanced tree تغییر بدهم:

  • ۵ GB RAM بیشتر مصرف می‌کنم
  • ۲۰۰۰ CPU ذخیره می‌کنم

آیا بر سر ارزش برای شام؟»

جواب: بستگی به cost table دارد (چقدر یک CPU = یک GB RAM؟)

۲. تصمیم‌های subtle:

جایی که نمی‌دانی چقدر engineer-time لازم است، یا تأثیرات undefined هستند.

مثال: «هزینه‌ی یک API بد‌طراحی چقدر است؟»

برای این نوع، نویسنده می‌گوید: rely on experience, leadership, and precedent.

Input به Decision Making: Conversion Table

اگر تمام شی‌های مختلف را می‌خواهی مقایسه کنی، باید یک conversion table بسازی:

۱۰۰ CPU = ۱۰ GB RAM = ۲ Engineer-Weeks = $50,000

با این جدول، هر مهندس می‌تواند خود‌بخود analysis انجام دهد:

«اگر ۲ هفته engineer-time خرج کنم و ۲۰۰۰ CPU ذخیره کنم، سود دارم؟»

نتیجه: $۲۰۰۰ (engineer-weeks) vs $۱۰۰۰ (CPU savings) = خیر، خوب نیست.

مثال عملی: Distributed Build System

کتاب یک نقطه‌ی آموزنده می‌دهد:

قبل: Google engineers محلی می‌ساختند (local build)

  • Slow compilation
  • Hardware expensive (engineers نیاز به workstations قوی دارند)

بعد: Google یک distributed build system ساخت

  • Cost: engineer-time برای توسعه + CPU برای infrastructure
  • Benefit: builds خیلی سریع‌تر

حتی با حساب هزینه‌ی development، سود خیلی بیشتر بود.

اما مشکل: وقتی engineers دیگر محلی slow build احساس نکردند، شروع به اضافه کردن bloated dependencies کردند!

نتیجه: یکی از Jevons Paradox: هرچه efficient بشوی، consumption بیشتر می‌شود.

Trade-off: Fork vs Share

سؤال نهایی و پیچیده: آیا من باید dependency shared استفاده کنم یا fork کنم؟

Factor Fork Share
Control Full control ✅ Changes dictated by others ❌
Time Short-lived? OK ✅ Long-lived? Risk ❌
Scale Isolated ✅ Security fix = update all forks ❌
Domain Domain-specific ✅ General-purpose ❌

جواب: Depends! اگر project short-lived است و fork محدود scope دارد، fork OK است. اما برای data structures، protocols و formats نباید fork کنی.

Decision Making را Revisit کن

مهمترین insight:

«Data تغییر می‌کند. فرض‌ها غلط ثابت می‌شوند. تصمیم‌های قدیمی امروز غلط باشند.»

Solution: Always Be Deciding – یعنی هر ماه بخش decisions را دوباره ارزیابی کن.

اگر این framing نباشد، teams analysis paralysis میافتند (حل perfect را می‌خواهند و هرگز تصمیم نمی‌گیرند).

بهتر: «چند ماه بعد می‌تونیم این تصمیم را تغییر بدهیم. حالا بریم و ببینیم کجا می‌رسیم.»

بخش نهایی: برنامه‌نویسی vs مهندسی نرم‌افزار

نویسنده یک سوال مهم می‌پرسد:

«آیا مهندسی نرم‌افزار بهتر از برنامه‌نویسی است؟»

جواب: نه، متفاوت است.

موضوع برنامه‌نویسی (کوتاه‌عمر) مهندسی نرم‌افزار (بلندمدت)
Integration tests نیازی نیست ✅ الزامی ❌
Refactoring نادر مستمر
Semantic Versioning غیرضروری Critical
Tool flexibility Choose any Choose sustainable

Point: ابزار‌های مناسب برای کدام domain متفاوت است. یک اسکریپت ۲ روزه نیازی به integration tests ندارد!

خلاصه فصل ۱ (TL;DR)

نویسنده یک خلاصه‌ی عالی می‌دهد:

Point توضیح
Time dimension مهندسی نرم‌افزار درباره‌ی ۳ محور است: زمان، مقیاس، تریدآف
۱۰۰,۰۰۰ times تفاوت در طول عمر کد بین کوتاه و بلندمدت
Sustainability توانایی واکنش به تغییر، نه اجبار
Hyrum’s Law تمام observable behaviors وابسته‌اند
Scaling هر تکرار باید linear یا بهتر scale شود
Expertise Centralize knowledge برای scale کردن
Data-driven Decisions بر داده مبتنی، اما نه فقط
Revisit regularly Decisions تغییر می‌یابند; Always Be Deciding

خلاصه‌ی کل فصل ۱

فصل ۱ یک سفر بود از:

  1. تعریف مهندسی نرم‌افزار
  2. محور ۱ (Time): Life-span کد و پایداری
  3. محور ۲ (Scale): Policies، expertise، و Beyoncé Rule
  4. محور ۳ (Trade-offs): Decision-making، costs، و iteration

Point کلی: مهندسی نرم‌افزار درباره‌ی building sustainable systems that can adapt over time with many people working together است. فقط کد نوشتن کافی نیست؛ maintenance، growth، و teamwork کلید است.


فصل ۲: چگونه در تیم‌ها خوب کار کنیم (Culture & Teamwork)

مقدمه: مشکل اول خود تو هستی!

شاید فکر کنی بزرگترین چالش مهندسی نرم‌افزار، یادگیری الگوریتم‌ها یا فریم‌ورک جدید است، اما این کتاب می‌گوید: نه! چالش اصلی، تعامل با انسان‌ها است.

برای شروع، نویسنده بی‌تعارف می‌گوید:

«اگر می‌خواهی در تیم موفق باشی، اول باید باگ‌های خودت را بشناسی.»

همه ما دوست داریم فکر کنیم منطقی هستیم، ولی انسان‌ها پر از احساسات، ترس و غرور هستند. برای اینکه یک مهندس نرم‌افزار عالی باشی، فقط کد زدن کافی نیست؛ باید یاد بگیری چطور با دیگران کار کنی.

این فصل روی سه ستون اصلی بنا شده: فروتنی (Humility)، احترام (Respect) و اعتماد (Trust) که به اختصار HRT نامیده می‌شوند.

۱. افسانه‌ی نابغه (The Genius Myth)

ما عاشق قهرمان‌ها هستیم: لینوس توروالدز (خالق لینوکس)، بیل گیتس، استیو جابز. داستان‌هایی که می‌شنویم معمولاً این‌طور است: «یک نابغه به غار تنهایی می‌رود، هفته‌ها کد می‌زند، و با یک شاهکار بیرون می‌آید که دنیا را تغییر می‌دهد.»

واقعیت اما چیز دیگری است: لینوس فقط هسته‌ی اولیه لینوکس را نوشت. عظمت لینوکس نتیجه کار هزاران نفر بود که روی آن کار کردند. مایکل جوردن بدون تیم و مربی‌اش نمی‌توانست قهرمان شود.

چرا این باور خطرناک است؟ چون خیلی از مهندسان (شاید حتی خود من و تو!) تهِ دلمان دوست داریم آن «نابغه» باشیم. فکر می‌کنیم اگر کدمان را به کسی نشان دهیم و غلط داشته باشد، همه می‌فهمند ما نابغه نیستیم. پس چه کار می‌کنیم؟ قایم می‌شویم!

۲. پنهان کردن کد: یک اشتباه بزرگ (Hiding Considered Harmful)

بسیاری از برنامه‌نویس‌ها می‌ترسند کد نیمه‌کاره‌شان را نشان دهند. می‌گویند: «صبر کن تمام شود، بعداً نشان می‌دهم.» یا «نمی‌خواهم کسی ببیند چقدر باگ دارم.»

چرا کار کردن در خفا (Working in a cave) اشتباه است؟

۱. تشخیص دیرهنگام خطا (Early Detection): فرض کن داری یک دوچرخه طراحی می‌کنی و هفته‌ها در گاراژت مخفیانه روی آن کار می‌کنی. وقتی تمام شد، دوستت می‌گوید: «اِ، چرا صندلی نگذاشتی؟» اگر زودتر نشان داده بودی، همان روز اول این را می‌فهمیدی. در نرم‌افزار هم همین‌طور است: شاید داری کدی می‌زنی که اصلا نیاز نیست، یا راه حل خیلی ساده‌تری دارد.

۲. ریسک “اتوبوس” (The Bus Factor): «ضریب اتوبوس» یعنی: اگر چند نفر از اعضای تیم بروند زیر اتوبوس (یا شرکت را ترک کنند)، پروژه نابود می‌شود؟ اگر تو تنها کسی هستی که کد را می‌فهمد، ضریب اتوبوس ۱ است. این یعنی فاجعه. اگر کد را مرتب به اشتراک بگذاری، دیگران هم یاد می‌گیرند و پروژه امن می‌شود.

۳. سرعت پیشرفت (Pace of Progress): تنهایی کار کردن معمولاً کندتر است. وقتی گیر می‌کنی، ممکن است دو روز وقت بگذاری تا مشکلی را حل کنی که هم‌تیمی‌ات در ۵ دقیقه حل می‌کرد. نترس از اینکه بپرسی.

۳. سه ستون اصلی (HRT)

برای اینکه یک هم‌تیمی عالی باشی، باید این سه ویژگی را در خودت پرورش دهی:

  1. فروتنی (Humility): باور کن که مرکز جهان نیستی و همه‌چیز را نمی‌دانی. تو جایز‌الخطایی. وقتی اشتباه می‌کنی، بپذیر. «من اشتباه کردم» جمله‌ی قدرتمندی است.
  2. احترام (Respect): به همکارانت اهمیت بده. باور کن که آنها هم باهوش و با‌انگیزه هستند. با آنها مهربان باش، حتی وقتی نظر مخالف داری.
  3. اعتماد (Trust): باور کن که دیگران هم کارشان را بلدند. به آنها اجازه بده تصمیم بگیرند و کار را پیش ببرند. لازم نیست همه چیز را خودت کنترل کنی.

تمرین عملی: منیت (Ego) را کنار بگذار

یکی از سخت‌ترین کارها برای برنامه‌نویس‌ها، جدا کردن «خودشان» از «کدشان» است. باید مدام به خودت یادآوری کنی:

«من کُدم نیستم.» (You are not your code)

وقتی کسی از کد تو انتقاد می‌کند (مثلاً در Code Review)، دارد از کد انتقاد می‌کند، نه از شخصیت تو. اگر این را بپذیری، دیگر از پیدا شدن باگ در کدت ناراحت نمی‌شوی، بلکه خوشحال می‌شوی که محصول بهتر شده است.

خلاصه بخش ۱ فصل ۲

  • افسانه نابغه را فراموش کن: نرم‌افزار بزرگ کار تیمی است، نه فردی.
  • کد را قایم نکن: زودتر شکست بخور (Fail Fast) تا زودتر یاد بگیری.
  • HRT را تمرین کن: فروتنی، احترام، اعتماد.
  • تو کُدت نیستی: نقد کد، نقد شخصیت تو نیست.

فصل ۲ – ادامه: هنگامی که کدتان شکست بخورد (Blameless Post-Mortem)

مقدمه: اگر صرف نظر کنید، مشکل بزرگ تر می‌شود

تا اینجا یاد گرفتی که مهندسی نرم‌افزار کار تیمی است و نباید کد خود را مخفی کنی. اما حالا سوال مهمی مطرح می‌شود:

اگر تیم تو کدی شکسته به تولید ببرد، چه اتفاقی می‌افتد؟

در بسیاری از شرکت‌ها، جواب این سوال ساده است: مقصر‌گیری شروع می‌شود. رئیس سر و صدا می‌کند، ایمیل‌های عصبانی فرستاده می‌شود، و فرد مسئول احساس بدی می‌کند.

اما Google یک رویکرد متفاوت را انتخاب کرده: فرهنگ Post-Mortem بدون مقصریابی (Blameless Post-Mortem Culture).

اصل اول: شکست یک فرصت یادگیری است

گوگل یک شعار مشهور دارد: «شکست یک گزینه است» (Failure is an option)

اگر تیم شما هرگز ناکام نمی‌شود، یعنی کافی ریسک نمی‌گیری. اگر کافی ریسک نمی‌گیری، یعنی نوآوری نمی‌کنی. و اگر نوآوری نمی‌کنی، رقابت‌های شما تو را تحت فشار خواهند داد.

Thomas Edison یکی از بهترین نقل‌های مشهور را داشت:

«اگر ۱۰,۰۰۰ راه پیدا کنم که چیزی کار نمی‌کند، ناکام نشده‌ام؛ فقط ۱۰,۰۰۰ قدم به جلو رفته‌ام.»

مثال: Google X و Moonshot Projects

در بخش Google X (نام فعلی: X Development)، جایی که روی پروژه‌های جنگلی مثل خودروهای بدون راننده کار می‌کنند، شکست عمداً و به اصرار در فرهنگ درج شده است.

در اینجا چنین می‌دهند:

  • تیم‌ها با ایده‌های احمقانه و فاقد تجربه می‌آیند
  • تشویق می‌کنند هم‌تیمی‌ها آن را سریع‌تر refute کنند
  • بهترین ایده‌ها (که نمی‌توان refute کرد) به سراغ تلاش جدی می‌روند

نتیجه؟ کمتر وقت و منابع در ایده‌های بدی تلف می‌شود.

Post-Mortem چیست؟

Post-Mortem (درحرفی: «بعد از مرگ») یک اجلاس رسمی است که بعد از یک صدمه (مثل down شدن سرور یا باگ بزرگ) برگزار می‌شود تا یاد بگیریم چه اتفاق افتاد.

در اینجا کلید است: post-mortem درباره جستجوی مقصر نیست، درباره یادگیری است.

چه چیزی یک Post-Mortem خوب دارد؟

طبق کتاب، یک سند «پس از حادثه» (Post-Mortem) خوب باید شامل این بخش‌های کلیدی باشد:

بخش توضیح
خلاصه اجمالی (Brief Summary) چه اتفاقی افتاد؟ (در حد ۲ تا ۳ جمله کوتاه).
خط زمانی (Timeline) حادثه از کی شروع شد؟ کی کشف شد؟ و کی برطرف شد؟
دلیل اصلی (Root Cause) ریشه و علت اصلی مشکل چه بود؟ (نه اینکه چه کسی اشتباه کرد).
تأثیر (Impact) چه آسیبی به سیستم یا کاربران وارد شد؟
اقدامات فوری (Immediate Actions) برای رفع سریع مشکل چه کاری انجام شد؟
اقدامات پیشگیرانه (Action Items) چه کارهایی باید انجام دهیم تا این اتفاق دیگر تکرار نشود؟
درس‌های آموخته‌شده (Lessons Learned) چه چیزی یاد گرفتیم که قبلاً نمی‌دانستیم؟

نمونه Post-Mortem خوب در مقابل بد

نکته کلیدی اینجاست که در Post-Mortem نباید دنبال «مقصر» بگردیم، بلکه باید دنبال «ایراد سیستم» باشیم.

❌ Post-Mortem بد (تمرکز بر مقصر):

«حسن یک کوئری (Query) بد روی دیتابیس اجرا کرد و باعث شد کل سیستم پایین بیاید. حسن باید قبل از اجرا، کوئری را با دقت بیشتری بررسی می‌کرد.»

✅ Post-Mortem خوب (تمرکز بر یادگیری و سیستم):

مشکل: یک کوئری سنگین باعث شد مصرف CPU دیتابیس به ۱۰۰٪ برسد و سرویس از دسترس خارج شود.

دلیل اصلی: ما ابزاری برای پایش (Monitoring) کوئری‌های سنگین نداشتیم و در فرآیند «بازبینی کد» (Code Review) هم بررسی پیچیدگی کوئری الزامی نبود.

اقدام پیشگیرانه: ۱. اضافه کردن ابزار مانیتورینگ برای شناسایی خودکار کوئری‌های کند. ۲. اصلاح چک‌لیست Code Review تا بررسی پرفورمنس کوئری‌ها اجباری شود.

می‌بینید؟ در مدل خوب، اسم «حسن» حذف شده است. چون اگر حسن نبود، ممکن بود شخص دیگری همین اشتباه را بکند. مشکل واقعی «حسن» نبود، بلکه «نبودِ سیستم نظارتی» بود.

چرا فرهنگ «بدون سرزنش» (Blameless) مهم است؟

اگر در تیمتان مدام دنبال مقصر باشید، این اتفاقات می‌افتد:

  1. پنهان‌کاری: مهندسان وقتی اشتباه کنند، آن را قایم می‌کنند تا توبیخ نشوند. (این خطرناک‌ترین حالت است!)
  2. ترس از نوآوری: هیچ‌کس جرأت نمی‌کند ایده جدیدی را امتحان کند، چون می‌ترسد خراب شود و سرزنش شود.
  3. کاهش روحیه: فضای تیم سمی و پر از استرس می‌شود.

اما اگر فرهنگ بدون سرزنش داشته باشید:

  1. شفافیت: مهندسان بدون ترس می‌گویند: «من اشتباه کردم» و همه سریع‌تر مشکل را حل می‌کنند.
  2. پیشرفت سیستم: به جای تنبیه افراد، سیستم‌ها و ابزارها را قوی‌تر می‌کنید تا جلوی خطای انسانی را بگیرند.
  3. یادگیری تیمی: اشتباه یک نفر تبدیل به درس عبرت برای همه می‌شود.

ارتباط با سه اصل (HRT)

این فرهنگ دقیقاً روی همان سه ستون اصلی فصل ۲ بنا شده است:

  • فروتنی (Humility): قبول می‌کنیم که همه ما (حتی مدیران ارشد) ممکن است اشتباه کنیم.
  • احترام (Respect): به کسی که اشتباه کرده احترام می‌گذاریم و باور داریم که نیت بدی نداشته است.
  • اعتماد (Trust): اعتماد داریم که هم‌تیمی‌هایمان باهوش هستند و از این اشتباه درس می‌گیرند.

خلاصه این بخش

تا اینجا دو درس مهم از فصل ۲ گرفتیم: ۱. کدتان را پنهان نکنید: کار تیمی یعنی اشتراک‌گذاری سریع، حتی اگر کار ناقص باشد. ۲. شکست پل پیروزی است (اگر سرزنش نباشد): وقتی سیستم خراب می‌شود، به جای پیدا کردن «مقصر»، دنبال اصلاح «فرآیند» باشید.


فصل ۲ – بخش آخر: هنر نقد کردن و نقد شنیدن (Code Review & Feedback Culture)

معاملهٔ سختِ نقد و انتقاد

هر کس از انتقاد متنفر است. حتی بهترین برنامه‌نویس‌ها، وقتی کار شان را برای بررسی مجدد ارائه می‌دهند، کمی نگران می‌شوند: «شاید تعداد زیادی اشتباه دارد؟ شاید فکر می‌کنند من خوب نیستم؟»

مسئلهٔ اصلی این است که در بسیاری از شرکت‌ها، نقد اغلب بیرحمانه و شخصی است. لطفاً به نمونه‌های زیر توجه کنید:

❌ نقد بد (خصمانه و غیرسازنده)

«مِی‌خدا، کنترل‌جریان (Control Flow) این متد کاملاً اشتباه است! همه از پترن xyzzy استفاده می‌کنند. چرا تو این کار رو نمی‌کنی؟»

این نوع نقد چه مشکلاتی دارد:

  • شخصی‌سازی: انگار شخص خود غلط است، نه کد
  • محکومیت: از کلمهٔ «اشتباه» استفاده می‌کنی
  • فشار: از او می‌خواهی تغییر کند، بدون جواب
  • انزجار ایجاد می‌کند: فرد بلافاصله دفاعی می‌شود

✅ نقد خوب (سازنده و احترام‌آمیز)

«من با کنترل‌جریان این بخش گیج شدم. آیا استفاده از پترن xyzzy می‌تواند این قسمت را برای من روشن‌تر کند؟ شاید کد را هم نگاه‌داشتن در طول زمان آسان‌تر کند.»

چرا این بهتر است:

  • فروتنی: مسئلهٔ درک من است، نه شما
  • پیشنهاد، نه فرمان: «آیا… می‌تواند» بدتر از «باید»
  • توجه به کد: در مورد کد صحبت می‌کنیم، نه شخصیت
  • انتخاب به دست فرد: او می‌تواند پیشنهاد را قبول یا رد کند
  • مشترک: هر دوتان برای بهتری پروژه کار می‌کنید

تفریق مهم: «تو کدی نیستی»

یکی از مشکلات اساسی برنامه‌نویسان این است که خود را با کار خود یکی می‌دانند. اگر کسی کد‌ات را نقد کرد، احساس می‌کنی که تو شخصاً نقد شده‌ای.

اما این اشتباه است:

تصور غلط واقعیت
کد تو = تو کد تو ≠ تو
نقد کد = نقد شخصیت نقد کد = بهتری شدن
اگر کد سوء است، من سوء‌ام اگر کد سوء است، یاد می‌گیریم

کد نوشتن مثل هر مهارتی است—تنیس، نقاشی یا سخنرانی. اگر مربی تنیستت بگوید «سرویس‌ات ضعیف است»، این نمی‌خواهد بگوید تو نسبت به انسان‌بودن ناشایست!

نقد گرفتن (از دید گیرنده)

وقتی کسی نقد می‌کند:

۱. باور کن که نیت خوب دارند:

  • آنها (امیدا) می‌خواهند پروژه بهتر شود
  • آنها نمی‌خواهند تو را دار و دستگیر کنند
  • آنها می‌خواهند از اشتباه ‌ها یاد بگیری

۲. نقد را صفر میز بگیر:

  • خود را دفاع نکن
  • بپرس: «آیا می‌تونی مثال بزنی؟»
  • فکر کن: «آیا حق دارند؟»

۳. مسالمت‌آمیز پاسخ بده:

  • اگر موافق بودی: «خیلی خوب، درست گفتی!»
  • اگر مخالف بودی: «متوجه شدم. البته من فکر می‌کنم [دلیل بهتر]. آیا می‌تونی این نقطهٔ نظر رو بررسی کنی؟» (از انگلیسی: PTAL = Please Take Another Look)

نقد دادن (از دید دهنده)

وقتی تو دارای نقد هستی:

۱. زمان صحیح انتخاب کن: دوست‌تان کار را در تنهایی انجام داده؟ یا در تیم؟ آیا تازه شروع کرد یا تقریباً تمام شد؟

مثال: اگر همکار جدیدی است و نقد‌سازی در فرهنگ شرکت معمول نیست، قبل از شروع حتی یک نقد، اول بگو چه می‌خواهی انجام دهی.

۲. قاطعیت را بپرس:

  • سؤال کن: «آیا می‌تونی مثال بدی؟»
  • شرح بده: «چرا فکر می‌کنی این بهتره؟»
  • گوش کن: شاید او دلیل خوبی دارد

۳. حفاظت کن: نقد را خصوصی انجام بده، نه علنی. اگر برای تیم درس است، درس بده. اما نقد شخصی را نه!

مثالِ واقعی: داستانِ جو (Joe’s Story)

جو در شرکت جدیدی کار شروع کرد. بعد از یک هفته، شروع به نقد کدِ تیم کرد:

«سلام، متوجه شدم تو از آن الگوی X استفاده کردی. البته می‌توانستی از Y هم استفاده کنی…»

اما مشکل:

  • جو با بدون آموختن فرهنگ تیم شروع کرد
  • فریقش هنوز نقد سازی را برای نقد اصلاح نکرده بود
  • تیم احساس کرد: «این یارو داره ما رو نقد می‌کنه؟»

نتیجه: رئیسش تلفن کرد و گفت: «لطفاً سریع‌تر نقد نکنید. تیم ناراحت است.»

درس: قبل از نقد دادن، قاعدهٔ بازی را بیاموز. شاید اول در تیم بحث کن: «می‌تونیم Code Review شروع کنیم؟» و بعدش شروع کن.

خلاصهٔ سه اصل (HRT) در Code Review

اصل نقد‌دهنده نقد‌گیرنده
Humility (فروتنی) «من نمی‌فهمم» «من نمی‌دانستم»
Respect (احترام) «می‌خواهم کمکت کنم» «تو نیت خوب داری»
Trust (اعتماد) «تو خوب هستی، فقط این…» «پذیر، می‌خواهی بهتر شوی»

درسِ نهایی این فصل

فصل ۲ کتاب «Software Engineering at Google» درباره سه چیز مهم بود:

۱. بترس نه، بشنو: کار تیمی بهتر از تنهایی است ۲. بیاموز نه، سرزنش کن: شکست فرصت یادگیری است، نه جنایت ۳. نقد کن با عشق: نقد سازنده، نه تخریب‌کنندهٔ

نکتهٔ پایانی: فریق میل و فقط شماست

به قول نویسندهٔ فصل Brian Fitzpatrick:

«اگر می‌خواهی موفق باشی، یاد بگیر که با دیگران کار کنی. هر آن چیزی که برنامه‌نویسی ۱۰۰٪ یاد می‌گیری، نقش اصلی ندارد. آن چیزی که اهمیت دارد، **نحوهٔ کار کردن با انسان‌ها است.»


فصل ۲ – بخش نهایی: کمونیتی و اشتراک دانش (Knowledge Sharing & Learning Together)

پرسیدن سؤال: درخواست کمک بدون شرم

یکی از مهم‌ترین مهارت‌های یک مهندس نرم‌افزار، خوب پرسیدن سؤال است. اما بسیاری از برنامه‌نویس‌ها احساس می‌کنند که اگر سؤال بپرسند، می‌شود نشانه‌ای بر ضعف و نادانی.

اما این غلط است.

چرا پرسیدن سؤال اهمیت دارد؟

تصور کنید تنهایی با یک مشکل وقت‌تلفی می‌کنید. شاید ۲ ساعت یا حتی یک روز بدون پیشرفت. اما اگر به یک همکار بپرسی، شاید در ۵ دقیقه جواب پیدا شود.

ریاضیِ ساده:

  • اگر نپرسی: ۸ ساعت تلف
  • اگر بپرسی: ۰.۵ ساعت (وقت سؤال) + ۱ ساعت یادگیری = ۱.۵ ساعت

بدتر هم می‌شود: اگر اول می‌پرسیدی، هم‌تیمی‌ات هم یاد می‌گرفتند!

مثال واقعی: داستان بریان

یکی از نویسندگان کتاب، بریان فیتزپاتریک، داستانی را تعریف می‌کند:

قبلاً در Google یک ابزار برای تبدیل CVS به Subversion نوشت. کارل، دوست و همکار بریان، خیلی خوب CVS را می‌شناخت.

وقتی بریان و کارل شروع کردند pair programming (برنامه‌نویسی در دو نفر)، مشکل پیش آمد:

  • بریان: یک مهندسِ “پایین به بالا” (Bottom-up) بود—سریع خود را غوطه‌ور می‌کرد و با آزمایش و خطا کار می‌کرد.
  • کارل: یک مهندسِ “بالا به پایین” (Top-down) بود—می‌خواست تمام جزئیات و ساختار را اول درک کند.

نتیجه: مشاجره و بحث‌های درون‌کشی!

اما بعداً بریان فهمید: آنها دارای سبک‌های متفاوت بودند، نه “درست” و “غلط”.

درس: صبر کن، به دیگری احترام بگذار و یاد بگیر که چطور با سبک‌های متفاوت کار کنی.

یادگیری و اشتراک‌دانش در تیم

برای اینکه یک تیم بسیار خوب باشد، همه باید با هم یادگیری کنند.

۱. گروه‌چت (Group Chat)

مثل Slack یا Microsoft Teams:

  • مزایا: سریع، بی‌درخت، همه می‌توانند ببینند
  • معایب: بی‌ساختار، یافتن پاسخ‌های قدیمی سخت است

۲. فهرست‌های ایمیل (Mailing Lists)

مثل موضوع‌های بحث Google Groups:

  • مزایا: ساختار‌دار، قابل‌جستجو، دائمی
  • معایب: کند است، برای سؤالات سریع اسمٹ نیست

۳. سیستم‌های سؤال‌و‌پاسخ (Q&A Systems)

مثل Stack Overflow یا YAQS در Google:

  • مزایا: بهترین پاسخ‌ها “up-vote” می‌شوند، کاملاً سازمان‌یافته
  • معایب: نیاز به وقت برای نوشتن خوب

شاگردی و آموزش (Mentoring & Teaching)

⚠️ حقیقتِ اساسی

هر کس درس‌های کچھ را می‌دانند.

شما نه “خبره” و نه “مبتدی” نیستید—شما در حال حرکت هستید.

همکار جدیدی نیاز به کمک توست. اما یک نفر جدید‌تر نیز یک روز از تو یادگیری می‌کند!

۴ روش برای تدریس و اشتراک دانش:

A. ساعات کاری (Office Hours)

مثل مشاوره دانشگاه: هر هفته ۱ ساعت برای پاسخ‌گویی به سؤالات.

B. سخنرانی‌های فنی (Tech Talks)

مثل یک پریزنتیشن نیمه‌ساعتی در مورد موضوع مشخص.

C. کلاس‌های یادگیری (Classes)

درس سازمان‌یافته‌تر، اگر موضوع پیچیده است.

D. مستندات (Documentation)

این بخش خیلی مهم است!

اولین بار که چیزی یاد گرفتی، بهترین زمان برای نوشتن است، چون هنوز می‌دانی کدام قسمت‌ها سخت بود!

درس: بهبود مستندات

در Google، هر مهندس می‌تواند هر مستند را اصلاح کند—حتی اگر مالک آن نباشد.

اگر خطای کوچک دیدی (مثلاً یک تایپو):

  • تصحیح کن
  • فائل را ارسال کن (PR)
  • در نظری شامل شو

قانون “دختر پیشاهنگ”: راه‌یابی را تمیز‌تر از حالتی ترک کن که آن را یافته‌ای!

احترام و لطف در اشتراک دانش

اصلاح کن: بسیاری از شرکت‌ها تولرانس (یا حتی ستایش!) می‌کنند “برنامه‌نویس کند” (Brilliant Jerk)—افرادی که باهوش هستند اما ناخوشایند.

نتیجه؟ تیم روحیه‌ اش پایین می‌رود.

Google یاد دارد: خبره بودن و لطیف بودن متضاد نیستند.

به قول رهبران Google:

«رهبران بهترِ مردمی اطراف خود را بهتر می‌کنند. آنها ایمنی روانی تیم را بالا می‌برند. مردم جاهل رهبر خوبی نیستند.»

خلاصهٔ فصل ۲ کامل: سه ستون + یک شهر

عنصر معنی در عمل
Humility (فروتنی) من همه‌چیز نمی‌دانم سؤال بپرس، مستند بخوان
Respect (احترام) دیگران ارزشمند هستند آنها را گوش کن، کمک کن، تدریس کن
Trust (اعتماد) دیگران خوب هستند فرض کن نیت خوبند، تفویض کن
Knowledge Sharing یادگیری مشترک کمونیتی بساز، مستند نویس، رهنمایی کن

پیام نهایی فصل ۲

فصل ۲ کتاب «Software Engineering at Google» درباره یک حقیقت ساده است:

«برنامه‌نویسی درباره نویسندگی است. اما مهندسی نرم‌افزار درباره کار با انسان‌ها است.»

اگر می‌خواهی واقعاً موفق باشی: ✅ قایم نکن — کار تیمی کن
شکست را بپذیر — از اشتباه‌ها یاد بگیر
نقد سازنده بده — احترام‌آمیز باش
نقد گیر — دفاع نکن
پرسیدن و تدریس — کمونیتی بساز

این بود فصل ۲ — یکی از مهم‌ترین فصل‌های کتاب. اگر تنها یک فصل از کل کتاب برای مهندسین جدید خواندنی است، این باید همان باشد.


حتماً، معذرت می‌خواهم. متن قبلی کمی ناشیانه بود. این هم بازنویسی کامل و روان فصل ۳ با فارسی معیار:

فصل ۳: اشتراک دانش (Knowledge Sharing)

مقدمه: سازمان شما چقدر باهوش است؟

یکی از بزرگ‌ترین چالش‌های هر سازمان این است: آیا دانش افراد به کل سازمان منتقل می‌شود؟

اگر در تیم شما ۱۰ مهندس خبره وجود داشته باشد ولی دانش آن‌ها به بقیه منتقل نشود، در واقع شما یک تیم باهوش ندارید؛ بلکه ۱۰ فرد باهوش دارید که جداگانه کار می‌کنند. هدف فصل ۳ این است که چطور از «افراد باهوش» به «سازمان باهوش» برسیم.

چالش اول: ایمنی روانی (Psychological Safety)

اولین شرط یادگیری، ایمنی روانی است. یعنی اعضای تیم باید احساس کنند که می‌توانند بدون ترس از مسخره شدن یا سرزنش شدن، سؤال بپرسند.

  • اگر کسی بپرسد «فلان ابزار چطور کار می‌کند؟» و همکارش بگوید «واقعاً نمی‌دانی؟! این که خیلی ساده است!»، آن شخص دیگر هرگز سؤال نخواهد پرسید.
  • وقتی سؤال پرسیده نشود، دانش منتقل نمی‌شود.
  • نتیجه: هر کس چرخ را برای خودش دوباره اختراع می‌کند.

چالش دوم: جزایر دانش (Islands of Knowledge)

وقتی دانش به اشتراک گذاشته نمی‌شود، تیم‌ها مثل جزیره‌های جدا از هم عمل می‌کنند:

  • تیم الف با مشکل X روبرو می‌شود و یک هفته وقت می‌گذارد تا آن را حل کند.
  • تیم ب ماه بعد با همان مشکل X روبرو می‌شود و آنها هم یک هفته وقت می‌گذارند.
  • اگر تیم الف راه‌حلش را مستند کرده بود، تیم ب می‌توانست در ۱۰ دقیقه مشکل را حل کند.

راهکارها: چهار روش برای اشتراک دانش

۱. پرسش و پاسخ (Q&A)

ساده‌ترین راه، پرسیدن است. اما نکته مهم این است که پاسخ باید در دسترس همه باشد.

  • روش بد: ارسال پیام خصوصی به یک متخصص. (فقط یک نفر یاد می‌گیرد).
  • روش خوب: پرسیدن در گروه عمومی (Slack یا Teams) یا یک سامانه پرسش و پاسخ (مثل Stack Overflow داخلی). (ده‌ها نفر یاد می‌گیرند).

۲. مستندسازی (Documentation)

بسیاری از مهندسان از نوشتن مستندات فراری هستند چون فکر می‌کنند باید «کامل و بی‌نقص» باشد.

  • قانون طلایی گوگل: مستندات باید زنده باشند.
  • مالکیت جمعی: هر کسی که یک مستند را می‌خواند و اشکالی می‌بیند (حتی یک غلط املایی)، باید همان لحظه آن را اصلاح کند. نباید منتظر «نویسنده اصلی» بماند.

۳. آموزش از طریق کد (Code Review)

کد فقط برای کامپایل شدن نیست؛ کد یک وسیله ارتباطی بین انسان‌هاست. فرآیند بازبینی کد (Code Review) بهترین فرصت برای آموزش است. وقتی یک مهندس ارشد کد یک تازه‌کار را نقد می‌کند، در واقع دارد دانش و تجربیاتش را به او منتقل می‌کند.

۴. برنامه‌های آموزشی (Education Programs)

گوگل روش‌های خلاقانه‌ای برای آموزش دارد:

  • Testing on the Toilet (آموزش در سرویس بهداشتی!): مهندسان گوگل برگه‌های آموزشی یک‌صفحه‌ای (مثلاً درباره روش‌های جدید تست‌نویسی) را چاپ می‌کنند و در داخل سرویس‌های بهداشتی نصب می‌کنند. چون آنجا تنها جایی است که افراد وقت خالی دارند و مجبورند چیزی بخوانند! این روش عجیب، بسیار مؤثر بوده است.

  • Tech Talks (سخنرانی‌های فنی): هر کسی می‌تواند یک ارائه ۳۰ دقیقه‌ای درباره موضوعی که بلد است برگزار کند. این ویدیوها ضبط و آرشیو می‌شوند.

فرهنگ «خوانایی» (Readability) در گوگل

یکی از جالب‌ترین برنامه‌های گوگل، مدرک Readability است.

در گوگل، برای اینکه بتوانید کدی را به مخزن اصلی (Repository) ارسال کنید، باید یا خودتان مدرک «خوانایی» آن زبان (مثلاً ++C یا Java) را داشته باشید، یا یک نفر که این مدرک را دارد، کد شما را تأیید کند.

این مدرک چیست؟ این مدرک نشان می‌دهد که شما نه تنها آن زبان را بلد هستید، بلکه تمام استانداردهای کدنویسی گوگل (Best Practices) را هم رعایت می‌کنید.

این سیستم باعث می‌شود که: ۱. کدها یکدست و تمیز باقی بمانند. ۲. افراد در طول فرآیند گرفتن مدرک، کلی نکته جدید یاد بگیرند.

خلاصه فصل ۳

برای اینکه سازمان شما یادگیرنده باشد:

  1. بترسید اما بپرسید: فضایی بسازید که پرسیدن «نمی‌دانم» عیب نباشد.
  2. بنویسید: هر چیزی که یاد می‌گیرید را جایی (حتی ناقص) یادداشت کنید.
  3. به اشتراک بگذارید: دانش قدرت نیست؛ اشتراک دانش قدرت است.
  4. احترام بگذارید: متخصصان واقعی کسانی هستند که دانش خود را با فروتنی به دیگران یاد می‌دهند، نه کسانی که دیگران را تحقیر می‌کنند.

فصل ۴: مهندسی برای عدالت (Engineering for Equity)

مقدمه: وقتی فناوری بی‌طرف نیست

ما اغلب فکر می‌کنیم کد و ریاضیات «بی‌طرف» هستند. ۲+۲ همیشه می‌شود ۴، و کد هم همان کاری را می‌کند که نوشته شده. اما این فصل یک حقیقت تلخ را به ما یادآوری می‌کند: فناوری می‌تواند ناعادلانه باشد.

اگر مهندسان فقط به «اکثریت» کاربران فکر کنند، محصولاتی می‌سازند که برای اقلیت‌ها کار نمی‌کنند یا حتی به آنها آسیب می‌زنند.

سوگیری (Bias) پیش‌فرض است

اولین درسی که باید بپذیریم این است: «سوگیری پیش‌فرض است» (Bias is the default).

همه ما سوگیری‌های ناخودآگاه (Unconscious Bias) داریم. ما دنیا را از دریچه تجربیات خودمان می‌بینیم.

  • اگر راست‌دست هستیم، یادمان می‌رود که قیچی‌ها برای چپ‌دست‌ها سخت هستند.
  • اگر بینایی کامل داریم، یادمان می‌رود که سایت‌ها برای نابینایان غیرقابل استفاده‌اند.

در نرم‌افزار هم همین‌طور است. اگر تیم مهندسی فقط از مردان سفیدپوست تشکیل شده باشد، آنها محصولی می‌سازند که برای مردان سفیدپوست عالی است، اما ممکن است برای زنان یا رنگین‌بوستان فاجعه باشد.

مطالعه موردی: فاجعه Google Photos

یکی از تلخ‌ترین مثال‌های این فصل، اتفاقی است که در سال ۲۰۱۵ برای Google Photos افتاد. هوش مصنوعی گوگل عکس‌های دوستان سیاه‌پوست یکی از کاربران را به اشتباه به عنوان «گوریل» دسته‌بندی کرد.

چرا این اتفاق افتاد؟ ۱. داده‌های ناقص: داده‌هایی که برای آموزش هوش مصنوعی استفاده شده بود، تنوع نژادی کافی نداشت (اکثر عکس‌ها از سفیدپوستان بود). ۲. تیم یکدست: احتمالاً در تیم مهندسی و تست، افراد سیاه‌پوست کافی حضور نداشتند تا قبل از انتشار متوجه این مشکل شوند.

این فقط یک «باگ فنی» نبود؛ این یک شکست اخلاقی بود که باعث شرمندگی گوگل شد و اعتماد کاربران را خدشه‌دار کرد.

چرا باید برای «همه» بسازیم؟

شعار گوگل این است: «برای همه بسازید» (Build for Everyone). اما نویسنده می‌گوید این شعار کافی نیست. باید بگوییم: «با همه بسازید» (Build WITH Everyone).

اگر می‌خواهید محصولی عادلانه بسازید:

  1. تیم‌های متنوع استخدام کنید: زن، مرد، سیاه‌پوست، سفیدپوست، معلول، سالم. تنوع در تیم باعث می‌شود باگ‌های فرهنگی و اجتماعی زودتر کشف شوند.
  2. برای سخت‌ترین حالت طراحی کنید: اگر محصولتان را طوری طراحی کنید که برای یک نابینا قابل استفاده باشد، برای یک کاربر عادی هم قابل استفاده‌تر و تمیزتر خواهد بود (مثلاً دکمه‌های واضح‌تر، متن‌های خواناتر).

سرعت در برابر عدالت

در سیلیکون‌ولی همیشه شعار این است: «سریع حرکت کن و چیزها را بشکن» (Move fast and break things). اما فصل ۴ می‌گوید: «اگر چیزهایی که می‌شکنید، آدم‌ها هستند، سرعتتان را کم کنید.»

گاهی اوقات لازم است انتشار محصول را به تأخیر بیندازیم تا مطمئن شویم:

  • آیا این الگوریتم تشخیص چهره روی پوست‌های تیره هم کار می‌کند؟
  • آیا این سیستم استخدام خودکار، زنان را به خاطر فاصله‌های شغلی (مثلاً مرخصی زایمان) رد نمی‌کند؟

بهتر است دیرتر منتشر کنید تا اینکه محصولی نژادپرست یا جنسیت‌زده منتشر کنید.

خلاصه فصل ۴

  • کد سیاسی است: هر خط کدی که می‌نویسید، روی زندگی آدم‌ها تأثیر می‌گذارد.
  • سوگیری وجود دارد: فرض نکنید بی‌طرف هستید. مدام بپرسید: «این محصول چه کسانی را نادیده گرفته است؟»
  • تنوع قدرت است: تیم‌های متنوع محصولات قوی‌تری می‌سازند، نه فقط برای اینکه «کار خوب» کرده باشند، بلکه برای اینکه محصولاتشان برای بازار بزرگ‌تری کار می‌کند.
  • عدالت را اندازه بگیرید: همان‌طور که پرفورمنس سرور را مانیتور می‌کنید، عدالت الگوریتم‌هایتان را هم مانیتور کنید.

فصل ۵: چگونه یک تیم را رهبری کنیم (How to Lead a Team)

مقدمه: کشتی بدون کاپیتان

یک کشتی بدون کاپیتان تنها یک اتاق انتظار شناور است. اگر کسی فرمان را نگیرد و موتور را روشن نکند، کشتی فقط با جریان خواهد رفت. نرم‌افزار هم دقیقاً همین‌طور است: اگر رهبری نباشد، گروه از مهندسان فقط وقت تلف می‌کنند.

این فصل درباره دو نقش رهبری متفاوت در گوگل است:

  1. مدیر (Manager): رهبر مردم
  2. رهبر فنی (Tech Lead): رهبر فناوری

دو نقش اصلی رهبری

۱. مدیر مهندسی (Engineering Manager)

مدیر مسئول کارکرد، بهره‌وری و خوشحالی هر فرد در تیمش است. همچنین باید اطمینان حاصل کند که نیازهای کسب‌وکار برآورده شوند.

وظایف اصلی:

  • پرورش و توسعه افراد تیم
  • حل مشکلات بین‌فردی
  • تعیین اولویت‌ها و منابع
  • حفاظت از تیم از سیاست سازمانی

۲. رهبر فنی (Tech Lead)

رهبر فنی مسئول تصمیمات فنی، معماری، و پروژه‌های پریورتی است. این نفر معمولاً یک مهندس فعال است که علاوه بر رهبری، کد هم می‌نویسد.

وظایف اصلی:

  • معماری و طراحی سیستم
  • تقسیم‌بندی کار بین تیم
  • حل مسائل فنی پیچیده
  • تعیین سرعت پیشرفت (velocity)

۳. رهبر فنی و مدیر (Tech Lead Manager - TLM)

در تیم‌های کوچک یا نوپا، یک نفر هر دو نقش را بازی می‌کند. این یک نقش بسیار سخت است.

درس کلیدی: تأثیرگذاری بدون اقتدار (Influencing Without Authority)

یکی از مهم‌ترین مهارت‌های رهبری این است که افراد را بدون اینکه مستقیماً مسئول آنها باشی، تحت تأثیر قرار دهی.

مثال از گوگل: جف دین (Jeff Dean) یکی از مشهورترین مهندسان گوگل است. او مستقیماً فقط بخش کوچکی از تیم مهندسی گوگل را رهبری می‌کند، اما تأثیر او بر کل سازمان بسیار بزرگ است. این به خاطر دانش و سخن‌گویی او است، نه اقتدار رسمی.

یک مثال دیگر: تیم Data Liberation Front (تیمی که برنامه Takeout (خروج داده) را ساخت) با کمتر از شش مهندس، موفق شد که بیش از ۵۰ محصول گوگل را برای صادرات داده تهیه کند! چگونه؟ با این که:

  • یک نیاز استراتژیک را شناسایی کردند
  • نشان دادند که این با اولویت‌های شرکت تطابق دارد
  • ابزاری ایجاد کردند که دیگر تیم‌ها به راحتی می‌توانستند استفاده کنند

فصل ۶: رهبری در مقیاس بزرگ (Leading at Scale)

وقتی شما رهبر یک تیم می‌شوید، بعد طبیعی این است که رهبر چند تیم شوید. در این مرحله، شما نام‌ها و تفاصیل فنی کمتر می‌بینید و بیشتر به استراتژی و راهبری بر مسائل بزرگ‌تر تمرکز می‌کنید.

سه اصل رهبری در مقیاس بزرگ:

۱. Always Be Deciding (همیشه تصمیم بگیر)

وظیفهٔ شما شناسایی تعادل بین انتخاب‌های متضاد است. هر تصمیم مهم شامل trade-off است.

مثال: مسئلهٔ سرعت جستجوی گوگل

مسئلهٔ سرعت جستجو را می‌توانستند به دو بخش تقسیم کنند:

  • علائم سرعت: تسریع کدموجود
  • علل سرعت: پیشگیری از مسائل سرعت اصلاً

کسانی که فقط روی تسریع کار می‌کردند، توانایی خود را هدر می‌دادند، زیرا هزاران مهندس دیگر به کدهای نتایج جستجو ویژگی‌های جدید اضافه می‌کردند و سرعت بهبود‌یافتهٔ آنها را منهی می‌کردند. با داشتن دو تیم که روی دو جنبهٔ متفاوت کار می‌کردند، مسئله حل شد.

۲. Always Be Leaving (همیشه برای떠ایی آماده باش)

یکی از بزرگ‌ترین خطاها برای رهبری این است که خود را غیرقابل‌جایگزین (Single Point of Failure - SPOF) کنی.

نکتهٔ اساسی: شما باید نه فقط خودتان بلکه رهبری‌های جدید را تربیت کنید.

اگر همیشه کارهای مهم را خود انجام دهی:

  • ❌ تیمت نمی‌تواند رشد کند
  • ❌ تو یک SPOF می‌شوی
  • ❌ تو خسته و سوخته می‌شوی

جای اینکه کاری را خود انجام دهی (که تیم سریع‌تر به انجام برسد)، آن را به دیگری تفویض کن. شاید بیشتر طول بکشد، اما:

  • تیمت یاد می‌گیرد
  • تو برای مسائل بزرگ‌تر فارغ می‌شوی
  • سازمان مستقل‌تر می‌شود

۳. Always Be Scaling (همیشه مقیاس بده)

سؤال مهمی که باید هر روز از خودت بپرسی:

«چه کاری است که فقط من می‌تونم انجام دهم؟»

پاسخ‌های خوب: ✓ دید بلند‌مدت و استراتژی را تعریف کنی ✓ تیمت را از سیاست سازمانی محافظت کنی ✓ افراد را تشویق کنی ✓ اطمینان حاصل کنی که همه احترام و لطف را رعایت می‌کنند ✓ با مدیریت بالاتر ارتباط برقرار کنی

جمع‌بندی

فصل ۵ و ۶ درس این را می‌دهند:

  • رهبری مهارتی است که یاد گرفته می‌شود، نه شامل‌دولت
  • بهترین رهبران خادم رهبر (Servant Leaders) هستند
  • اصلی‌ترین کار شما افراد را تربیت کردن است، نه کد نوشتن
  • باید خود را قابل‌جایگزین کنی، نه غیرقابل‌جایگزین