توسعه پروژههای نرمافزاری فوت و فن خاص خودش را دارد. تولید یک نرمافزار کار سادهای است. اما اگر بخواهید نرمافزاری را توسعه دهید که قرار است سالها مورد استفاده قرار گیرد، باید نکاتی را بدانید تا در هنگام پیادهسازی، و مهمتر از آن پشتیبانی نرمافزار با مشکل مواجه نشوید. اگرچه کد تمیز را برنامهنویسان مینویسند، اما اثرات آن غالبا بطور مستقیم در مدیریت پروژه ظاهر میشود و به همین دلیل است که مدیران نیز باید تا حدی از این مفهوم مطلع باشند. در غیر این صورت روند اجرای پروژه و زمانبندی آن از کنترل مدیران خارج شده و چهبسا به شکست پروژه و حتی نابودی یک شرکت نرمافزاری میانجامد. در این سلسله مقالات به بررسی کد تمیز، چیستی آن و چگونگی نوشتن این مدل از کد میپردازیم.
اهمیت نوشتن کد تمیز
نوشتن کد تمیز در پروژه نرمافزاری بسیار مهم است. کد تمیز موفقیت یا شکست یک پروژه را تعیین میکند.
اغلب در شروع یک پروژه نرمافزاری شما هیچ محدودیتی ندارید و به راحتی و با صرف زمان کمی میتوانید اشکالات کد را برطرف کنید و ویژگیهای جدید به آن اضافه نمایید. اما به مرور زمان و پیشرفت پروژه حجم کد زیاد شده و تعداد ماژولهای آن افزایش مییابند. این ماژولها با یکدیگر یکپارچه شده و کارایی نرمافزار را پدید میآورند. با زیاد شدن کد و تعداد ماژولها، برطرف کردن اشکالات و اضافه کردن ویژگیهای جدید به کد، امکان بروز ناسازگاری بین آنها را افزایش داده و باعث افزایش زمان و حجم کار لازم برای اضافهکردن یک ویژگی ساده به کد یا برطرف کردن یک مشکل ساده در آن میگردد. بدین ترتیب کارایی (Productivity) تیم برنامهنویسی شروع به کاهش میکند.
در طرف دیگر، مدیران سرعت شما در ابتدای پروژه دیدهاند و بر اساس آن زمانبندی دیگر بخشهای پروژه را انجام داده و به مشتریان قول دادهاند. برنامههای آنها مطابق با زمانبندی پیش نمیرود و آنها قولهایی که به مشتریان برای اضافه کردن ویژگیهای جدید و یا برطرف کردن باگهای موجود دادهاند را زیر پا میگذارند. دلیل کند شدن و کم شدن کارایی شما برای مدیران مشخص نیست. آنها فقط میدانند که سرعت تیم برنامهنویسی به طور غیر قابل پیشبینیای کاهش یافته است.
حال به عنوان یک مدیر که به جای سود کردن در حال ضرر دادن است، چه میکنید؟
- شاید فشار بر برنامهنویسان برای انجام دادن به موقع کارشان اولین راه حل شما باشد. کم کردن زمان برای یک Task مشخص، میتواند به برنامهنویسان فشار بیاورد تا سخت کار کنند.
– این راه حل صحیح نیست، چون مشکل اصلی برنامهنویسان نیستند، بلکه این کد برنامه است که سبب کندی برنامهنویسان شده است. پس این راه حل کارایی ندارد و جز تأخیر بیشتر در پروژه سودی نخواهد داشت. - اضافه کردن برنامهنویس به تیم راه حل دوم است. به هر حال اضافه کردن نیرو سرعت تیم را بالا میبرد.
– این راه حل نیز کاملا صحیح نیست. چون ابتدا برنامهنویس تازه کار است. او برای شروع به کار کد پروژه را میخواند و از دیگر برنامهنویسان کمک میخواهد. در نتیجه بقیه برنامهنویسان نیز زمانشان را برای آموزش به فرد جدید میگذارند و کارایی آنها نیز کاهش مییابد. در نهایت برنامهنویس جدید با خواندن کد پروژه یاد میگیرد که چطور کارها را انجام دهد. کد و افرادی که خود باعث مشکل شده اند حال الهام بخش برنامهنویس جدید شما هستند. گره کور، کورتر شده است! این مهم به قانون Brook معروف است: اضافه کردن نیروی انسانی به پروژه نرمافزاریای که تأخیر دارد باعث افزایش تأخیر آن میشود. - از نو شروع کنید. بازطراحی (Redesign) پروژه راه حلی است که اغلب توسط برنامهنویسان پیشنهاد میشود. با توجه به هزینه و زمان این راهکار، اغلب مدیران این راه حل را نمیپذیرند. اما به عنوان آخرین راه حل، مجبور میشوند که به این راه حل تن در دهند.
– برای Redesign بهترین برنامهنویسان موجود را انتخاب میکنید و کار بازطراحی را به آنان میسپارید. این برنامهنویسان همان کسانی هستند که فاجعه اول را پدید آوردهاند. بنابراین مشخص است که نتیجه چه خواهد شد. شما نمیتوانید یک مشکل را با تفکری که آن را به وجود آورده است، حل کنید. بازطراحی اصولا فرار به جلو برنامهنویسان است. با فرار از مشکل آن را حل نخواهید کرد. برای حل مشکل باید با آن مواجهه شد و واقعیات را دید. بازطراحی اغلب یک راه حل از پیش شکست خورده است. این ایده شاید حتی برای پروژههای کوچک کار کند، اما پروژههای بزرگ هیجگاه با Redesign موفق نمیشوند. چون زمان و هزینه لازم برای Redesign بسیار بالاست و ممکن است کل پروژه و حتی شرکت را از پا در آورد.
کد فاسد یا Rot Code چیست؟
چه اتقاقی میافتد که کد با گذر زمان ما را دست و پا گیر میکند؟ مگر نه این که ما از یک کد انعطافپذیر و معماری ساده و خوب در گذر زمان به چنین کدی رسیدهایم؟ اصلا خصوصیات یک کد فاسد چیست که به آن کد فاسد میگوییم؟
-
- صلبیت (Rigidity): مقاومت یک سیستم نرمافزاری نسبت به تغییر را صلبیت آن میگویند. یک سیستم صلب است زمانی که برای برطرف کردن یک باگ یا اضافه کردن یک ویژگی ساده نیاز به تغییرات بسیار در نقاط مختلف کد داشته باشد (تغییر در یک ماژول کار ماژول دیگری را در سیستم مختل مینماید). چنین سیستمی در مقابل تغییرات از خود مقاومت نشان میدهد و به آن سیستم صلب گفته میشود.
در هنگام کار روی اینگونه سیستمها زمانبندی برای انجام یک Task -به دلیل غیر قابل پیشبینی بودن تعداد ماژولهایی که باید تغییر کنند- با مشکل مواجه میشود. مثلا برای انجام کاری زمان تقریبی یک هفته از سوی برنامهنویسان در نظر گرفته میشود. اما چون حجم تغییرات مورد نیاز برای برنامهنویس قابل تخمین نیست، مسلما زمان در نظر گرفته شده برای کار زمان دقیقی نخواهد بود. انتشار تغییرات در ماژولهای متفاوت، باعث زیاد شدن زمان اعمال تغییر و تأخیر زمانی برنامهنویسان و در نتیجه تأخیر کل پروژه میگردد. در پایان یک هفته، پاسخ برنامهنویسان این جمله معروف است: “این Task از آنچه که فکر میکردیم پیچیدهتر است!” - شکنندگی (Fragility): یک سیستم شکننده است اگر با یک تغییر ساده از جهات گوناگون و البته غیر قابل پیشبینی بد عمل کند و دچار نقص فنی گردد. یک سیستم شکننده است اگر برای برطرف کردن یک باگ یا اضافه کردن یک ویژگی ساده باعث بد کار کردن یک یا چند قسمت دیگر سسیستم شود که هیچ ارتباطی با قسمتی که تغییر کرده است ندارند. در هنگام توسعه این طور سیستمها تصور مدیران و مشتریان این است که برنامهنویسان کنترل کد نرمافزار را از دست دادهاند.
- تفکیکناپذیری (Inseparability): مقاومت یک سیستم در برابر تفکیک اجزاء آن از یکدیگر را تفکیکناپذیری آن میگویند. در واقع، یک سیستم تفکیکناپذیر است اگر قسمتهای مختلف آن از هم مستقل نباشند و نتوان هر قسمت را به طور مستقل در سیستم دیگر به کار گرفت. اینگونه سیستمها غیر قابل پیشبینی هستند و اگر قسمتی از آنها را در پروژهای دیگر باز استفاده کنید، حجم تغییرات لازم در کد قابل پیشبینی است.
- شفافیت (Opacity): یک سیستم شفاف است اگر بتوان با خواندن کد به سادگی هدف برنامهنویس را دریافت. از سوی دیگر یک سیستم کدِر است اگر با خواندن کد آن نتوان فهمید سیستم چه کاری انجام میدهد یا چگونه کار میکند. کد کدر قابل خواندن نیست، تغییر آن سخت است و فهم آن ساده نیست.
- صلبیت (Rigidity): مقاومت یک سیستم نرمافزاری نسبت به تغییر را صلبیت آن میگویند. یک سیستم صلب است زمانی که برای برطرف کردن یک باگ یا اضافه کردن یک ویژگی ساده نیاز به تغییرات بسیار در نقاط مختلف کد داشته باشد (تغییر در یک ماژول کار ماژول دیگری را در سیستم مختل مینماید). چنین سیستمی در مقابل تغییرات از خود مقاومت نشان میدهد و به آن سیستم صلب گفته میشود.
اگر یک کد/سیستم صلب، شکننده، تفکیکناپذیر و یا کدر باشد، به آن کد/سیستم فاسد یا بد میگوییم. چنین کدهایی برنامهنویسان را با مشکل مواجه میکنند و سرعت آنها را کاهش میدهند.
چرا برنامهنویسان کد فاسد مینویسند؟
فرض کنید مجبور باشید مسیر ۳۰ دقیقهای خانه تا محل کارتان را در 1۵ دقیقه بروید، چه میکنید؟ بله، سرعت خود را افزایش میدهید. سرعت دو برابر میتواند شما را در زمان دلخواه به مقصد برساند. اما ریسکپذیری و امکان تصادف شما را نیز تا دو برابر افزایش میدهد. بنابراین یا هرگز به مقصد نمیرسید (!) یا در 15 دقیقه در مقصد خواهید بود. اما اگر همین مسیر را بخواهید در ۵ دقیقه طی نمایید نیاز به سرعتی معادل ۶ برابر سرعت عادی دارید. در چنین حالتی اگر حتی زنده بمانید احتمالا پلیس شما را دستگیر میکند!
زمانی که زیر فشار کاری باشید و مدیران از شما بخواهند کاری را به هر قیمت در یک زمان کم نامعقول انجام دهید، شما چه چارهای دارید؟ شاید کار را انجام دهید، اما مطمئنا آن را درست انجام نمیهید. چون مجبورید دقت را فدای سرعت کنید. در این حالت اگر برنامهنویس باشید، کد فاسد تولید میکنید. به جای آن که زمانتان را به فکر کردن بگذرانید تا کد را بهینه بنویسید، آن را صرف زدن کد بیکیفیت (فاسد) میکنید.
حقیقت آن است که مدیران احمق باعث خلق چنین کدهایی میشوند. آنها با اعمال فشار روی شما انتظار دارند کاری که به طور معقول در یک ماه انجام میشود را در یک روز انجام دهید! آنها به خیال خود اینگونه سرعت را بالا میبرند؛ غافل از این که خلق چنین کدی در پروژه بعدها سرعت آنها را دهها برابر کند میکند.
شما به عنوان برنامهنویس کسی هستید که میدانید باید از نوشتن چنین کدی امتناع کنید. شما استخدام شدهاید چون میدانید. بنابراین هیچگاه تسلیم خواسته مدیران نشوید. عجله نکنید و کد را تا حد امکان بهینه کنید. بدانید اگر عجله کنید در نهایت زمان بیشتری هدر خواهید داد. پس سعی کنید کد تمیز بنویسید و به هیچ بهانهای از زیر بار کد تمیز در نروید. مثلا این بهانه که “بعدا که عجله نداشتم بر میگردم و کد را تمیز میکنم”. راستی آخرین باری که برگشتید و کدتان را تمیز کردید کی بود؟!!
تنها راهی که سرعت شما را افزایش میدهد، نوشتن کد تمیز است. پس خودتان را گول نزنید، چون کد فاسد حتی در کوتاه مدت سرعت شما را کاهش خواهد داد. بله، درست خواندید. این توهمی بیش نیست که کد فاسد سرعت را در کوتاه مدت افزایش میدهد.
کد تمیز یا Clean Code چیست؟
این سوال از برنامهنویسان خبره دنیا پرسیده شده است. پاسخهای آنها چنین است:
Bjarne Stroustrup: کدی است که مختصر و کارا (نیازمند کمترین سیکل CPU) باشد و با کمترین حافظه اجرایی اجرا شود. کد تمیز باید تنها یک کار انجام دهد.
Grady Booch: کدی است که ساده و صریح باشد و مانند نثر فصیح خوانده شود.
Michael Feathers: کدی است که برای نویسندهاش اهمیت دارد.
Ward Cunningham: کدی است که در هنگام خواندن کد هر روال (routine) از آن حس کنید کاملا همان کدی است که انتظارش را داشتید.
توصیه Boy Scout
جهان را بهتر از آنچه که قبل از شما بود ترک کنید. این توصیهای است که به Boy Scout معروف شده است. توصیهای که در مورد کدهای برنامهنویسی هم صادق است. سعی کنید هرگاه که کدی را میخوانید آن را به نحوی بهتر کنید. این امر باعث میشود که کد شما همواره ارتقاء یافته و تمیزتر شود. اینگونه میتوان با کد مهربان بود و به آن توجه کرد.
در مقالات بعدی به نحوه نوشتن کد تمیز میپردازیم. این که در هر بخش از کد چه نکاتی را باید رعایت کنیم و چه مسائلی را باید در ذهن داشته باشیم.