راهکار اول: پیشنهاد بازساخت کد در زمان مناسب
در نگاه اول ممکن است بازساخت کد (refactoring) چندان مهم بهنظر نرسد، با این حال یک توسعهدهنده کاربلد قبل از هر چیز بررسی میکند که کد بازساخت شده باشد. ناگفته پیداست تغییر کدی که بازساخت شده باشد، بسیار راحتتر انجام میشود. برای روشنتر شدن این موضوع به نمونههای زیر توجه کنید:
نمونه اول: توسعهدهنده، کدی بسیار شبیه به کدهایی که پیش از این وجود داشته، مینویسد. چه بسا که این کدها را کُپی پِیست (Copy Paste)، کرده باشد. سپس بررسیکننده کد پیشنهاد دوباره کپیکردن این کدها را با انتقال آنها بهجای دیگری میدهد تا این کد در هر دو قسمت قابل استفاده باشد.
نمونه دوم: توسعهدهنده باید پروژه دیگری انجام دهد، به همین دلیل تابعی (function) را تغییر میدهد تا بهجای ۲ آرگومان (Argument)، پذیرای ۳ آرگومان باشد. آخرین آرگومان، بولین فلگ ( boolean flag) است که آرگومان را با ساختار If تقسیم میکند. اینجاست که بررسیکننده کد متوجه میشود اگر توسعهدهنده کلاس جدیدی برای مدل منطقی تجاری تازه ایجاد کند، تابع ساده میماند و دردسر تصمیمگیری (decision-making) به کلاس جدیدی منتقل میشود.
راهکار دوم: پیشنهاد روشهای اثربخشتر برای حل مسئله
این رویکرد در ۲ قسمت مختلف نمایان میشود. با پیشنهاد راهحلهای خلاصهتر (خطهای کمتر کد) یا راهحلی که عملکرد سریعتری داشته باشد. با این حال بهتر است دست رد به سینه افرادی بزنید که وسواس زیادی برای بهینهسازی کدها دارند. اگر به این افراد اجازه بدهید، تمامی پروژه را دوباره کدنویسی میکنند. راهکاری که برای بررسی کد مطرح کردیم با نمونههای زیر روشنتر میشود:
نمونه اول: توسعهدهنده راهحلی را با استفاده از for-loop با ساختار If اعمال میکند. در این شرایط بررسیکننده کد پیشنهاد میدهد این کد با list-comprehension و فیلتر If دوباره کدنویسی شود.
# First approach
available_employees = []
for employee in employees:
if employee.is_working():
available_employees.append(employee)
return available_employees
# Second approach, after code review
return [employee for employee in employees if employee.is_working()]
Copy
نمونه دوم: توسعهدهنده از لیست ثابت (Constant List ) مقدار (Value) استفاده میکند تا متغیر (Variable) داخل آن را تشخیص دهد. در این شرایط بررسیکننده کد یک، پیشنهاد استفاده از Tuple را برای بهینهسازی جستوجو میدهد. بررسیکننده دو نیز برای اثبات انتخاب مناسب، لیست بنچمارک (Benchmark List)، Tuple و Set را پیشنهاد میکند:
# original code
ALLOWED_STATUSES = [
'NEW',
'WAITING_FOR_RESPONSE',
'OVERDUE',
'REOPENED',
'ESCALATED',
]
def can_be_opened(ticket):
return ticket.status in ALLOWED_STATUSES
# benchmark using timeit module
## list
python3 -m timeit -s 'ALLOWED_STATUSES = ["NEW", "WAITING_FOR_RESPONSE", "OVERDUE", "REOPENED", "ESCALATED"]' '"NON_EXISTING" in ALLOWED_STATUSES'
> 5000000 loops, best of 5: 61.5 nsec per loop
## tuple
python3 -m timeit -s 'ALLOWED_STATUSES = ("NEW", "WAITING_FOR_RESPONSE", "OVERDUE", "REOPENED", "ESCALATED")' '"NON_EXISTING" in ALLOWED_STATUSES'
> 5000000 loops, best of 5: 56.1 nsec per loop # Negligible improvement
## set
python3 -m timeit -s 'ALLOWED_STATUSES = {"NEW", "WAITING_FOR_RESPONSE", "OVERDUE", "REOPENED", "ESCALATED"}' '"NON_EXISTING" in ALLOWED_STATUSES'
> 20000000 loops, best of 5: 15.6 nsec per loop # 4 times faster!
Copy
در نهایت، توسعهدهنده ممکن است حتا از Set استفاده نکند. این فرایند ۵ آیتم طولانی را در لیستی بررسی میکند که در جای حساسی قرار ندارد.
راهکار سوم: کلون (Clone) محلی کد برای بررسی
این روش ساده، اما کارآمد، تغییر کدها را در بافت جامعتری نشان میدهد. تجربه ثابت کرده بهرغم اینکه گیتهاب (Github)، بیتباکِت (Bitbucket) و گیتلَب (Gitlab)، روشی راحت برای بررسی کد با هایلایتکردن خطهای تغییریافته در اختیار توسعهدهندگان قرار میدهند، «کلون محلی کد» در بعضی از شرایط خاص کارآمد بهنظر میرسد.
راهکار چهارم: توجه داشتن به معیارهای پذیرش (acceptance criteria)
منظور از توجه داشتن به معیارهای پذیرش، بررسی سرسری کدها برای تشخیص تیکت (Ticket) در عنوان آنها نیست. منظور این است که ابتدا عنوان تیکت را بخوانید، سپس اگر معیارهای پذیرش در آن قابلقبول بود، این معیارها را یکیپسازدیگری تایید کنید. برای روشنتر شدن این راهکار اجازه دهید مثالی بزنیم:
نمونه: یک توسعهدهنده، کدی برای محاسبه قیمت ارسال کالا مینویسد. یک بررسیکننده تیکت این کد را در قسمت معیار پذیرش ۴ میخواند و متوجه میشود که قانونی برای ارسال رایگان کالا با ارزش بیشتر از ۲۰۰ دلار وجود دارد. اینجاست که بررسیکننده درخواست ایجاد تغییر در این کد را صادر میکند.
این رویکرد باید در نقطه آغاز مراحل بررسی کد قرار گیرد. نمونههای زیادی را سراغ داریم که مهندسین از دیدگاه فنی کدنویسی را انجام میدهند و توجهی به دلایل اصلی نگارش کد در مرحله اول ندارند.
راهکار پنجم: ابتدا تستها را بخوانید
رویکرد مطالعه نسخت تستها بهترین انتخاب برای بررسی کد بهحساب میآید. این رویکرد در کنار نوشتن کد، برای خواندن کدها نیز کاربرد دارد. در این مرحله نیز باید توجه ویژهای برای پذیرش معیارها انجام شود. وجود بررسیکننده کد در این مرحله الزامی است. بررسیکننده کد باید تمامی معیارهای پذیریش را که در تیکت مشخص شده، توضیح دهد.
راهکار ششم: توجه ویژهای به نامها داشته باشید
توسعهدهندگان ارشد باید دانش بیشتری درباره نامگذاری داشته باشند. هر چقدر که دانش توسعهدهندگان ارشد در نامگذاری بیشتر باشد، نامهای دقیقتر و خلاصهتری انتخاب میکنند. توسعهدهندگان باتجربهای که مدتی است در یک پروژه فعالیت دارند، باید نام گذاری را زیرنظر بگیرند تا جلوی نامگذاری مترادف گرفته شود و دیگر توسعهدهندگان این کدها را راحتتر درک کنند.
نمونه: توسعهدهندهای نام مترادفی برای یک متغیر (Variable) پیدا میکند. این نام مترادف، طولانی است. ریشههای فرانسوی دارد و غیرمتعارف بهنظر میرسد. اینجاست که بررسیکننده کد به توسعهدهنده پیشنهاد میدهد تا از نامهای رایج در پروژه استفاده کند.
وظیفه اصلی بررسیکننده کد
بسیاری از فعالان دنیای نرمافزار وظیفه اصلی بررسیکننده کد را آموزش به دیگر توسعهدهندگان میدانند. با این حال این تعریف کاربرد چندانی ندارد. بررسیکننده کد باید در کمترین زمان باگها (Bugs) را شناسایی کند.
به این مطلب چند ستاره میدهید؟(امتیاز: 4.5 - رای: 1)
- منبع: breadcrumbscollector
- مترجم: محمد کاملان