واژهنامه
برنامهنویسیِ دونفره pair programming
راهنما navigator
وظیفه task
برنامهنویسیِ افراطی extreme programming
عملیاتی production
همکاریِ تیمی collaborative teamwork
چرخش rotation
پیشگفتار
امروزه بسیاری از افرادی که در حوزهی توسعهی نرمافزار فعالیت میکنند، با مفهومِ برنامهنویسیِ دونفره آشنا هستند. با این حال، همچنان این روش به طورِ پراکنده در صنعت بهکار گرفته میشود. یکی از دلایل پذیرشِ محدودِ آن این است که مزایای برنامهنویسیِ دونفره در نگاهِ اول چندان واضح نیست و بیشتر در میانمدت و بلندمدت نمایان میشود. همچنین، این روش به سادگیِ «دو نفر پشتِ یک کامپیوتر» نیست، که بسیاری بهسرعت آن را کنار میگذارند چون احساسِ راحتی نمیکنند. اما طبقِ تجربهی ما، برنامهنویسیِ دونفره برای همکاریِ تیمی و تولیدِ نرمافزارِ باکیفیت بسیار حیاتی است.
«من و بتی اسنایدر از ابتدا یک جفت بودیم. من معتقدم که بهترین برنامهها و طراحیها توسط جفتها انجام میشوند، زیرا آنها میتوانند یکدیگر را نقد کنند، خطاهای هم را پیدا کنند و از بهترین ایدهها استفاده کنند.»
— ژان بارتیک، یکی از اولین برنامهنویسان
«همهی برنامههای عملیاتی را با دو نفر که پشتِ یک دستگاه نشستهاند، بنویسید.»
— کنت بک
ژان بارتیک یکی از زنانِ انیاک (ENIAC) بود که بسیاری از آنها بهعنوانِ اولین برنامهنویسان یاد میکنند. آنها وظیفهی برنامهنویسی را زمانی بر عهده گرفتند که حتی واژهی «برنامهنویسی» وجود نداشت، هیچ الگوی مشخصی برای آنها نبود، و کتابی هم برای آموزشِ این کار وجود نداشت. با این وجود، تصمیم گرفتند که برنامهنویسی را بهصورتِ دونفره انجام دهند. تقریباً ۵۰ سال طول کشید تا برنامهنویسیِ دونفره به یک اصطلاحِ رایج تبدیل شود، زمانی که کِنت بِکِ بزرگ در دههی ۱۹۹۰ میلادی این روش را در کتابِ خود با عنوانِ «برنامهنویسیِ افراطی» (Extreme Programming) شرح داد. این کتاب، اصولِ توسعهی نرمافزارِ چابک (Agile) را به مخاطبانِ گستردهتری معرفی کرد که برنامهنویسیِ دونفره یکی از این اصول بود.
برنامهنویسیِ دونفره (pair programming) اساساً به معنای کدنویسی توسطِ دو نفر در یک دستگاه است. این روش بسیار مشارکتی است و مستلزمِ ارتباطاتِ زیاد میانِ برنامهنویسان است. در حالی که دو برنامهنویس روی یک وظیفه (task) با هم کار میکنند، نه تنها کد مینویسند، بلکه کارشان را نیز برنامهریزی و دربارهی آن بحث میکنند. آنها ایدهها را در طولِ مسیر شفاف میکنند، رویکردها را بررسی میکنند و به راهحلهای بهتری میرسند.
در بخشِ اولِ این مقاله، «چگونه برنامهنویسی دونفره انجام دهیم؟»، به بررسیِ رویکردهای عملیِ مختلف در این روش میپردازیم. این بخش برای مخاطبانی است که به دنبالِ شروع یا بهبودِ این شیوه هستند.
بخشِ دوم و سوم، «مزایا» و «چالشها»، به اهدافِ برنامهنویسیِ دونفره و نحوهی مواجهه با چالشهایی که مانعِ دستیابی به این اهداف میشوند، میپردازند. این بخشها مناسبِ کسانی است که میخواهند درکِ بهتری از مزایای برنامهنویسیِ دونفره برای تیم و نرمافزارشان پیدا کنند یا ایدههایی برای بهبودِ این فرآیند به دست آورند.
بخشِ چهارم و پنجم، «آیا باید برنامهنویسیِ دونفره انجام داد یا خیر؟» و «اما واقعاً چرا زحمتش را بکشیم؟»، با جمعبندیِ دیدگاههای ما درباره برنامهنویسیِ دونفره در مقیاسِ کلیترِ جریان تیمی (team flow) و همکاری به پایان میرسند.
چگونه برنامهنویسیِ دونفره انجام دهیم؟
سبکها
راننده و راهنما (Driver and Navigator)
این نقشهای کلاسیک در برنامهنویسیِ دونفره، قابلِ استفاده در بسیاری از روشهای مختلفِ این سبک هستند.
راننده (driver) کسی است که کنترل را در دست دارد، یعنی پشتِ صفحه کلید نشسته است. تمرکزِ راننده بر روی تکمیلِ یک هدفِ کوچک است و مسائلِ بزرگتر را فعلاً نادیده میگیرد. راننده باید حتماً در حینِ کدنویسی توضیح دهد که چه کاری انجام میدهد.
راهنما (navigator) در نقشِ ناظر قرار دارد و زمانی که راننده کدنویسی میکند، کد را بازبینی میکند، دستورالعمل میدهد و افکار خود را به اشتراک میگذارد. همچنین، راهنما نگاهی به مسائلِ بزرگتر، اشکالاتِ احتمالی و گامهای بعدی دارد و آنها را یادداشت میکند.
هدف از این تقسیمبندی نقشها، داشتنِ دو دیدگاهِ متفاوت نسبت به کد است.
- راننده با رویکردی تاکتیکی و جزئینگر به جزئیاتِ کدنویسی میپردازد.
- راهنما با دیدگاهی استراتژیکتر، تصویرِ کلی را در ذهن دارد.
جریانِ معمول به این صورت است:
- یک وظیفهی نسبتاً مشخص را شروع کنید.
- روی یک هدفِ کوچک (tiny goal) توافق کنید. این هدف میتواند با یک تستِ واحد (Unit Test)، پیامِ Commit، یا یادداشتی روی یک برچسبِ چسبان (Sticky Note) تعریف شود.
- مرتباً نقشها را تغییر دهید. این مشارکتِ فعالِ مشترک باعث حفظِ انرژی و درکِ بهتر مسائل میشود.
- در نقش راهنما، از ورود به حالت «تفکرِ تاکتیکی» اجتناب کنید. جزئیات را به راننده بسپارید و با دیدگاهی میانمدت به فرایند نگاه کنید. ایدهها، موانعِ احتمالی و گامهای بعدی را یادداشت کنید و بعد از تکمیلِ هدفِ کوچک با راننده دربارهی آنها صحبت کنید تا جریانِ کارِ راننده مختل نشود.
پینگ پُنگ (Ping Pong)
این روش به خوبی با توسعهی تستمحور (TDD) سازگار است و برای وظایفِ کاملاً تعریفشده که میتوان آنها را به صورت تستمحور پیادهسازی کرد، ایدهآل است.
- پینگ: برنامهنویسِ A یک تستِ شکستخورده (falling test) مینویسد.
- پنگ: برنامهنویسِ B پیادهسازیِ لازم برای پاس کردنِ تست را مینویسد.
- سپس برنامهنویسِ B مرحلهی بعدی «پینگ»، یعنی تستِ شکستخوردهی بعدی را آغاز میکند.
- پس از هر «پنگ»، میتوان با همکاری، کد را بازنویسی (Refactor) کرد و سپس به تستِ شکستخورده بعدی پرداخت. این فرآیند از روش «قرمز – سبز – بازنویسی» پیروی میکند؛ تستِ شکستخورده بنویسید (قرمز). با حداقل تلاشِ ممکن، تست را پاس کنید (سبز). سپس کد را بازنویسی کنید.
برای مثالهای خوب از این رویکرد، میتوانید به کتابِ 99 Bottles of OOP نوشتهی Sandy Metz و Katrina Owen مراجعه کنید.
برنامهنویسی با سبک قوی (Strong-Style Pairing)
این تکنیک، بطورِخاص برای انتقالِ دانش خیلی مفید است و توسط Llewellyn Falco با جزئیاتِ بیشتر اینجا شرح داده شده است.
قانون: «برای اینکه ایدهای از ذهنِ شما به کامپیوتر منتقل شود، باید از دستانِ فرِد دیگری عبور کند.» در این سبک، معمولاً راهنما (navigator) فردی باتجربهتر است که با وظیفه یا ابزار آشناست، و راننده فردی تازهکار (در زبان، ابزار، یا کُدبیس) است. فردِ باتجربه بیشتر در نقشِ راهنما باقی میماند و راننده را راهنمایی میکند.
یکی از جنبههای بسیار مهم در این سبک این است که راننده باید به راهنما اعتمادِ کامل داشته باشد و با «درکِ ناقص» احساس راحتی کند. سوالاتی مانند «چرا؟» یا به چالش کشیدنِ راهحلها باید پس از جلسهی پیادهسازی مطرح شوند. این سبک، بهویژه برای افرادی که کاملاً تازهکار هستند، میتواند مؤثر باشد و یادگیریِ فعال (از طریقِ انجام دادن) را به یادگیریِ منفعل (از طریقِ مشاهده) ترجیح میدهد.
در حالی که این تکنیک ممکن است شبیهِ مدیریتِ جزئی (Micro-management) به نظر برسد، میتواند ابزارِ مفیدی برای شروعِ کار باشد. با این حال، نباید بیش از حد استفاده شود. هدف این است که بعد از مدتی بتوانید به راحتی نقشها را تغییر دهید و از حالتِ مدیریتِ جزئی خارج شوید. این نشانهای است که انتقالِ دانش موفق بوده است.
توسعهی دوتایی (Pair Development)
“توسعهی دوتایی” بیشتر از اینکه یک تکنیکِ خاص برای کارِ دوتایی باشد، یک نوع طرزِ فکر در موردِ همکاری است. (اولین بار این اصطلاح در یک رشته توییت از سارا مِی مشاهده شد.) توسعهی یک داستانِکاربری (user story) یا یک ویژگی (feature)، معمولاً فقط به کدنویسی محدود نمیشود و شاملِ وظایفِ دیگری هم هست. بهعنوانِ یک جفت، شما مسئولِ همهی این وظایف هستید.
برای ورود به این طرزِ فکر، در ادامه، چند نمونه از فعالیتهای غیرکدنویسی که از کارِ دوتایی نفع میبرد، آورده شده است.
برنامهریزی - هدف ما چیست؟
وقتی کار روی چیزی را شروع میکنید، مستقیماً به سراغِ کدنویسی نروید. این مرحلهی اولیه از چرخهی عمرِ یک ویژگی، فرصتِ بسیار خوبی برای جلوگیری از اتلافِ وقت است. با چهار چِشم، روی مشکل، شناساییِ سوءتفاهمها یا پیشنیازهای فراموششده در این مرحله تمرکز کنید، این کار زمانِ زیادی را در آینده صرفهجویی میکند.
- درکِ مشکل: داستان (story) را با دقت بخوانید و برداشتِ خود را از آن برای یکدیگر توضیح دهید. سوالاتِ باز یا سوءتفاهمهای احتمالی را با مالکِ محصول (Product Owner) روشن کنید. اگر تیمِ شما “تعریفِ آماده بودن” (Definition of Ready) دارد، دوباره آن را مرور کنید و مطمئن شوید که همه چیز برای شروع آماده است.
- ارائه راهحل: ایدههایی برای حلِ مشکل ارائه دهید. این کار را میتوانید باهم انجام دهید یا جداگانه فکر کنید و سپس ایدههای خود را برای یکدیگر مطرح کنید. این بستگی به میزانِ تعریفشده بودنِ راهحل و همچنین سبکهای فردی شما دارد. برخی از افراد دوست دارند ابتدا بهتنهایی فکر کنند، در حالی که برخی دیگر ترجیح میدهند در حینِ صحبت کردن ایدهپردازی کنند. اگر یکی از شما با کسبوکار یا تکنولوژی کمتر آشناست، زمانی را برای توضیحِ زمینههای لازم اختصاص دهید.
- برنامهریزی برای اجرا: برای راهحلی که انتخاب کردهاید، چه مراحلی باید طی شود؟ آیا ترتیبِ خاصی از وظایف وجود دارد که باید رعایت شود؟ چگونه این کار را تست خواهید کرد؟ بهتر است این مراحل را در یک سندِ مشترک یا روی برگه بنویسید. این کار به شما کمک میکند پیشرفتِ خود را دنبال کنید یا اگر نیاز باشد فردِ دیگری به کار اضافه شود، او را سریعتر وارد فرآیند کنید. نوشتنِ این مراحل همچنین به یادآوریِ کارهایی که باید انجام شوند کمک میکند؛ چراکه اغلب فراموش میکنیم چه مواردی را باید انجام دهیم.
تحقیق و بررسی
وقتی پیادهسازیِ یک ویژگی نیاز به استفاده از تکنولوژیِ جدیدی دارد که هر دوی شما با آن آشنا نیستید، ابتدا باید تحقیق و بررسی انجام دهید. این کار معمولاً در قالبهای مشخصی مانندِ “راننده-راهنما” یا “پینگپنگ” نمیگنجد. مثلاً جستجوی نتایج در یک صفحه نمایشِ مشترک معمولاً چندان مؤثر نیست.
برای انجامِ تحقیق و بررسی در حالتِ توسعهی دوتایی، میتوانید این مراحل را دنبال کنید:
- فهرستی از سوالاتی که باید پاسخ داده شوند تهیه کنید تا بتوانید یک راهحلِ مناسب ارائه دهید.
- از هم جدا شوید – یا سوالات را بین خود تقسیم کنید یا هر دو بهصورت جداگانه برای یافتنِ پاسخِ یکسان تلاش کنید. در اینترنت یا منابعِ داخلیِ سازمان به دنبالِ پاسخ بگردید یا مفهومی که برای هر دوی شما جدید است را مطالعه کنید.
- پس از یک بازهی زمانی مشخص که از قبل توافق کردهاید، دوباره کنارِهم بیایید و یافتههای خود را به اشتراک بگذارید و بحث کنید.
مستندنویسی
یکی دیگر از کارهایی که میتوانید فراتر از کدنویسی باهم انجام دهید، مستندنویسی است. با هم فکر کنید که آیا برای کاری که انجام دادهاید نیاز به مستنداتی هست یا نه. بسته به مورد و ترجیحاتِ فردی، میتوانید مستندات را باهم بنویسید یا یکی از شما مستندات را ایجاد کند و دیگری آن را مرور و اصلاح کند.
مستندسازی نمونهی خوبی از وظیفهای است که یک جفت میتواند در انجامِ آن یکدیگر را منظم و مسئول نگه دارد. این کار اغلب به انتهای کار موکول میشود و وقتی تنها چیزی که مانعِ از تکمیلِ ویژگی و رساندنِ آن به وضعیتِ “انجامشده“، مستندنویسی باشد، معمولاً از آن صرفنظر میکنیم یا بهصورتِ سطحی انجام میدهیم. اما کار در قالب جفت باعث میشود این کارهای ارزشمند اما گاهی خستهکننده را بهدرستی انجام دهیم، کاری که در آینده از آن قدردانی خواهیم کرد.
مدیریتِ زمان
علاوه بر سبکهای کلی برای همکاریِ دوتایی (Pairing)، ابزارها و تکنیکهای کوچکی وجود دارند که این فرآیند را آسانتر میکنند.
یکی از این ابزارها، تکنیکِ پومودورو (Pomodoro) است. این روشِ مدیریتِ زمان، کار را به بخشهای زمانی تقسیم میکند – معمولاً ۲۵ دقیقه – که با استراحتهای کوتاه از هم جدا میشوند. این تکنیک را میتوان برای تقریباً همهی روشهای همکاریِ دوتایی به کار برد و باعث میشود متمرکز بمانید. همکاریِ دوتایی میتواند فرایندی خستهکننده باشد، بنابراین یادآوری برای استراحت و تعویضِ منظمِ نقشها (مانند تعویض کسی که پشتِ کیبورد است) بسیار مفید است.
استفاده از تکنیک پومودورو در عمل
تصمیم بگیرید روی چه چیزی کار کنید
ابتدا مشخص کنید که هدفِ بعدی چیست و روی چه چیزی میخواهید کار کنید.تایمر را برای ۲۵ دقیقه تنظیم کنید
میتوانید از افزونههای مرورگر برای پومودورو استفاده کنید یا حتی از یک تایمرِ آشپزخانهای به شکلِ گوجهفرنگیِ واقعی کمک بگیرید!بدونِ وقفه کار کنید
در طولِ این ۲۵ دقیقه، بدونِ حواسپرتی روی کار خود تمرکز کنید.وقتی تایمر زنگ زد، کار را متوقف کنید
استراحتِ کوتاهی (۵ تا ۱۰ دقیقه) داشته باشید.پس از ۳ یا ۴ دوره پومودورو، استراحتِ طولانیتری کنید
یک استراحتِ طولانیتر (۱۵ تا ۳۰ دقیقه) داشته باشید.از استراحتهای کوتاه برای تجدیدِ انرژی استفاده کنید: آب یا قهوه بنوشید، به دستشویی بروید یا کمی هوای تازه بگیرید. سعی کنید از این زمان برای کارهای دیگر مانند نوشتنِ ایمیل استفاده نکنید. این زمان برای استراحتِ ذهن و بدن است، نه ادامه کار!
چرخشِ دوتاییها (Pair Rotations)
چرخشِ دوتاییها به این معناست که پَس از مدتی همکاری، یکی از اعضای تیم از داستان خارج میشود و فردِ جدیدی جایگزینِ او میشود، در حالی که فردِ باقیمانده بهعنوانِ “لنگر” (Anchor)، فردِ جدید را واردِ فرآیند میکند.
دلایلِ چرخش در دوتاییها
دلایلِ لجستیکی. گاهی اوقات چرخش به دلایلِ عَملی ضروری است. برای مثال، ممکن است یکی از اعضای دوتایی بیمار شود یا به مرخصی برود. یا یکی از شما از راهِ دور کار کند در حالی که کار به حضورِ فیزیکی نیاز دارد، مثل تنظیماتِ سختافزاری.
تغییرِ فضا و تنوع. گاهی دوتاییها برای مدتِ طولانی باهم کار کردهاند و علائمی از خستگی یا کلافگی (cabin fever) نشان میدهند. یا ممکن است پروژهای که روی آن کار میکنید بسیار خستهکننده و انرژیبر باشد. در این شرایط، چرخش باعث میشود یکی از افراد استراحت کند و نفرِ جدیدی با انرژی و دیدگاهِ تازه وارد شود.
جلوگیری از ایجادِ سیلوهای دانشی. مهمترین دلیل برای چرخش، جلوگیری از متمرکز شدنِ دانش در یک یا چند نفرِ خاص، و انجام بررسیهای بیشتر روی کد (code review) در طولِ فرآیند است. کارِ دوتایی خود به تنهایی در این موارد کمک میکند، اما چرخش میتواند تعدادِ چشمهایی که کد را بررسی میکنند نیز بیشتر کند.
تناوبِ مناسب برای چرخش
دربارهِ تناوبِ (frequency) چرخش نظراتِ متفاوتی وجود دارد. برخی معتقدند چرخش هر ۲-۳ روز یکبار ضروری است تا دانش به اندازهی کافی پخش شود و کیفیت افزایش یابد. با این حال، هر چرخش هزینههایی هم دارد؛ از جمله زمانِ لازم برای وارد کردنِ فردِ جدید به داستان و هزینهی تغییرِ زمینه (context) برای نفری که جدا شده است. این نکته را نیز توجه کنید که اگر در پروژه هیچ لنگری برای حفظِ تداوم وجود نداشته باشد، خطرِ از دست رفتنِ دانشِ ضمنی دربارهی مشکل و فضای راهحل افزایش مییابد و ممکن است باعثِ نیاز به انجامِ دوبارهکاری شود.
برای توسعهدهندگانِ کمتجربهتر، لنگر ماندن برای مدتِ طولانیتر مفیدتر است، چرا که زمانِ بیشتری برای غرق شدن در موضوع و تثبیتِ دانش خواهند داشت.
هنگامِ تصمیمگیری دربارهی چرخش، باید تعادلِ بین هزینهها و مزایا را در نظر گرفت. به عنوانِ مثال، اگر در تیم شما اشتراکِ دانش، با کیفیتِ بالایی وجود دارد (مانند جلسات show and tell، کدِ خوانا و مستنداتِ مناسب)، ممکن است اصرار بر چرخشهای مکرر فقط بهبودِ اندکی در مالکیتِ جمعیِ کد ایجاد کند، اما اصطکاک و سربارِ زیادی به همراه داشته باشد.
برنامهریزیِ روز
کار دوتایی نیاز به سطحی از هماهنگی و برنامهریزی در تقویم دارد. اگر زمانی را برای توجه و تنظیم برنامه اختصاص ندهید، در طول روز با مشکلاتی مواجه خواهید شد.
روز را با یک بررسی سریع تقویم شروع کنید. با همکار دوتایی خود توافق کنید که چند ساعت قرار است با هم کار کنید. همچنین ببینید آیا باید برنامه خود را برای جلسات یا کارهایی که خارج از وظایف دوتایی هستند تنظیم کنید یا خیر. اگر مشخص شد که یکی از شما برای مدتی مجبور است به تنهایی کار کند، مطمئن شوید که پیشنیازهای لازم برای ادامه کار بدون حضور او فراهم است. برای مثال، از کامپیوتر آن شخص برای کدنویسی استفاده نکنید.
گر در طول روز جلسات یا تعهدات دیگری دارید، اطمینان حاصل کنید که یادآوریهایی تنظیم کردهاید که به موقع متوجه آنها شوید، مخصوصاً وقتی با کامپیوتر همکار خود کار میکنید.
اگر تیم شما به طور پیشفرض به صورت دوتایی کار میکند، توافق بر سر “ساعات اصلی کدنویسی” برای همه اعضا میتواند برنامهریزی را بسیار آسانتر کند. این ساعات به عنوان چارچوبی برای زمانهای مشترک کار تیمی عمل کرده و به هماهنگی بهتر کمک میکند.
با داشتن برنامهریزی دقیق و انعطافپذیری در برابر تغییرات روزانه، کار دوتایی شما روانتر و مؤثرتر خواهد بود.