به دو دلیل شما در حال خواندن این کتاب هستید: یک: یک برنامهنویس هستید. دو: میخواهید برنامهنویس بهتری شوید. خوب است. ما به برنامهنویسهای بهتر نیاز داریم.
در کتاب پیشرو، میخواهیم راجع به خوب برنامه نوشتن صحبت کنیم. این کتاب، سرشار از کدهای مختلفی است که میخواهیم از جهات متفاوتی آنها را بررسی کنیم. این کدها را از بالا به پایین، و از درون به بیرون بررسی خواهیم کرد و در انتهای کار، شناخت بهتری از کد خواهیم داشت. علاوه بر این، قادر خواهیم بود کد خوب را از کد بد تشخیص دهیم. قادر به نوشتن یک کد خوب خواهیم بود و خواهیم دانست که چگونه یک کد بد را به یک کد خوب تبدیل کنیم.
ممکن است فردی معتقد باشد یک کتاب پیرامون کد بدرد سالها پیش میخورد و امروزه کد مسئله اصلی نیست. بلکه ما باید نگران مدلها و نیازمندیها باشیم. بعضی از افراد معتقدند که به پایان دوران کدنویسی نزدیک هستیم. به زودی تمام کدها به جای نوشته شدن توسط برنامهنویسها، توسط کامپیوترها تولید خواهند شد. کسب و کارهای مختلف، نرمافزارهای موردنیازشان را از طریق خصوصیات فنی تولید خواهند کرد و دیگر به برنامهنویسان نیازی نخواهد بود.
این حرف کاملا پوچ و خارج از منطق است. ما هرگز از کد فارغ نخواهیم شد، زیرا کد نمایانگر جزییات نیازمندیهاست. در بعضی سطوح، نمی توان جزییات را نادیده گرفت یا خلاصه کرد. آنها باید کاملا مشخص باشند و مشخص کردن نیازمندیها با چنان جزییاتی که یک ماشین بتواند آنها را اجرا کند برنامهنویسی است. این خصوصیات فنی نیز کد میباشد.
انتظار دارم که سطح انتزاع زبانها به گسترش خود ادامه دهد. همچنین انتظار دارم که تعداد زبانهای مختص دامنه(domain-specific- زبانهایی که برای محدوده خاصی از مسائل ساخته شده اند) رشد پیدا کند. این مسئله خوب است. اما باعث حذف کد نمیشود.
در واقع تمام مشخصات نوشته شده در این زبان های سطح بالا و مختص دامنه، "کد" خواهند بود! این کد همچنان نیاز دارد که سختگیرانه، دقیق، و بسیار رسمی و جزیی باشد تا یک ماشین بتواند آن را بفهمد و اجرا کند. گروهی که فکر میکنند که یک روز کد میتواند ناپدید شود شبیه به ریاضی دانانی هستند که امید دارند یک روز یک تعریف یا فرمول ریاضیای را کشف کنند که نیاز نداشته باشد که رسمی باشد. آنها امید دارند که یک روز راهی برای ساختن ماشینهایی کشف کنند که میتواند چیزی را که ما میخواهیم به جای چیزی که میگوییم انجام دهند. این ماشینها باید قادر باشند که آنقدر خوب ما را بفهمند که نیازمندیهای خاص و مبهم را به برنامههای کاملا قابل اجرا که با دقت، آن نیازمندیها را مرتفع میکنند، ترجمه کنند. این اتفاق هیچگاه نمیافتد. حتی انسانها با تمام بینش و خلاقیتشان قادر به ساخت موفق سیستمها از احساسات مبهم مشتریان نیستند.
در واقع اگر نظم نیازمندیهای مشخصات چیزی به ما آموخته باشد، آن این است که نیازمندیهای دقیق توصیف شده به اندازه کد رسمی هستند و میتوانند به عنوان تستهای قابل اجرایی از کد عمل کنند! بهخاطر داشته باشید که کد زبانی است که در نهایت با آن، نیازمندیها را بیان میکنیم. ممکن است ما زبانهایی بسازیم که به نیازمندیها نزدیکتر باشند. ممکن است ما ابزارهایی بسازیم که به ما در براورده کردن و سرهمبندی این نیازمندیها با ساختارهای رسمی کمک کنند. اما هرگز دقت لازم را حذف نمیکنیم. پس کد وجود دارد.
اخیرا یک پیشگفتار از کتاب Implementation Patterns نوشته Kent Beck خواندهام. او میگوید :"... این کتاب بر مبنای یک فرضیه ضعیف بنا شده است: این که کد خوب مهم است ..." یک فرضیه ضعیف؟ من مخالفم! من فکر میکنم آن فرضیه یکی از بیشمار فرضیههای گسترش یافته، مورد حمایت، و پربار در حرفه ماست(و فکر میکنم Kent این را میداند.) ما میدانیم که کد خوب مهم است زیرا ما زمان زیادی ناچار بودیم با نبود آن کنار بیاییم.
من یک شرکت را میشناسم که در اواخر دهه 80 یک برنامه killer نوشته است. این برنامه خیلی معروف بود و تعداد زیادی از افراد حرفه ای آن را خریده و استفاده کردند. اما پس از آن، چرخه انتشار شروع به کش آمدن کرد. از یک انتشار تا انتشار بعدی باگها تعمیر نشدند. زمان بارگذاری افزایش یافت و crash افزایش یافت. من به خاطر دارم که یک روز من آن محصول را با ناامیدی پاک کردم و دیگر هیچگاه از آن استفاده نکردم. مدت کمی پس از آن، آن شرکت از صحنه تجارت خارج شد. دو دهه بعد من یکی از اولین کارکنان آن شرکت را دیدم و از او پرسیدم که چه اتفاقی افتاد. آن پاسخ، ترسهای من را تایید کرد. آنها در عرضه محصول به بازار عجله کرده بودند و حجم عظیمی از کد را درست کرده بودند. هرچه آنها ویژگیهای بیشتر و بیشتری اضافه کردند، کد بدتر و بدتر شد تا زمانی که دیگر آنها نتوانستند آن را مدیریت کنند.
این کد بد بود که آن شرکت را نابود کرد. آیا تا کنون توسط یک کد بد به مشکل خورده اید؟ اگر شما یک برنامهنویس با هر سطح از تجربه باشید آنگاه شما در مواقع زیادی این مانع را احساس کردید.حتی یک نام برای آن داریم. ما آن را به سختی راه رفتن(wading) صدا میکنیم.
ما در طول یک کد بد به سختی راه میرویم. ما در باتلاقی از خاربنهای در هم تنیده و تلههای مخفی تقلا میکنیم. ما برای یافتن مسیر، به امید چند اشاره، چند سر نخ از اینکه چه اتفاقی در شرف وقوع است تقلا میکنیم اما تمام چیزی که میبینیم کدهای بی معنی بیشتر و بیشتر است. قطعا شما با کدهای بد به مشکل برخورده اید. خب چرا آنها را نوشتید؟ میخواستید سریع پیش بروید؟ عجله داشتید؟احتمالا بله. احتمالا شما احساس کردید که زمان کافی برای انجام یک کار خوب ندارید؛ رئیس شما از شما عصبانی میشود اگر برای تمیز کردن کدتان زمان هدر دهید. احتمالا شما از کار کردن بر روی این برنامه خسته شده بودید و میخواستید تمام شود. یا شاید شما به کارهای ناتمام بقیه کارمندانی که به آنها قول داده بودید که کار را انجام میدهید نگاه کردید و متوجه شدید که نیاز دارید تا ماژولها را به یکدیگر بچسبانید تا بتوانید کارها را به مرحله بعد ببرید. همه ما این کارها را انجام دادیم. همه ما به ریخت و پاشی که درست کرده بودیم نگاه کردیم و سپس انجام آن را به روز دیگر موکول کردیم. همه ما آسودگی ناشی از کار کردن برنامه نامرتب خودمان را حس کردیم و تصمیم گرفتیم که انجام کار شلخته بهتر از هیچ کاری است.همه ما گفتیم بعدا که برمیگردیم، آن را تمیز میکنیم. قطعا در آن روزها ما قانون LeBlanc را نمیشناختیم : بعدا یعنی هیچوقت.
اگر بیش از دو یا سه سال است که برنامهنویس بوده اید، احتمالاً با کد کثیف شخص دیگری معطل مانده اید. میزان معطل بودن می تواند قابل توجه باشد. طی یک بازه زمانی یک یا دو ساله، تیمهایی که در ابتدای یک پروژه بسیار سریع در حال حرکت بودند، خود را در حال حرکت با سرعت حلزونی میبینند. هر تغییری که در کد ایجاد کنند، دو یا سه قسمت دیگر کد را خراب می کند. تغییر ندادن مهم است. هرگونه افزودن یا تغییر در سیستم مستلزم این است که گره خوردگیها، پیچ و تابها و مشکلات "درک شوند" تا بتوانید تعداد بیشتری گره و پیچ و تاب اضافه کنید. با گذشت زمان شلختگی بسیار بزرگ و عمیق و بسیار بلند میشود، به گونه ای که نمی توان آنها را تمیز کرد. اصلاً راهی نیست. با ساخته شدن شلختگی، بهرهوری تیم همچنان رو به کاهش میرود، و در نهایت به صفر نزدیک میشود. با کاهش بهره وری، مدیریت تنها کاری که میتواند را انجام میدهد؛ آنها به امید افزایش بهره وری کارکنان بیشتری را به این پروژه اضافه میکنند. اما آن کارکنان جدید سیستم را نمیشناسند. آنها تفاوت بین تغییری را که منطبق با هدف طراحی انجام میشود و تغییری که هدف طراحی راناکارآمد میکند، نمی دانند. علاوه بر این، آنها و هر کس دیگری که در تیم حضور دارند، تحت فشارهای هولناکی برای افزایش بهره وری قرار دارند. بنابراین همه آنها بیشتر و بیشتر باعث شلختگی میشوند و باعث میشوند که بازدهی هر چه بیشتر به سمت صفر برسد. (شکل 1-1 را ببینید.)
سرانجام تیم شورش میکند. آنها به مدیریت اطلاع میدهند که نمیتوانند بر مبنای این کد نفرت انگیز محصولی را توسعه دهند. آنها خواستار طراحی مجدد هستند. مدیریت نمیخواهد که منابع را صرف طراحی مجدد پروژه کند، اما آنها نمیتوانند انکار کنند که بهره وری وحشتناک است. سرانجام آنها به خواستههای توسعه دهندگان تن میدهند و اجازه انجام طراحی مجدد بزرگ در اسمان را میدهند.
یک تیم جدید قوی انتخاب شده است. همه دوست دارند در این تیم حضور داشته باشند زیرا این یک پروژه Greenfield است. آنها دوباره شروع به کار میکنند و چیزی زیبا را ایجاد میکنند. اما فقط بهترینها و درخشان ترینها برای تیم قوی انتخاب میشوند. همه افراد دیگر باید به حفظ سیستم فعلی ادامه دهند. اکنون دو تیم در رقابت هستند. تیم قوی باید سیستم جدیدی بسازد که هر آنچه را که سیستم قدیمی انجام میدهد انجام دهد. نه تنها این، آنها باید با تغییراتی که به طور مداوم در سیستم قدیمی انجام میشود، به روز باشند. مدیریت تا زمانی که سیستم جدید نتواند کارهایی را که سیستم قدیمی انجام میدهد، انجام دهد، سیستم جدید را جایگزین سیستم قدیمی نخواهد کرد. این رقابت میتواند برای مدت زمان طولانی ادامه یابد. من دیده ام که 10 سال طول کشید. و زمانی که این کار انجام شد، اعضای اصلی تیم قوی مدتها بود که از تیم رفته بودند، و اعضای فعلی خواستار طراحی مجدد سیستم جدید هستند زیرا این سیستم بسیار شلخته است.
اگر حتی یک بخش کوچک از داستانی را که تعریف کردم تجربه کرده اید، پس میدانید که صرف وقت برای تمیز کردن کد خود صرفاً مقرون به صرفه نیست. این یک کار حرفه ای برای بقا است.
آیا تا به حال آنقدر با شلختگیها کلنجار رفته اید که کاری را که در طی چند ساعت میتوانستید انجام دهید، هفتهها طول بکشد؟ آیا دیده اید که چیزی که میتوانست با تغییر یک خط ایجاد شود، در عوض در تغییر در صدها ماژول مختلف انجام شد؟ این علائم بسیار شایع است. چرا این اتفاق برای کد میافتد؟ چرا کد خوب خیلی سریع به کد بد تبدیل میشود؟ توضیحات زیادی برای آن داریم. ما شاکی هستیم که نیازمندیها به گونه ای تغییر یافته که طرح اصلی را خنثی میکند. ما ناراحتیم که برنامهها برای انجام درست کارها بسیار فشرده بود. ما در مورد مدیران احمق و مشتریان عجول و انواع بازاریابیهای بی فایده و ضد عفونی کنندههای تلفنی صحبت میکنیم. اما Dilbert عزیز، مشکل در سرنوشت ما نیست، بلکه در خودمان است. ما غیر حرفه ای هستیم.
ممکن است پذیرش این حقیقت تلخ، مشکل باشد. چطور ممکن است این شلختگی تقصیر ما باشد؟در مورد نیازمندیها چطور؟ در مورد برنامه چطور؟ در مورد مدیران احمق و انواع بی فایده بازاریابی چطور؟ آیا آنها مقصر نیستند؟ خیر. مدیران و بازاریابان برای دریافت اطلاعاتی که برای وعدهها و تعهدات لازم دارند، به ما نگاه میکنند. و حتی وقتی آنها به ما نگاه نمیکنند، ما نباید از گفتن آنچه که فکر میکنیم شرمنده باشیم. کاربران به ما نگاه میکنند تا تصدیق کنند که ما چگونه سیستم را با نیازمندیها پر میکنیم. مدیران پروژه از ما انتظار دارند که به پیش برد برنامه کمک کنیم. ما عمیقا درگیر برنامه ریزی پروژه هستیم و مسئولیت هرگونه خرابی را به عهده میگیریم. به خصوص اگر این شکستها مربوط به کد بد باشند! "اما صبر کنید!" شما بگویید. "اگر آنچه را که مدیر من میگوید، انجام ندهم، اخراج میشوم." احتمالا نه. اکثر مدیران حقیقت را میخواهند، حتی اگر چنین رفتار نکنند. اکثر مدیران کدهای خوبی میخواهند، حتی وقتی در مورد برنامه وسواس دارند. آنها ممکن است با شور و شوق از برنامهها و نیازمندیها دفاع کنند؛ اما این کار آنهاست این وظیفه شماست که با اشتیاق برابر، از کد دفاع کنید. برای اینکه این مسئله برای شما جا بیفتد، چه میشود اگر شما یک پزشک باشید و یک بیمار داشته باشید که به این دلیل که شستن دستها قبل از عمل جراحی زمان زیادی میبرد، خواستار جلوگیری از این کار احمقانه باشد؟(هنگامی که برای اولین بار در سال 1847 توسط Ignaz Semmelweis به پزشکان توصیه شد دستهای خود را بشویند، این توصیه به دلیل اینکه سر پزشکان خیلی شلوغ بود و وقت نداشتند میان ویزیت بیماران دستهای خود را بشویند رد شد.) به وضوح بیمار رئیس است. و با این وجود پزشک کاملاً باید از انجام عمل خودداری کند. چرا؟ زیرا پزشک بیشتر از بیمار از خطرات بیماری و عفونت اطلاع دارد. این که پزشک مطابق با خواست بیمار عمل کند (حتی اگر مجرمانه نباشد) غیرحرفه ای است. به همین ترتیب غیر حرفه ای است که برنامهنویسان به خواسته مدیرانی که ریسک ایجاد شلختگیها را نمیفهمند تن در دهند.
برنامهنویسان با مجموعه ای از مسائل پایه ای روبرو هستند. همه توسعه دهندگان با بیش از چند سال تجربه میدانند که شلختگیهای قبلی آنها را کند میکند. و با این وجود همه توسعه دهندگان فشار ناشی از ایجاد شلختگی را احساس میکنند زیرا باید به ضرب الاجل برسند. به طور خلاصه، آنها وقت لازم را برای حرکت سریع ندارند! حرفه ایها میدانند که قسمت دوم این مسئله اشتباه است. شما با ایجاد شلختگی به ضرب الاجل نمیرسید. در واقع، شلختگی فورا شما را کند میکند و شما را مجبور میکند که ضرب الاجل را از دست بدهید. تنها راه برای رسیدن به ضرب الاجل- تنها راه سریع پیشبرد کار- این است که همیشه کد را تا حد ممکن تمیز نگه دارید.
بیایید بگوییم شما معتقد هستید که کد کثیف مانع قابل توجهی است. بیایید بگوییم که شما میپذیرید که تنها راه پیشبرد سریع، تمیز نگه داشتن کدهایتان است. سپس باید از خود بپرسید: "چگونه میتوانم کد تمیز بنویسم؟" اگر نمی دانید تمیز بودن کد چیست، تلاشتان برای نوشتن کد تمیز خوب نیست! خبر بد این است که نوشتن کد تمیز بسیار شبیه به نقاشی کشیدن است. بیشتر ما میدانیم چه زمانی یک تصویر خوب یا بد نقاشی شده است. اما قدرت تشخیص هنر خوب از بد به معنای این نیست که بلدیم چگونه نقاشی کنیم. بنابراین قدرت تشخیص کد تمیز از کد کثیف به این معنی نیست که میدانیم چگونه می توان کد تمیز نوشت! نوشتن کد تمیز مستلزم استفاده منظم از تکنیکهای ظریف بی شماری است که این تکنیکها از طریق به کارگیری حس"پاکیزگی" بکار برده میشود. این "حس کردن کد" مهم است. برخی از ما با آن متولد میشویم. برخی از ما باید برای به دست آوردن آن بجنگیم. نه تنها این امکان را به ما میدهد که ببینیم آیا کد خوب است یا بد، بلکه برای تبدیل کد بد به کد تمیز، استراتژی استفاده از قوانین مان را به ما نشان میدهد. به طور خلاصه، یک برنامهنویس که کد تمیز مینویسد، هنرمندی است که میتواند یک صفحه خالی بگیرد و از طریق یک سری دگرگونیها آن را به یک سیستم با کدگذاری زیبا تغییر دهد.
احتمالاً به اندازه برنامهنویسها تعریف وجود دارد. بنابراین از برخی از برنامهنویسان بسیار شناخته شده و با تجربه پرسیدم که چه فکر میکنند. Bjarne Stroustrup مخترع زبان C++ و نویسنده The C++ Programming Language: من دوست دارم کد من زیبا و کارآمد باشد. منطق باید سر راست باشد تا پنهان کردن باگها دشوار باشد، وابستگیهای حداقلی برای سهولت در نگهداری، کنترل کامل خطا مطابق با یک استراتژی تکه به تکه و عملکرد نزدیک به بهینه، بگونه ای که مردم را وسوسه نکند تا کد را با بهینهسازی های غیر اصولی شلخته کنند. کد تمیز یک کار را به خوبی انجام میدهد. Bjarne از کلمه “ظریف” استفاده میکند. این کلمه کامل است! دیکشنری موجود در MacBook من این تعریف را برای این کلمه ارائه میدهد : از نظر ظاهری و رفتاری دلپذیر و برازنده و شیک است. کاملاً مبتکرانه و ساده. به کلمه "دلپذیر" دقت کنید. ظاهرا Bjarne فکر میکند که خواندن کد تمیز لذت بخش است. خواندن آن باید لبخند را به لبان شما بیاورد، هماگونه که یک جعبه موسیقی خوش ساخت و یا یک ماشین با طراحی زیبا باعث میشود لبخند بزنید Bjarne همچنین دو بار از واژه بازده استفاده می کند. شاید وقتی این کلمه از دهان مخترع C ++ خارج میشود، غافلگیر کننده نباشد. اما فکر میکنم چیزی فراتر از تمایل صرف برای سرعت وجود دارد. چرخههای تلف شده لذت بخش نیستند و ناخوشایند هستند و اکنون به کلماتی که Bjarne برای توصیف پیامد آن ناهنجاری استفاده میکند توجه داشته باشید. او از کلمه "وسوسه" استفاده میکند. در اینجا یک حقیقت عمیق وجود دارد. کد بد شلختگی را وسوسه میکند تا رشد کند! وقتی دیگران کد بد را تغییر میدهند، متمایل به بدتر کردن آن هستند. Dave Thomas عملگرا و Andy Hunt این نکته را با یک روش متفاوت میگویند. آنها از استعاره پنجرههای شکسته استفاده کرده اند. وقتی ساختمانی پنجرههای شکسته دارد اینظور به نظر میرسد که کسی به آن اهمیتی نمیدهد. بنابراین دیگران هم به آن ساختمان اهمیتی نمیدهند. آنها اجازه میدهند تا پنجرههای بیشتری شکسته شود. حتی خودشان هم شروع به شکستن پنجرهها میکنند. آنها با گرافیتی نما را خراب میکنند و اجازه میدهند در آن جا زباله جمع شود.
یک پنجره شکسته روند زوال را شروع میکند. Bjarne همچنین خاطرنشان میکند که رسیدگی به خطا باید کامل باشد. این مربوط به قانون توجه به جزییات میشود. کنترل خطای مختصر فقط یکی از راههایی است که برنامهنویسان با استفاده از آن به تفصیل جزئیات میپردازند. نشت حافظه (Memory leaks) یکی دیگر از راهها و شرایط مسابقه(race condition) راه دیگر است. راه دیگر نامگذاری متناقض(Inconsistent naming) است. نتیجه اصلی این است که کد تمیز توجه زیادی به جزئیات دارد. Bjarne با این ادعا که کد تمیز یک کار را به خوبی انجام میدهد، بحث را میبندد. تصادفی نیست که بسیاری از اصول طراحی نرمافزار وجود دارند که میتوانند دلیل اصلی این توصیه ساده باشند.
نویسندگان یکی پس از دیگری سعی در برقراری ارتباط با این اندیشه داشتند. کد بد بیش از حد خرابکاری میکند، تمایلات را زشت کرده و اهداف را مبهم میکند. کد تمیز متمرکز است. هر تابع، هر کلاس، هر ماژول یک نگرش تک ذهنیتی را که کاملاً دست نخورده و آلوده نشده باقی مانده است با جزئیات پیرامون خود در معرض نمایش قرار میدهد
گردی بوچ Grady Booch، نویسنده “Object Oriented analysis and Design with Applications” :کد تمیز ساده و سر راست است. کد تمیز مثل یک نثر خوب نوشته شده است. کد تمیز هرگز هدف طراح را مبهم نمیکند بلکه پر از انتزاعات واضح و خطوط کنترل سر راست است. Grady برخی از نکاتی را که Bjarne بیان میکند، عنوان میکند، اما او یک جنبه خوانایی را در نظر میگیرد. من خصوصاً این نظر او را که كد تمیز باید مانند نثر خوب نوشته شده باشد دوست دارم. دوباره به کتاب خوبی که مطالعه کرده اید فکر کنید. به یاد آورید که چگونه کلمات ناپدید شدند تا تصاویر جایگزین شوند! مثل تماشای فیلم. اینطور نیست؟ بهتر! شخصیتها را دیدید، صداها را شنیدید، ترحم و طنز را تجربه کردید. خواندن کد تمیز هرگز شبیه به خواندن کتاب ارباب حلقهها نخواهد بود. با این وجود استعاره ادبی بد نیست. مانند یک رمان خوب، کد تمیز باید به وضوح تنشهای موجود در مشکل را حل کند. باید آن تنشها را به اوج خود برساند و سپس به خواننده بگوید که: "آها! اینه!" زیرا مشکلات و تنشها در ظهور یک راه حل واضح برطرف میشود.به نظر من استفاده grady از عبارت "انتزاع خشک(crisp abstraction)" به عنوان یک کلمه ضد و نقیض جذاب است! در نهایت، کلمه "خشک" تقریباً مترادف "واقع" است. فرهنگ لغت مک بوک من تعریف زیر از "خشک" را دارد: قاطعانه و سرنوشت ساز، بدون تردید و جزئیات غیر ضروری. علیرغم این کنار هم گذاشتن معانی، کلمات دارای پیام قدرتمندی هستند. کد ما باید برخلاف حدس و گمانها و واقعی باشد. کد باید فقط شامل چیزهای مهم و ضروری باشد. خوانندگان ما باید قاطعیت ما را درک کنند.
آقای Dave Thomas، موسس OTI، پدرخوانده استراتژی Eclipse : کد تمیز میتواند بجز نویسنده اصلی آن، توسط یک توسعهدهنده دیگر نیز خوانده شود و بهبود یابد. این کد Unit test و Acceptance test دارد. این کد اسامی معنی دار دارد. کد تمیز به جای اینکه راههای زیادی برای انجام یک کار ارائه کند، یک راه برای انجام یک کار دارد. کد تمیز حداقل وابستگیها، که به طور واضح تعریف شده اند، و یک API واضح و حداقلی را ارائه میدهد. کد باید دانا باشد زیرا بسته به زبان، تمام اطلاعات لازم را نمی توان به طور مشخص و به تنهایی با کد بیان کرد. Dave بزرگ، تمایل Grady برای خوانایی را با پیچیدگی مهمی به اشتراک میگذارد. Dave ادعا میکند که کد تمیز باعث میشود بهبود آن برای سایر افراد آسان باشد. این ممکن است واضح به نظر برسد، اما نمیتواند بیش از حد مورد تأکید قرار بگیرد. از این گذشته، میان کدی که خواندن آن آسان است و کدی که تغییر آن آسان است تفاوت وجود دارد. Dave تمیز بودن کد را با تستها پیوند میزند! ده سال پیش این امر باعث تعجب بسیار میشد. اما قوانین توسعه مبتنی بر تست(Test Driven Development) تأثیر عمیقی بر صنعت ما گذاشته و به یکی از اساسیترین قوانین ما تبدیل شده است. حق با Dave است. کد، بدون تست، تمیز نیست. مهم نیست که چقدر زیبا باشد، هر چقدر هم که قابل خواندن و در دسترس باشد، اگر آزمایش نشده باشد، کثیف است. Dave دو بار از کلمه حداقل استفاده میکند. ظاهراً منظور او در این تعریف کدهای کوچک است. در واقع، از زمان پیدایش ادبیات نرمافزار تا کنون، این یک ترجمه رایج بوده است. کوچکتر بهتر است. Dave همچنین میگوید که کد باید دانا(Liteate) باشد. این یک اشاره ریز به ادبیات برنامهنویسی Knuth دارد. نتیجه کلی این است که کد باید به شکلی تهیه شود که برای انسانها خوانا باشد
میشل فیدرز Micheal Feathers، نویسنده Working Effectively with Legacy Code :من میتوانم تمام خصوصیاتی را که در کد تمیز به آن توجه میکنم ذکر کنم، اما کیفیت فرا معماری وجود دارد که بر تمام آنان ارجح است. همیشه به نظر میرسد که کد تمیز توسط کسی نوشته شده است که به آن اهمیت داده است. هیچ چیز واضحی وجود ندارد که بتوانید انجام دهید تا کد بهتر شود. به همه این موارد توسط نویسنده کد فکر شده است و اگر سعی دارید پیشرفتها را تصور کنید، به جایی که هستید برمیگردید، جایی که از کد شخصی که برای شما باقی گذاشته تشکر میکنید - کدی که توسط کسی که عمیقاً به این مهارت اهمیت میدهد به جا گذاشته شده است. یک کلمه: اهمیت دادن. این کلمه واقعاً موضوع این کتاب است. شاید یک عنوان مناسب این باشد که چگونه به کد اهمیت دهیم. Micheal به مهمترین نکته اشاره کرد. کد تمیز کدی است که از آن مراقبت شده است. شخصی وقت خود را برای ساده و منظم نگه داشتن آن صرف کرده است. آنها توجه کافی به جزئیات داشته اند. آنها مراقبت کرده اند.
رون جفری.Ron Jeffries، نویسنده Extreme Programming Installed و Extreme Programming Adventures in C# : رون حرفه برنامهنویسی خود را در Fortran در فرماندهی هوایی استراتژیک آغاز کرد و تقریباً به هر زبان و تقریباً بر روی هر دستگاهی، کدی را نوشت. این امر باعث شد که در مورد صحبت کردنش بسیار مراقب باشد: در سالهای اخیر من قوانین کد ساده Beck را شروع و تقریباً به پایان رساندم. به ترتیب اولویت، کد ساده:
• تمام تستها را اجرا میکند؛
• بدون (کد اضافه)Duplicate است.
• تمام ایدههای طراحی موجود در سیستم را بیان میکند.
• تعداد موجودیتهایی چون کلاسها، متدها، توابع و موارد مشابه را به حداقل میرساند.
از این میان، بیشتر روی Duplication تمرکز میکنم. وقتی همین کار بارها و بارها انجام شد، این نشانگر این است که ایده ای در ذهن ما وجود دارد که به خوبی در کد نمایش داده نشده است. سعی میکنم بفهمم که چیست. سپس سعی میکنم این ایده را با وضوح بیشتری بیان کنم. برای من، بیانگر بودن شامل اسامی معنادار است، و من احتمالاً چندین بار اسامی چیزها را قبل از تثبیت آنها، تغییر میدهم. با ابزار مدرن کدنویسی مانند Eclipse، تغییر نام کاملا بدون هزینه است، بنابراین تغییر دادن برای من مشکل ساز نخواهد بود. با این وجود بیان کد فراتر از نامها است. من همچنین به این موضوع نگاه میکنم که آیا یک شی یا متد بیش از یک کار را انجام میدهد یا نه. اگر یک شیء باشد، احتمالاً باید به دو یا چند شیء تقسیم شود. اگر یک متد باشد، من همیشه از refactoring Extract Method روی آن استفاده میکنم، نتیجه اجرای این روش بر روی یک متد این است که چیزی که متد انجام میدهد را واضح تر بیان میکند، و برخی از زیرمتدها چگونگی انجام این کار را بیان میکنند. Duplication و صراحت، برای رسیدن به چیزی که من آن را کد تمیز تلقی کنم، راه بسیار طولانی ای را طی میکنند و بهبود کد کثیف فقط با توجه به این دو مورد میتواند تفاوت بزرگی ایجاد کند. با این حال، یک چیز دیگر وجود دارد که من از انجام آن آگاه هستم، که توضیح آن کمی سختتر است. بعد از سالها انجام این کار، به نظر من همه برنامهها با عناصر بسیار مشابهی ساخته شده اند. یک مثال "یافتن چیزها در یک مجموعه" است. چه بانک اطلاعاتی از سوابق کارمندان، یا نقشه درهم ساز(Hash map)کلیدها و مقادیر، و یا آرایه ای از بعضی از اقلام داشته باشیم، ما اغلب خودمان را خواهان مورد خاصی از آن مجموعه میبینیم. در پی آگاهی از وقوع این اتفاق، من اغلب پیادهسازی خاصی را در یک متد یا کلاس انتزاعی تر میپیچم. این به من چند مزیت جالب میدهد. من اکنون میتوانم آن عملکرد را با چیزی ساده پیادهسازی کنم، مثلا با یک هش مپ، اما از آنجایی که اکنون همه ارجاعات مربوط به آن جستجو را توسط انتزاع کوچکم تحت پوشش قرار دادم، میتوانم هر زمان که بخواهم، پیادهسازی را تغییر دهم. من بعدا میتوانم با حفظ توانایی خود برای تغییر، به سرعت پیش بروم. علاوه بر این، وقتی با چند روش نسبتا ساده میتوانم همه چیزی که میخواهم را بیابم، مجموعه انتزاع اغلب توجه مرا به آنچه که "واقعاً" در جریان است، جلب میکند و مرا از مسیر پیادهسازی مجموعه رفتارهای دلخواه منصرف میکند. Duplication کاهش یافته، بیان واضح و ساخت انتزاعات ساده از ابتدا. این چیزی است که برای من کد تمیز میسازد.
در اینجا، در چند پاراگراف کوتاه، Ron مطالب این کتاب را خلاصه کرده است.
بدون Duplication، یک چیز، بیان، تجریدهای کوچک. همه چیز آنجاست.
و **Ward Cunningham مخترع ویکی، مخترع Fit، هم اختراع کننده eXtreme Programming. نیروی انگیزشی در پشت Design Pattern. رهبر فکری شی گرایی و Smalltalk. پدرخوانده همه کسانی که به کد اهمیت میدهند:**وقتی هر روالی(Routine) که میخوانید دقیقا همان چیزی است که انتظار دارید، شما میدانید که دارید روی کد تمیز کار میکنید. همچنین هنگامی که کد شبیه به زبانی که برای مشکل درست شده است، میتوانید آن را یک کد زیبا بنامید.
جملههایی مانند این، خصوصیات Ward است. شما آن را خوانده اید، سر خود را تکان داده اید، و سپس به موضوع بعدی رفته اید. منطقی به نظر می رسد، بطور واضح این مسئله به سختی به عنوان یک مسئله عمیق و ژرف درنظر گرفته میشود. ممکن است فکر کنید تقریباً همان چیزی بود که انتظار داشتید. اما بیایید نگاه دقیق تری داشته باشیم. " . . تقریباً آنچه انتظار داشتید. " آخرین باری که ماژولی را دیدید که تقریباً همان چیزی بود که انتظار داشتید کی بود؟ آیا به احتمال زیاد ماژولهایی که به آنها نگاه میکنید گیج کننده، پیچیده و درهم و برهم نیستند؟ این قانون اشتباه نیست؟ آیا شما عادت نکردید که تلاش برای گرفتن و نگه داشتن تارهای استدلال که از کل سیستم به دست می آیند و راه خود را در ماژولی که میخوانید درست میکنند، به هیچ انگارید؟ آخرین باری که یک کد را خواندید و سر خود را به شکلی که Ward گفته است تکان دادید، کی بود؟ Ward انتظار دارد که وقتی کد تمیز را میخوانید به هیچ وجه تعجب نکنید. در واقع، شما حتی تلاش زیادی هم نمی کنید. شما آن را خواهید خواند، و تقریباً همان چیزی است که انتظار دارید. این امر آشکار، ساده و قانع کننده خواهد بود. هر ماژول مقدمات را برای مرحله بعد تنظیم میکند. هر کدام به شما میگوید که بعدی چگونه نوشته خواهد شد. برنامههایی که آن چنان تمیز هستند، به گونه ای عمقی و خوب نوشته شده اند که حتی متوجه آن نمیشوید. طراح باعث میشود مانند همه طرحهای استثنایی، این مسئله به طرز مسخره ای ساده به نظر برسد.
تفکر Ward در مورد زیبایی چطور؟ همه ما در برابر این واقعیت که زبانهای ما برای مشکلات ما طراحی نشده اند جبهه میگیریم. اما جمله Ward باری را بر دوش ما میگذارد. او میگوید که کد زیبا باعث میشود اینطور به نظر برسد که زبان برای این مشکل ایجاد شده است! بنابراین این مسئولیت ماست که زبان را ساده جلوه دهیم! طرفداران زبانها در همه جا هستند، هشیار باشید این زبان نیست که برنامهها را ساده جلوه دهد. این برنامهنویس است که باعث میشود زبان ساده به نظر برسد!
در مورد من(عمو Bob) چی؟ من در مورد کد تمیز چه فکر میکنم؟ این کتاب با جزییات زیاد آنچه من و همفکرانم درباره کد تمیز فکر میکنیم را به شما خواهد گفت. ما آنچه که فکر میکنیم یک نام متغیر تمیز، یک تابع تمیز، یک کلاس تمیز و غیره را ایجاد میکند به شما خواهیم گفت. ما این عقاید را مطلق ارائه خواهیم کرد و از سختگیری خود عذرخواهی نمیکنیم. برای ما، در این مرحله از حرفه مان، آنها مطلق هستند. آنها مکتب فکری ما در مورد کد تمیز هستند. هنرمندان رزمی همه با بهترین هنر رزمی یا بهترین تکنیک در یک هنر رزمی موافق نیستند. اغلب استادان هنرهای رزمی مکتب خود را تشکیل میدهند و دانش آموزان را برای یادگیری دور خود جمع میکنند. بنابراین ما Gracie Jiu Jistu را میبینیم، که توسط خانواده Gracie در برزیل تأسیس و تدریس شده است. ما Hakkoryu Jiu Jistu را میبینیم که توسط Okuyama Ryuho در توکیو تاسیس و تدریس شده است. ما Jeet Kune Do را میبینیم، که توسط بروس لی در ایالات متحده تاسیس و تدریس شده است. هنرجویان این رویکردها، خود را در آموزههای بنیانگذار غرق میکنند. آنها خود را وقف این می كنند كه آنچه آن استاد خاص تدریس میکند را فارغ از چیزی که استاد دیگر تدریس میکند، بیاموزند. بعداً با رشد هنرجویان در هنر خود، ممکن است دانش آموز استاد دیگری شوند تا بتوانند دانش و تمرین خود را گسترش دهند. عده ای سرانجام برای کشف مهارتهای خود، به کشف تکنیکهای جدید و تأسیس مکتب خود میروند. هیچ یک از این مکاتب مختلف کاملاً درست نیستند. با وجود این، در درون یک مکتب خاص به نظر میرسد که آموزهها و فنون صحیح هستند.
از این گذشته، یک روش درست برای تمرین Hakkoryu Jiu Jitsu یا Jeet Kune Do وجود دارد. اما این حق در یک مکتب، آموزههای یک مکتب متفاوت را باطل نمیکند. این کتاب را در مورد توصیفات مکتب اشیا آموزشی در کد تمیز در نظر بگیرید. تکنیکها و آموزههای موجود روشی است که ما هنر خود را تمرین میکنیم. ما مایل هستیم ادعا کنیم که اگر این آموزهها را رعایت کنید، از مزایایی که ما از آنها لذت بردیم لذت خواهید برد و یاد میگیرید که کدی بنویسید که تمیز و حرفه ای باشد. اما این اشتباه را نکنید که فکر کنید که "حق" به طور مطلق با ما است.
مکاتب و اساتید دیگری نیز وجود دارند که به همان اندازه که ما ادعا داریم، حرفه ای هستند. شایسته است که شما از آنها نیز بیاموزید. در واقع، بسیاری از توصیههای این کتاب جنجال برانگیز است. احتمالاً با همه آنها موافق نخواهید بود. ممکن است با بعضی از آنها به شدت مخالف باشید. خوب است. ما نمیتوانیم ادعای کمال اعتبار کنیم. از طرف دیگر، توصیههای موجود در این کتاب مواردی است که ما طولانی و سخت در مورد آنها فکر کرده ایم. ما آنها را طی چندین دهه تجربه و آزمایش و خطای مکرر آموخته ایم. بنابراین چه موافق باشید یا مخالف باشید، اگر به نقطه نظر ما احترام نگذارید و آن را نبینید شرم آور خواهد بود. ما نویسنده ایم فیلد @author در یک Javadoc به ما میگوید که ما کی هستیم. ما نویسنده هستیم و یک چیز در مورد نویسندگان وجود دارد و آن این است که آنها خواننده دارند. در واقع، نویسندگان مسئول برقراری ارتباط خوب با خوانندگان خود هستند. دفعه بعد که شما یک خط از یک کد را نوشتید، به یاد داشته باشید که شما نویسنده ای هستید که برای خوانندگانی که تلاش شما را قضاوت میکنند، مینویسید. ممکن است بپرسید : یک کد واقعا چه مقدار خوانده میشود؟ تمام تلاش ما صرف نوشتن آن نمیشود؟ آیا تاکنون به یک جلسه ویرایش دوباره باز گشته اید؟ در دهه 80 و 90 ویرایشگرانی مانند Emacs داشتیم که هرگونه فشار به صفحه کلید را ردیابی میکردند. میتوانید یک ساعت کار کنید و بعد از آن کلیه ویرایشهای خود را مانند یک فیلم پر سرعت پخش کنید. وقتی این کار را کردم، نتایج جالب توجه بود. هیچ یک از این مکاتب مختلف کاملاً درست نیستند. با وجود این، در درون یک مکتب خاص به نظر میرسد که آموزهها و فنون صحیح هستند.
اکثریت قریب به اتفاق تجدید نظرها در مورد بخش پیمایش و هدایت به سایر ماژولها بود! باب وارد ماژول میشود. او به تابعی که نیاز به تغییر دارد میرود او با توجه به گزینههای خود مکث میکند. اوه، او در حال برگشتن به بالای ماژول برای بررسی مقدار اولیه داده شده به یک متغیر است. اکنون او دوباره به پایین برمیگردد و شروع به تایپ میکند. اوه، او دارد آنچه را که تایپ کرده است پاک میکند! او دوباره آن را تایپ میکند. او دوباره آن را پاک میکند! او نیمی از چیز دیگری را تایپ میکند اما بعد آن را پاک میکند! او به تابع دیگری میرود که تابعی را که دارد تغییر میدهد را صدا میزند تا ببیند چگونه آن تابع صدا زده شده است. او دوباره به بالا برمیگردد و همان کدی را که تازه پاک کرده است تایپ میکند. مکث میکند. او دوباره آن کد را پاک میکند! وی پنجره دیگری را باز میکند و به یک زیر کلاس نگاه میکند. آیا این تابع دوبار نوشته شده است؟ . . . شما بی اراده کار میکنید. در واقع، نسبت زمانی که صرف خواندن میکنید در مقابل زمانی که صرف نوشتن میکنید بیش از 10: 1 است. همیشه بخشی از تلاشمان برای نوشتن کد جدید، برای خواندن کد قدیمی صرف میشود. از آنجا که این نسبت بسیار زیاد است، میخواهیم خواندن کد آسان باشد، حتی اگر این کار نوشتن را سختتر کند. البته هیچ راهی برای نوشتن کد بدون خواندن آن وجود ندارد، بنابراین آسان تر کردن خواندن در واقع نوشتن آن را آسان تر میکند. از این منطق گریزی وجود ندارد. اگر نمیتوانید کدهای اطراف را بخوانید، نمیتوانید کد بنویسید. نوشتن کدی که میخواهید امروز بنویسید بسته به اینکه چقدر خواندن کد اطراف آن سخت یا آسان باشد، دشوار یا آسان خواهد بود. بنابراین اگر میخواهید سریع کار کنید، اگر میخواهید به سرعت کار خود را به اتمام برسانید، اگر میخواهید کد شما به راحتی نوشته شود، خواندن آن را آسان کنید قانون پیشاهنگان پسر اینکه کد به خوبی نوشته شود کافی نیست. کد باید در طول زمان تمیز نگه داشته شود. با گذشت زمان، همه ما شاهد پوسیدن و کاهش درجه ارزش کد هستیم. بنابراین ما باید نقش فعالی در جلوگیری از این تخریب داشته باشیم. پیشاهنگان پسر امریکا یک قانون ساده دارند که ما میتوانیم از آن در حرفه خود استفاده کنیم. محل اردوگاه را تمیزتر از آنچه که به آن وارد شدید، ترک کنید اگر همه ما هنگام ورود به کد، كد خود را كمي تميزتر از زماني كه آن را رها کرده بوديم کنیم، كد به سادگي نمي تواند پوسيده شود. پاکسازی لازم نیست چیز بزرگی باشد. بهتر کردن نام یک متغیر، شکستن یک تابع نسبتا بزرگ به توابع کوچکتر، از بین بردن یک تکثیر، پاک کردن یک عبارت شرطی ترکیبی باعث تمیزتر شدن کد میشود. آیا میتوانید کار کردن روی پروژه ای که کدش با گذشت زمان به آسانی بهتر شده است را تصور کنید؟آیا معتقدید که گزینه ای غیر از این حرفه ای است؟ در واقع، آیا پیشرفت مداوم جز ذاتی حرفه ای بودن نیست؟ مقدمه و اصول از بسیاری جهات، این کتاب "مقدمه" کتابی است که من در سال 2002 با عنوان توسعه نرمافزار چابک: اصول، الگوهای و عملکردها نوشتم. کتاب PPP خود با اصول طراحی شی گرا و بسیاری از شیوههایی که توسط توسعه دهندگان حرفه ای استفاده میشود درگیر است. اگر PPP را نخوانده اید، ممکن است در آینده متوجه شوید که آن کتاب، داستانی که توسط این کتاب گفته شده را ادامه میدهد. اگر قبلاً آن را خوانده اید، میتوانید تکرار بسیاری از تفکرات آن کتاب در سطح کد را در این کتاب ببینید. در این کتاب اشاراتی پراکنده به اصول مختلف طراحی خواهید یافت. در میان این اصول اصل تک مسئولیت4، اصل بسته باز5 و اصل وارونگی وابستگی6 وجود دارد. این اصول به تفصیل در PPP شرح داده شده است نتیجه گیری کتابهای مربوط به هنر قول نمی دهند شما را به یک هنرمند تبدیل کنند. تمام کاری که آنها میتوانند انجام دهند این است که برخی از ابزارها، تکنیکها و فرآیندهای فکری که سایر هنرمندان استفاده کرده اند را به شما ارائه میدهند. بنابراین این کتاب نیز نمیتواند قول دهد شما را به یک برنامهنویس خوب تبدیل کند. نمیتواند قول بدهد که به شما "درک کد" را بدهد. تمام کاری که میتواند انجام دهد این است که فرآیندهای فکری برنامهنویسان خوب و ترفندها، تکنیکها و ابزارهایی را که از آنها استفاده میکنند به شما نشان دهد. درست مانند یک کتاب در زمینه هنر، این کتاب پر از جزئیات خواهد بود. تعداد زیادی کد وجود دارد. هم کد خوب خواهید دید و هم کد بد. میبینید که کد بد را به کد خوب تبدیل میکنید. لیستهای از اکتشاف، قوانین و تکنیکها را مشاهده خواهید کرد. مثال پشت مثال خواهید دید. پس از آن، به شما بستگی دارد. شوخی قدیمی درباره ویولنیست کنسرت را که در راه رسیدن به یک اجرا گم شده بود را به یاد میآورید؟ او پیرمردی را در گوشه ای متوقف کرد و از او پرسید که چگونه به Carnegie Hall برسد. پیرمرد به ویولنیست و ویولون زیر بازویش نگاه کرد و گفت: "تمرین کن پسرم. تمرین کن!"