چگونه پیچیدگی کد را در یک شرکت نرمافزار مدیریت کنیم؟
برخی در مورد پیچیدگی کد معتقدند:
فقط خود یک برنامهنویس میتواند پیچیدگی کد را حل کند.
پذیرفتن این دیدگاه تغییرات ظریفی را به همراه دارد زیرا به این معنا است که حل پیچیدگی کد نیازمند توجه خود فرد به آن کد است. مطمئناً ابزار مناسبی برای آسان کردن این وظیفه وجود دارد اما نهایتاً برطرف کردن پیچیدگی کد با بهکارگیری هوشمندی انسانی، توجه به این موضوع و عملکرد مناسب برای حل آن ممکن میشود.
اما چرا این مسئله اهمیت دارد؟ حل پیچیدگی کد معمولاً نیازمند کارِ باجزئیات در سطح تهیهکنندگان کد است.
اگر یک مدیر فقط بگوید «کد را ساده کن» و سپس موضوع را پیگیری نکند، معمولاً کاری انجام نمیشود زیرا توجه کافی به آن نمیشود، و البته مدیران لزوماً در مورد هر قطعه از کد دانش موردنیاز را ندارند که بتوانند خودشان آن را تخصصیتر پیگیری کنند؛ ضمن اینکه بخشی از درک مسئله در طی فرایند حل آن حاصل میشود و مدیر آن کسی نیست که کد راهحل را مینویسد.
هرچه مدیر در شرکت در سطح بالاتری باشد، این موضوع بیشتر صادق است. وقتی مدیر ارشد فناوری (CTO)، معاون، یا مدیر مهندسی، دستوری عملی مانند «بهبود کیفیت کد» را میدهد اما این دستور عملی را اختصاصیتر نمی کند، بدون هیچ پیشرفت قابلتوجهای حرکتهای بسیاری در سازمان صورت میگیرد.
یک مدیر مهندسی نرمافزار همیشه وسوسه میشود که راهکارهای گسترده و جامع برای تمام مسائلی که در حوزههای وسیعی مطرح میشوند پیشنهاد دهد. اما رویکرد مناسب به پیچیدگی کد مستلزم تفکیک آن به پروژههای کوچکتر و عملکرد مفصل برنامهنویسان است. بنابراین تلاش برای حل تمام امور با یک راهکار جامع، کارساز نیست. درواقع مهندسین نرمافزار که احساس میکنند تلاش زیادی کردند اما نتوانستند کد ساده و قابل نگهداری تولید کنند به این تلاش آسیب میزنند. این الگوی مشترک در مدیریت نرم افزار موجب این اعتقاد غلط است که پیچیدگی کد گریزناپذیر بوده و نمیتوان کاری در مورد آن انجام داد.
بنابراین اگر مدیری هستید که کد پیچیدهای به شما تحویل داده شده و باید این مشکل را حل کنید، ترفند این کار، گرفتن دادهها از کارکنان مرتبط و کار بر کد است، تا جایی که مشکلات حل شود. توالی این کار تقریباً به این قرار است:
اول: از همه اعضای تیم بخواهید لیستی از وحشتهای خود در مورد کد بنویسند. علائم پیچیدگی کد از این قبیلند: واکنشهای عاطفی به کد، سردرگمی در مورد کد، این احساس که اگر به کد دست بزنند مثل یک شی شکستنی میشکند، مشکلات بهینهسازی و مانند آن. نیاز به پاسخ اعضای تیم به این پرسشها است: «آیا بخشی از سیستم وجود دارد که تصحیح و بهبود آن شما را عصبی کند؟» یا «بخشی از کد وجود دارد که از کار با آن وحشتزده باشید؟»
هرکدام از مهندسان نرمافزار لیست خود را مینویسند. پیشنهاد میشود از سیستمی برای جمع کردن این لیستها استفاده نکنید، فقط از افراد بخواهید که مشکلات خود را هرطور که برای آنها آسانتر است بنویسند. به آنها چند روز برای نوشتن این لیست فرصت بدهید؛ ممکن است با گذشت زمان موارد دیگری به ذهنشان خطور کند.
لازم نیست لیست فقط در مورد کد نوشتهی خودتان باشد، بلکه میتواند در مورد هر کدی باشد که توسعهدهنده باید بر آن کار کند یا از آن استفاده کند.
در این مرحله به دنبال علائم هستید نه علل. توسعهدهندگان میتوانند این لیست را کلیتر یا اختصاصیتر بنویسند.
دوم: با تیم جلسهای برگزار کنید و از همه بخواهید که لیست خود و رایانهای را برای دستیابی به کد همراه داشته باشند. تعداد ایدئال شرکتکنندگان این جلسه حدود هفت یا شش نفر است، شاید لازم باشد موضوعات را در تیمهای فرعی تقسیم کنید.
باید در این جلسه لیستها را بررسی کنید و برای هر یک از علائم ذکرشده، نام یک دایرکتوری، فایل، کلاس، روش، یا بلوک کد بخصوصی را تشخیص بدهید. حتی اگر کسی بگوید «برای کد، آزمون واحدی [1] وجود ندارد»، شما زمان دقیق خرابی را بپرسید و با پاسخ او فایلهایی را که باید برای آنها آزمون واحد نوشت تعیین کنید. در این جلسه باید توصیفی از مسئله را دریافت کنید نه پاسخهایی از این قبیل: «بازسازی کد دشوار است چون شاید بازنویسی من موجب خرابی ماژولهای دیگران شود.» در این صورت آزمون واحد کارساز است اما اول باید تا جایی که ممکن است محل مشکل را بیابید. درست است که تقریباً همه کد نیاز به آزمون واحد دارد اما اگر فرصت آن نیست، لازم است کار شدنیتری را انجام دهید.
ایده بازسازی کد بر این اساس است که فقط «کد» را میتوان تعمیر کرد، پس باید بدانید که چه بخشی از کد دشوار است. مسئله معمولاً گسترده است، اما میتوان مسائل را یکی پس از دیگری به مشکلات مشخص با قطعههای مشخص کد تفکیک کرد.
سوم: با استفاده از اطلاعات جلسه، هر اشکالی (باگی) که نمایانگر مشکل است (نه راهحل، فقط مشکل) برای هر دایرکتوری، فایل، کلاس و غیره که نامگذاری شده ثبت کنید.
اگر راهکاری در جلسه پیشنهاد شد، میتوانید در ثبت آن اشکال ذکر کنید؛ اما ابتدا باید به خود مشکل پرداخت.
چهارم: این مرحله، اولویتبندی است. اولین کار بررسی مشکلاتی است که بر بیشترین تعداد توسعهدهندگان تأثیر میگذارند و بیشترین تأثیر را دارند. این مشکلات بیشترین اولویت را دارند. معمولاً این اولویتبندی را کسی انجام میدهد که نسبت به سایر توسعهدهندگان تیم یا شرکت دید وسیعتری دارد. غالباً یک مدیر است.
بااینحال گاهی ترتیب حل مسائل بستگی مستقیم به شدت آنها ندارد. بهطور مثال شاید باید قبل از حل مسئلهی «ب» مسئلهی «الف» را حل کرد، یا حل مسئلهی «د» حل مسئلهی «ب» را آسانتر میکند. ازاینرو مسئله «الف» و «د» اول باید حل شوند، حتی اگر از مسائل وابسته به آنها شدیدتر نباشند. معمولاً مسائل زنجیرهایاند و ترفندی حل این مسائل، شروع با حل مسئلهای است که در «انتهای پشته است.». اولویتبندی اشتباه یکی از رایجترین و اصلیترین مشکلات طراحی نرمافزار است. ممکن است که اشتباه کوچکی به نظر برسد اما برای ثمربخشی تلاشها برای حل پیچیدگی کد ضرورت دارد. همیشه ماهیت اصلی طراحی درست نرمافزار، عمل درست در توالی درست است. اجبار توسعهدهندگان به حل مسائل خارج از توالی (بدون توجه به اینکه چه مشکلاتی در پس مشکلات دیگر هستند) موجب پیچیدگی کد میشود.
بخش اولویتبندی وظیفهای فنی است که معمولاً با هدایت فنی تیم به بهترین شکل انجام میشود. بعضیاوقات این هدایت فنی را یک مدیر و گاهی یک مهندس ارشد نرمافزار انجام میدهد.
گاهی تا قبل از پیشروی در بخشی از کد و یافتن اینکه اول تصحیح کدام بخش از کد آسانتر است، واقعاً نمیتوان فهمید کدام مسئله اول باید حل شود پس مرتبسازی اولویت دارد؛ اما اگر فقط درکار میتوانید ترتیب را مشخص کنید، فعلاً از این مرحله عبور کنید.
چه مرتبسازی را جلوتر و چه در حین عمل انجام بدهید، مهم این است که برنامهنویسان بدانند باید قبل از وظیفهشان چه وظیفه مهمی انجام شود. آنها باید اجازهی تغییر وظیفه فعلیشان را به وظیفهی دیگری که مانع آنهاست داشته باشند. البته محدودیت دارند (مثلاً نوشتن مجدد کل سیستم با یک زبان دیگر با هدف تعمیر یک فایل، ازلحاظ زمانی مقرونبهصرفه نیست) اما عموماً «تشخیص مسئله در انتهای پشته» از مهمترین وظایف توسعهدهنده در بازسازی کد است.
پنجم: در مرحلۀ پنجم هر اشکال را برای یکی از کارکنان تعیین کنید. این روند مدیریتی کاملاً استاندارد است؛ مطمئناً شامل ارتباطات و کار مفصلی است؛ اما بیشتر مدیران نرمافزار با نجوه ایفای این روند آشنا هستند.
در این مرحله وجود اشکال در بخشی از کد که تیم شما از آن نگهداری نمیکند، ممکن است مشکلساز باشد. در این صورت، در سازمان تیم مناسبی را که مسئولیت مسئله را به عهده میگیرند بهکار بگیرید. تعامل با مدیری که مشترکاً تیم دیگری را با او هدایت میکنید و در جایگاه بالاتری در زنجیره سازمانی است کمک میکند.
در بعضی سازمانها، اگر مشکل تیم خیلی پیچیده یا مفصل نباشد، معمولاً خود تیم میتواند تغییرات را ایجاد کند. برحسب تشخیص آنچه برای بهرهوری کلی بهتر است، عمل کنید.
ششم: حالکه همه اشکالات (باگها) ثبت شدهاند، زمان اعلام آنها است. در این مرحله عملکرد صحیح مدیر، نظارت بر توسعهدهندگان است که به تصحیح بعضی مشکلات کیفی کد که پیشازاین در حین کار مشخص شدند میپردازنند.
اگر برآورد تیم برای زمانبندی یک، چهار یا شش هفته است، بخشی از اصلاحات کد را در این زمانبندی بگنجانید. بهترین رویکرد این است که توسعهدهندگان ابتدا اصلاحاتی را انجام بدهند که کار تخصیصیافته به آنها را آسانتر کند، بعد از آن کار مختص به خود را انجام دهند. این رویکرد همیشه وقت کار خودشان را نمیگیرد؛ زیرا اگر درست انجام شود، توسعهدهندگان معمولاً میتوانند کار خود را در یکچهارم زمانی که اصلاحات پیشنیاز را انجام نمیدادند تمام کنند؛ که این اثبات میکند اصلاحات پیشنیاز بهرهوری را افزایش میدهد.
پیشروی طبیعی یک کار معین را برای کار بر کیفیت کد متوقف نکنید. بلکه دائماً بر کفایت کار برای کیفیت کد نظارت کنید تا کیفیت کلی کد همواره بهتر شود، نه اینکه با مرور زمان بدتر شود!
با این روشها درعمل بهبود کد را مستمر میکنید. البته این روند ظرایف بسیاری دارد که شاید عنوان هرکدام در یک کتاب بگنجد. بااینحال آنچه ذکر شد، همراه با درک صحیح و تجربه، برای پیشرفت چشمگیر کیفیت کد شما کافی است، چه بسا بر زندگی کاری شما در مدیریت یا مهندسی نرمافزار اثرگذار باشد.
[1] unit test