بازگشت به کتاب‌ها
جلد کتاب کار مؤثر با کدهای قدیمی نوشتهٔ مایکل فدرز

کار مؤثر با کدهای قدیمی

نوشتهٔ مایکل فدرز · سال انتشار 2004

کاربردی‌ترین کتاب برای آن ۹۰ درصد از کار نرم‌افزاری که پروژهٔ نو نیست — «کد قدیمی» را دقیقاً به‌عنوان «کد بدون تست» بازتعریف می‌کند و تکنیک‌های پیدا کردن درز هنوز استاندارد هستند.

نقاط قوت

  • «کد قدیمی» را دقیقاً (کد بدون تست) بازتعریف می‌کند به شکلی که مسئله را قابل‌حل می‌کند
  • تکنیک‌های درز و شکستن وابستگی مستقیماً و فوراً روی کدبیس‌های واقعی قابل استفاده‌اند

نقاط ضعف

  • مثال‌های کد مربوط به دورهٔ جاوا/سی‌پلاس‌پلاس‌اند و نحوشان کمی قدیمی است، هرچند تکنیک‌ها به‌خوبی قابل انتقال‌اند
  • کتابی برای خواندن کامل و لذت‌بردن نیست — مرجعی است که سراغش می‌روی وقتی مسئله‌ای پیش می‌آید

خلاصه کتاب

مایکل فدرز با تعریفی شروع می‌کند که بیشتر کار کتاب را انجام می‌دهد: کد قدیمی، کدِ بدون تست است. نه کد قدیمی از نظر سن، نه کد به زبانی از مد افتاده، نه کدی که نویسنده‌اش رفته. کدی که نمی‌توانید با اطمینان تغییرش دهید چون هیچ‌چیز به شما نمی‌گوید کِی خرابش کرده‌اید.

همین بازقاب‌بندی، یک مسئلهٔ عاطفی را به مسئله‌ای فنی تبدیل می‌کند. «این کدبیس افتضاح است» هیچ گام بعدی ندارد؛ «این کد تست ندارد و باید پیش از تغییر، تست اضافه کنم» دارد.

مانع، دوری است و فدرز صریح نامش را می‌برد: برای تغییر ایمنِ کد به تست نیاز دارید، اما برای افزودن تست معمولاً باید کد را تغییر دهید، چون کد برای تست‌پذیری نوشته نشده. وابستگی‌ها سفت‌وسخت کدشده‌اند، سازنده‌ها کار واقعی انجام می‌دهند، و کلاسی که می‌خواهید تست کنید نیمی از سیستم را با خودش می‌کشد.

کتاب فهرستی از تکنیک‌هاست برای شکستن این حلقه — یافتن جاهایی که می‌شود رفتار را بدون ویرایش کد در همان نقطه تغییر داد، جداکردن قطعه‌ای که برایتان مهم است، گذاشتن یک تست دورش، و تنها بعد از آن انجام تغییری که از اول از شما خواسته شده بود.

ایده‌های کلیدی

۱. درزها و نقاط فعال‌ساز

مفهوم محوری کتاب. درز جایی است که می‌توانید رفتار برنامه را بدون ویرایش کد منبع در همان نقطه تغییر دهید، و هر درزی یک نقطهٔ فعال‌ساز دارد که تصمیم در آن گرفته می‌شود.

درز شیء حالت رایج است: اگر کلاسی همکارش را از طریق یک اینترفیس صدا بزند، می‌توانید هنگام ساخت، پیاده‌سازی دیگری جایگزین کنید. نقطهٔ فعال‌ساز، هرجایی است که آن شیء تأمین می‌شود.

فدرز درزهای پیوند (جابه‌جایی کتابخانه‌ها در زمان لینک یا بارگذاری) و درزهای پیش‌پردازنده در سی و سی‌پلاس‌پلاس را هم پوشش می‌دهد. ارزش این واژگان این است که «این تست‌ناپذیر است» را به یک جست‌وجو تبدیل می‌کند: نزدیک‌ترین درز کجاست، و نقطهٔ فعال‌سازش چیست؟

۲. جوانه‌زدن و پیچیدن، به‌جای ویرایش در جا

برای وضعیت رایجی که باید رفتاری به متدی اضافه کنید که نمی‌توانید ایمن بازآرایی‌اش کنید، فدرز چهار تکنیک ارائه می‌دهد که به منطق موجود دست نمی‌زنند.

«متد جوانه‌زده» رفتار جدید را در متدی جدید و تست‌شده می‌گذارد و از متد قدیمی صدایش می‌زند — کد بدون تست یک خط اضافه می‌کند، و کد جدید کاملاً پوشش داده می‌شود. «کلاس جوانه‌زده» همین کار را در مقیاس کلاس می‌کند وقتی کلاس موجود زیادی درهم‌تنیده است.

«متد پیچیده» نام اصلی را عوض می‌کند و متدی جدید با نام قدیمی می‌سازد که هم آن و هم رفتار جدید را صدا می‌زند. «کلاس پیچیده» الگوی دکوریتور را برای همین هدف به کار می‌برد.

اصل مشترک این است که کد جدید باید تست‌پذیر باشد حتی وقتی کد پیرامونش نیست، و اینکه این امروز شدنی است نه پس از پاک‌سازی‌ای که هرگز زمان‌بندی نخواهد شد.

۳. تست‌های توصیف‌گر، توصیف می‌کنند نه تجویز

یکی از مفیدترین بازقاب‌بندی‌ها برای هرکسی که با کد بدون مستندات روبه‌روست. تست توصیف‌گر ادعا نمی‌کند کد باید چه کند؛ ادعا می‌کند کد در حال حاضر چه می‌کند.

روشش مکانیکی است: تستی بنویسید که چیزی را ادعا کند که می‌دانید غلط است، اجرایش کنید، مقدار واقعی را از پیام شکست بخوانید، و ادعا را با آن مطابق کنید. تکرار کنید تا رفتار را میخکوب کنید.

این فلج‌شدگیِ ناشی از ندانستن رفتار موردنظر را حل می‌کند. لازم نیست بدانید — لازم است سندی از رفتار فعلی داشته باشید تا هر تغییری که می‌دهید خودش را اعلام کند. باگ‌ها هم عامدانه حفظ می‌شوند، چون ممکن است چیزی به آن‌ها وابسته باشد.

۴. شکستن وابستگی، مهارت اصلی است

بزرگ‌ترین بخش کتاب فهرستی از حدود دو دوجین تکنیک شکستن وابستگی است، هرکدام با نام، رویه و مثال‌های کارشده.

استخراج اینترفیس، پارامتری‌کردن سازنده، استخراج و بازنویسی فراخوانی، زیرکلاس‌کردن و بازنویسی متد، معرفی نمایندهٔ نمونه — بیشترشان کوچک و مکانیکی‌اند، و ارزششان دقیقاً این است که انجامشان بدون تست ایمن است، چون ساختار را تغییر می‌دهند نه رفتار را.

فدرز صادق است که بعضی‌شان زشت‌اند. زیرکلاس‌کردن صرفاً برای بازنویسی متدی به‌قصد تست، طراحی زیبایی نیست؛ گامی است که اجازه می‌دهد تستی سرِ جایش بگذارید، و پس از آن طراحی بهتر ممکن می‌شود.

۵. در جهت تغییر کار کنید

مضمونی که در کتاب جریان دارد این است که نباید بکوشید یک کدبیس قدیمی را یکجا درست کنید. هیچ‌کس اجازه‌اش را نمی‌دهد و تمام هم نمی‌شود.

در عوض، کدی را بهتر کنید که همین حالا دستتان است. رویکرد فدرز این است که نقاط تغییر را شناسایی کنید، نزدیک‌ترین درزها را پیدا کنید، حداقل وابستگی‌های لازم را بشکنید، تست اضافه کنید، و بعد تغییر را انجام دهید.

اثر تجمعی این است که بخش‌هایی از سیستم که فعالانه توسعه می‌یابند خوب تست می‌شوند و بخش‌های خفته همان‌طور می‌مانند — که تخصیص درستی است، چون کد بدون تستی که کسی تغییرش نمی‌دهد ریسک بسیار کمتری از کد بدون تستی است که هفتگی عوض می‌شود.

برای چه کسی مفید است

  • هرکسی که کدبیسی را نگه‌داری می‌کند که خودش ننوشته — که بیشترِ وقتِ بیشترِ توسعه‌دهنده‌هاست.
  • توسعه‌دهنده‌ای که TDD بلد است اما سیستم بدون تست تحویل گرفته — این همان پل گمشده است.
  • هرکسی که وسوسهٔ بازنویسی دارد — جایگزین تدریجی به‌طور عینی چیده شده.
  • سرپرستان تیم که بازآرایی برنامه‌ریزی می‌کنند — رویکرد نقطهٔ تغییر، راهبردی قابل‌دفاع برای پیشنهاددادن است.
این کتابی نیست که سرتاسرش را برای لذت بخوانید — مرجعی است که سراغش می‌روید وقتی مسئله‌ای پیش می‌آید. فصل‌های ابتدایی دربارهٔ درزها و تست‌های توصیف‌گر را درست بخوانید، بعد فهرست شکستن وابستگی را چیزی بدانید که وقتی کلاسی سرِ جنگ با شما دارد به آن مراجعه می‌کنید.
مثال‌های کد، جاوا و سی‌پلاس‌پلاسِ سال ۲۰۰۴ هستند و نحوشان قدیمی به‌نظر می‌رسد، به‌ویژه در بخش تزریق وابستگی که فریم‌ورک‌های امروزی متفاوت مدیریتش می‌کنند. خود تکنیک‌ها به هر زبان شیءگرایی به‌خوبی منتقل می‌شوند، اما ترجمه‌اش را خودتان باید انجام دهید — انتظار داشته باشید از سطح مثال‌ها عبور کنید و به حرکت ساختاریِ زیرش برسید.

سؤالات پرتکرار

باید جاوا یا سی‌پلاس‌پلاس بلد باشم؟

نه. مثال‌ها از آن‌ها استفاده می‌کنند، اما تکنیک‌ها ساختاری‌اند و به هر زبان شیءگرایی اعمال می‌شوند. خواندن کدها حتی اگر با آن زبان کار نکنید هم سرراست است.

بعد از بیست سال هنوز مربوط است؟

بله — احتمالاً بیشتر از قبل. بیشتر کار نرم‌افزاری، تغییردادن سیستم‌های موجود است، و مسئلهٔ بنیادیِ تست‌کردن کدی که برای تست طراحی نشده تغییری نکرده.

اگر کدم واقعاً غیرقابل‌نجات باشد چه؟

فدرز می‌گوید این نادرتر از چیزی است که حس می‌شود، و اینکه بازنویسی‌ها معمولاً به همان دلایلی شکست می‌خورند که کد اصلی افت کرد. رویکرد تدریجی کندتر است اما به‌مراتب محتمل‌تر است که تمام شود.

از کجا شروع کنم؟

فصل درزها و تست‌های توصیف‌گر. این دو مفهوم نحوهٔ نگاهتان به کد تست‌ناپذیر را عوض می‌کنند، و بقیهٔ کتاب عمدتاً کاربردهای همان‌هاست.

نسبتش با «بازآرایی» چیست؟

فاولر فرض می‌گیرد تست دارید؛ فدرز می‌گوید وقتی ندارید چطور تست به دست بیاورید. اگر کدبیستان بدون تست است اول فدرز را بخوانید — پیش‌نیاز است.

این مطلب برایتان مفید بود؟

شمارش آرا پس از ۵ رأی نمایش داده می‌شود.

بیشتر در همین دسته