"همهچیز تغییر میکند و دیگر هیچچیزی مانند سابق نخواهد بود... زندگی همین است! زندگی به پیش میرود و ما هم باید چنین باشیم!" (اسپنسر جانسون: چه کسی پنیر مرا جابهجا کرد؟)
تغییر نرمافزار، غیر قابل اجتناب است. نه تنها مشکلی ندارد، میتواند عالی هم باشد! زیر نظر گرفتن تغییرات، معلّم خوبی است و به ما کمک میکند که حوزهی تخصصی خود را بهتر و عمیقتر درک کنیم و بسیاری از اشتباهات را مرتکب نشویم. مادری را مثال میزنم که اولین فرزند خود را به دنیا میآورد و رشد کودکش را زیر نظر میگیرد و از آن تجاربی به دست میآورد؛ بعد از تربیت چند کودک، آشنایی بسیار خوبی با مراحل رشد و مقتضیات سنین مختلف خواهد داشت.
البته ما نرمافزار را بیعلت تغییر نمیدهیم! مايكل فزرس (Michael Feathers) چهار دلیل عمده برای تغییر نرمافزارها ذکر میکند:
نیاز مشتریان تا ابد ثابت نمیماند و ممکن است نیازهای جدیدی داشته باشند. از سویی دیگر، محصول شما رقیبانی در بازار دارد که نباید از آنها عقب بمانید. فرض کنید برای شرکتی کار میکنید که محصولی مشابه Medium را میسازد. قابلیتهای جدید Medium را پیادهسازی میکند و همچنین نیازهای دیگری که کاربران ایرانی دارند را برآورده میکند، مانند امکان درونریزی (import) از سیستمهای وبلاگدهی که در حال شکست هستند.
باگ نرمافزاری، یک ارور یا نقص فنی در یک برنامهی کامپیوتری است که میتواند منجر به یک نتیجهی اشتباه یا غیر قابل پیشبینی شود.
یکی دیگر از دلایل تغییر نرمافزار، اصلاحکردن باگها (fixing bugs) است. اصطلاح باگ به شکل وسیعی قبل از حوزهی نرمافزار، در حوزههای دیگر مهندسی به کار میرفته و حتی ادیسون هم از آن استفاده کرده است! باگها انواع زیادی دارند؛ بعضی منجر به خطایی بحرانی میشوند که برنامه را متوقف میکند و بعضی دیگر موجب عملکرد نادرست یا مشکلات امنیتی میگردند. پس از اینکه نرمافزار منتشر شود، توسط کاربران زیادی در شرایط مختلف استفاده میشود و همین، اشکالات زیادی را به ما خواهد شناساند. برنامهنویسان برای حل اشکالات شناساییشده، نرمافزار را تغییر میدهند و این تغییر میتواند در هر سطحی اتفاق بیفتد.
این نوع متفاوتی از تغییر نرمافزار است. میخواهیم ساختار نرمافزار را به نحوی تغییر دهیم که قابلیت نگهداری (maintainability) افزایش یابد، اما رفتار (behavior) آن دستنخورده و سالم باقی بماند! مایکل فزرس میگوید:
The act of improving design without changing its behavior is called refactoring.
یعنی عمل بهبود طراحی نرمافزار -بدون اینکه رفتار آن تغییر کند- را ریفکتورینگ میگوییم. مارتین فولر (Martin Fowler) هم دو تعریف برای ریفکتورینگ آورده که یکی بنا بر فرم اسمی (noun form: refactoring) و دیگری بنا بر فرم فعلی (verb form: refactor) آن است. بر اساس تعریف اول:
Change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behavior.
تغییرات به ساختار داخلی نرمافزار اعمال میشود تا برای دیگران قابلفهمتر و دستکاری آن -بدون تغییر رفتار قابل مشاهدهاش- ارزانتر باشد.
امیدوارم آنچه گفته شد به شما دید مناسبی از ریفکتورینگ داده باشد. وقتی نرمافزار را برای تحقق اهداف کوتاهمدت تغییر میدهیم و به ساختار کلی پروژه توجه نمیکنیم، نرمافزار به سوی خرابی میرود و نگهداری آن مشکل میشود؛ در آیندهی نهچندان دور به آسانی قادر به اعمال تغییرات و افزودن قابلیتهای جدید نخواهیم بود و کارمان شبیه یافتن سوزن در انبار کاه خواهد شد. اما ریفکتورینگ مداوم، شکل نرمافزار را حفظ کرده و از اینکه غیر قابل کنترل شود، جلوگیری میکند.
فایدهی دیگر ریفکتورینگ این است که فهم نرمافزار را آسان میکند. شما کدهایتان را تنها برای کامپیوتر نمینویسید بلکه افراد دیگری هم مجبور به خواندن آنها هستند تا نرمافزار را توسعه دهند، پس باید کدی بنویسید که ساختار ایدهآلی داشته باشد و منظور خود را به وضوح بیان کند! رابرت مارتین (Robert Martin) در مقدمهی Clean Code تعریفهای مختلفی از «کد تمیز» آورده و واحد WTFs/minute را برای اندازهگیری کیفیت کد در بازبینی (review) معرفی میکند که جای تأمل دارد، خودتان باید کتاب را بخوانید!
مارتین فولر فایدهی دیگری برای ریفکتورینگ ذکر میکند و آن هم کشف باگهاست؛ او میگوید که من در شناسایی باگها از طریق خواندن کد، خیلی خوب نیستم، ولی وقتی به ریفکتورینگ میپردازم، با درکی که از ساختار کد پیدا کردهام، باگها را شناسایی میکنم!
آیا ریفکتورینگ باعث توسعهی سریعتر هم میشود؟ جواب مثبت است زیرا از راهی که قبلاً صاف و هموار کردهاید عبور میکنید!
بهینهسازی (optimization) مانند ریفکتورینگ است، اما هدف متفاوتی از طریق آن دنبال میشود. در خصوص هردویشان میگوییم که «ما عملکرد را دقیقاً همانطوری که هست باقی میگذاریم و قصدمان چیز دیگری است»، ولی در ریفکتورینگ آن «چیز دیگر» ساختار برنامه است؛ یعنی میخواهیم نگهداری برنامه را آسانتر کنیم. دربارهی بهینهسازی چطور؟ در اینجا «چیز دیگر» نحوهی استفاده از منابع (معمولاً زمان و حافظه) است و میخواهیم مصرفشان را کاهش دهیم تا بازدهی نرمافزار افزایش یابد.
بعد از تمام اینها، شما را به خواندن مقالهی زیر دعوت میکنم:
https://virgool.io/@WebPajooh/soghote-narmafzarha-ap2pkaaw4om1
منابعی که این مقاله را شکل دادند: