
توسعه نرمافزار پدیده عجیبی است.
از سالهای گذشته خاطرات و داستانهای زیادی در ذهنم مانده؛ از روزهای اولی که فکر میکردیم توسعه هر نرمافزاری نهایتاً یک هفته زمان میخواهد، تا امروز که برای تخمین یک تسک کوچک هم باید بارها همهچیز را بالا و پایین کنیم.
اما شاید جالبتر از توسعه نرمافزار، توسعهی تیم نرمافزار باشد.
سالها پیش، زمانی که بیشتر درگیر پروژههای سفارشی و مذاکره با کارفرماها بودم، یکی از بحثهای تکراری همیشه زمان تحویل پروژه بود.
من میگفتم این پروژه حداقل ده ماه زمان نیاز دارد و کارفرما میگفت:
«خب ۵ نفر دیگر اضافه کنید و دو ماهه جمعش کنید!»
آن زمان همیشه یک مثال آماده در جیبم داشتم؛ مثالی که سالها قبل در یکی از فرومها خوانده بودم:
برای به دنیا آمدن یک بچه، به یک زن و ۹ ماه زمان نیاز است.
نمیشود ۹ زن را کنار هم گذاشت تا بچه در یک ماه متولد شود.
راستش را بخواهید روی نحوه گفتنش هم خیلی کار کرده بودم!
معمولاً هم تأثیر خودش را میگذاشت و طرف مقابل را به فکر فرو میبرد.
تا اینکه یکبار کسی جواب جالبی داد:
«درسته… ولی میشه با ۹ زن، در ۹ ماه، ۹ بچه به دنیا آورد.»
و حقیقت این است که آن جواب، از خیلی از بحثهای مدیریتی عمیقتر بود.
چون مسئله فقط تعداد آدمها نیست.
مسئله این است که چه بخشهایی از توسعه نرمافزار قابل موازیسازی هستند و چه بخشهایی نیستند.
همین سؤال ساده، ما را به یکی از پیچیدهترین چالشهای تیمهای نرمافزاری میرساند:
آیا بزرگتر شدن تیم، الزاماً خروجی را بیشتر میکند؟
در این نوشته میخواهم کمی درباره پاسخهای مختلفی که صنعت نرمافزار به این سؤال داده صحبت کنم؛ از تیمهای محصولمحور گرفته تا مرزهایی که بین تیمها شکل میگیرد و گاهی خودشان تبدیل به بخشی از مشکل میشوند.
اولین پاسخ صنعت نرمافزار به مشکل رشد، خیلی ساده بود:
اگر پروژه بزرگتر شد، آدم بیشتری اضافه کن.
مدل ذهنی هم کاملاً منطقی به نظر میرسید.
وقتی یک نفر نمیتواند کل پروژه را جلو ببرد، کار را تقسیم میکنیم و هر بخش را به یک نفر میدهیم.
در ظاهر همهچیز عالی بود:
سرعت بیشتر
تقسیم مسئولیت
موازیسازی کارها
فشار کمتر روی افراد
این مدل حتی قبل از شکلگیری تخصصهای امروزی وجود داشت؛ زمانی که هنوز فرانتاند، بکاند، DevOps یا Infrastructure به شکل امروزی از هم جدا نشده بودند.
در بسیاری از تیمها، هر توسعهدهنده مسئول بخشی از پروژه میشد:
یکی ماژول کاربران را مینوشت
یکی گزارشها را
یکی سیستم پرداخت را
و یکی هم دیتابیس را جمع میکرد
در نگاه اول، همهچیز منطقی و قابل مدیریت بود.
اما کمکم یک مشکل خودش را نشان میداد:
نرمافزار فقط مجموعهای از بخشهای جدا از هم نیست.
هر بخش به بخش دیگر وابسته است.
تصمیمهای کوچک در یک قسمت میتوانند رفتار قسمتهای دیگر را تغییر دهند.
هر عضو جدید تیم، علاوه بر کدی که مینویسد، یک هزینه پنهان هم وارد سیستم میکند:
هزینه ارتباط.
هرچه تعداد افراد بیشتر میشد:
هماهنگی سختتر میشد
دانش پروژه پخشتر میشد
تصمیمگیری کندتر میشد
و اختلاف در سبک توسعه بیشتر خودش را نشان میداد
کمکم تیمها متوجه شدند که اضافه کردن نیرو همیشه به معنی افزایش سرعت نیست.
گاهی حتی برعکس، پروژه با وجود آدمهای بیشتر، کندتر هم میشد.
سالها بعد، فرد بروکس در کتاب معروف The Mythical Man-Month این مسئله را با جملهای معروف توضیح داد:
Adding manpower to a late software project makes it later.
اضافه کردن نیرو به یک پروژه عقبافتاده، ممکن است آن را حتی عقبتر بیندازد.
با بزرگتر شدن پروژهها، دیگر تقسیم سادهی ماژولها کافی نبود.
تکنولوژیها پیچیدهتر شدند و هر بخش از توسعه نیاز به دانش عمیقتری پیدا کرد.
دیگر نمیشد انتظار داشت یک نفر هم رابط کاربری طراحی کند، هم API بنویسد، هم دیتابیس را مدیریت کند، هم Deployment انجام دهد و هم Performance سرورها را زیر نظر بگیرد.
اینجا بود که تیمهای تخصصی کمکم شکل گرفتند:
تیم Frontend
تیم Backend
تیم Infrastructure
تیم DevOps
تیم QA
و بعدتر تیمهای Data، Security، SRE و …
این مدل، در مقایسه با ساختارهای قبلی، یک پیشرفت بزرگ محسوب میشد.
تخصص باعث شد کیفیت بالاتر برود، ابزارها حرفهایتر شوند و افراد بتوانند روی حوزهی مشخصی عمیق شوند.
برای مدتی به نظر میرسید صنعت بالاخره پاسخ درست را پیدا کرده است.
اما مشکل جدیدی آرامآرام خودش را نشان داد.
وقتی تیمها بر اساس تخصص از هم جدا شدند، فقط مسئولیتها جدا نشدند؛
کمکم طرز فکرها هم جدا شد.
هر تیم زبان خودش را پیدا کرد.
هر تیم اولویتهای خودش را داشت.
و هر تیم دنیا را از زاویهی خودش میدید.
تیم Backend روی Performance و Stability حساس بود.
Frontend بیشتر درگیر تجربه کاربری و سرعت توسعه بود.
DevOps به Deployment و Reliability فکر میکرد.
Infrastructure دغدغهی هزینه، مانیتورینگ و منابع را داشت.
در ظاهر همه برای یک محصول کار میکردند، اما در عمل گاهی شبیه کشورهایی بودند که فقط از طریق مرزها با هم ارتباط دارند.
جالب اینجاست که این جدایی فقط بین تخصصها باقی نماند.
بعد از مدتی، حتی داخل یک تخصص هم مرزهای جدید شکل گرفت.
مثلاً در شرکتهایی که چند محصول داشتند:
هر محصول تیم Frontend خودش را داشت
تیم Backend خودش را
و استانداردها کمکم از هم فاصله میگرفتند
دو تیم Frontend داخل یک شرکت ممکن بود:
ساختار پروژه متفاوتی داشته باشند
روش State Management متفاوتی انتخاب کنند
استانداردهای تست متفاوتی داشته باشند
و حتی درباره سادهترین تصمیمهای معماری هم نگاه کاملاً متفاوتی پیدا کنند
در این مرحله، مشکل دیگر فقط توسعه نرمافزار نبود.
مشکل، توسعهی سازمان نرمافزاری شده بود.
و شاید این همان جایی باشد که معماری نرمافزار دیگر فقط یک مسئله فنی نیست؛
بلکه مستقیماً به ساختار تیمها، ارتباطات و فرهنگ سازمان وابسته میشود.
بعد از سالها تجربهی تیمهای تخصصی، صنعت نرمافزار کمکم متوجه یک مسئله مهم شد:
مشکل فقط تخصص نیست، مشکل فاصلهی بین تخصصهاست.
در بسیاری از شرکتها، فرآیند توسعه شبیه یک خط تولید شده بود.
Frontend منتظر Backend بود.
Backend منتظر Infrastructure بود.
QA منتظر همه بود.
و در نهایت هر مشکلی بین تیمها دست به دست میشد تا بالاخره یک نفر مسئولیتش را قبول کند.
اینجا بود که مدل تیمهای محصولمحور یا همان Squadها محبوب شد.
ایده در ظاهر خیلی جذاب بود:
به جای اینکه تیمها بر اساس تخصص جدا شوند، یک تیم کوچک تشکیل بدهیم که همه چیز لازم برای توسعهی یک محصول را داخل خودش داشته باشد.
مثلاً:
چند Frontend Developer
چند Backend Developer
QA
Product Owner
شاید DevOps یا Designer
همه داخل یک تیم.
هدف این بود که تیم بتواند بدون وابستگی دائمی به بخشهای دیگر، یک محصول یا Feature را از ابتدا تا انتها جلو ببرد.
این مدل چند مزیت بزرگ داشت:
ارتباطات سریعتر شد
تصمیمگیری سادهتر شد
مسئولیتپذیری بیشتر شد
و تیمها حس مالکیت واقعی روی محصول پیدا کردند
در خیلی از شرکتها، این مدل واقعاً سرعت توسعه را بالا برد.
اما باز هم، یک مشکل جدید آرامآرام خودش را نشان داد.
وقتی هر Squad مستقلتر شد، کمکم فرهنگ فنی خودش را هم ساخت.
هر تیم ابزارهای خودش را انتخاب میکرد.
هر تیم استانداردهای خودش را تعریف میکرد.
و هر تیم به مرور شبیه یک شرکت کوچک داخل شرکت اصلی میشد.
مثلاً دو تیم Frontend داخل یک سازمان ممکن بود:
ساختار پروژه متفاوتی داشته باشند
روش مدیریت State متفاوتی استفاده کنند
استانداردهای تست متفاوتی داشته باشند
Design System را متفاوت پیادهسازی کنند
و حتی نگاه متفاوتی به Clean Code داشته باشند
در کوتاهمدت این استقلال جذاب بود، چون تیمها سریعتر حرکت میکردند.
اما در بلندمدت، هزینهی پنهان خودش را نشان میداد:
Fragmentation یا تکهتکه شدن سازمان فنی.
کمکم:
جابهجایی نیرو بین تیمها سختتر میشد
دانش بین تیمها منتقل نمیشد
کدها قابل استفاده مجدد نبودند
و هر تیم دوباره بخشی از مشکلات را از اول حل میکرد
جالب اینجاست که صنعت نرمافزار هر بار برای حل یک مشکل، ساختار جدیدی میساخت؛
اما همان ساختار، بعد از مدتی مشکل تازهای ایجاد میکرد.
شاید چون مسئله اصلی فقط ساختار تیمها نیست.
بلکه نحوهی ارتباط، اشتراک دانش و ایجاد تعادل بین استقلال و هماهنگی است.
اگر بخواهم صادقانه بگویم، فکر نمیکنم صنعت نرمافزار هنوز پاسخ قطعی برای ساختار ایدهآل تیمها پیدا کرده باشد.
ما سالها تلاش کردیم با بزرگتر کردن تیمها سرعت را بیشتر کنیم و فهمیدیم ارتباطات میتوانند از خود توسعه سختتر شوند.
بعد تخصصها را جدا کردیم تا هرکس روی حوزهی خودش عمیق شود، اما دیوارهایی بین تیمها ساختیم که گاهی از دیوارهای فنی هم ضخیمتر شدند.
بعد سراغ Squadها و تیمهای محصولمحور رفتیم تا وابستگیها کمتر شوند و تیمها مستقلتر عمل کنند؛ اما این بار خطر Fragmentation و چندپاره شدن فرهنگ فنی را تجربه کردیم.
شاید مسئله اصلی این باشد که توسعه نرمافزار، فقط توسعهی کد نیست.
ما در واقع همزمان داریم:
سیستم فنی میسازیم
سیستم انسانی میسازیم
و سیستم ارتباطی میسازیم
و پیچیدگی واقعی معمولاً از جایی شروع میشود که این سه سیستم روی هم اثر میگذارند.
به مرور زمان، شرکتهای بزرگ فهمیدند که برای جلوگیری از این چندپارگی، فقط داشتن Developer خوب کافی نیست.
آنها شروع کردند به ساختن لایههای جدیدی از هماهنگی:
Chapterها
Guildها
Platform Teamها
Architecture Reviewها
Design Systemها
Shared Standards
و حتی نقشهایی شبیه Engineering Architect یا Principal Engineer
نه برای کنترل تیمها، بلکه برای جلوگیری از این که هر تیم تبدیل به یک جزیره مستقل شود.
شاید مهمترین چالش تیمهای نرمافزاری امروز همین باشد:
چطور میتوان هم استقلال تیمها را حفظ کرد و هم انسجام فنی سازمان را از بین نبرد؟
و احتمالاً پاسخ نهایی، نه در ساختارهای عجیب مدیریتی است و نه در فرآیندهای سنگین.
بلکه در ایجاد فرهنگی است که آدمها را تشویق کند:
دانش را به اشتراک بگذارند
مسئولیت مشترک داشته باشند
و نرمافزار را به چشم یک سیستم واحد ببینند، نه مجموعهای از مرزها و قلمروها.
شاید در نهایت، موفقترین تیمهای نرمافزاری آنهایی نباشند که بیشترین تعداد Developer را دارند؛
بلکه آنهایی باشند که بهتر از بقیه میتوانند با هم فکر کنند.