کدنویسی با AI

Context-aware refactoring با AI

Context-aware refactoring با AI — راهنمای فارسی از مجموعهٔ «کدنویسی با AI» در وبلاگ آیرا. بازنویسی‌شده با تمرکز روی کاربر ایرانی و روایت شناخت پیوسته.

نوشتهٔ به‌روزرسانی: ۴ دقیقه مطالعه
تصویر مقالهٔ Context-aware refactoring با AI

بیشتر توسعه‌دهنده‌ها با ابزارهای AI کد می‌نویسن — ولی وقتی نوبت به refactoring می‌رسه، هنوز بیشتر کار رو دستی انجام می‌دن. چرا؟ چون refactoring بدون context، خطرناکه. و اینجاست که «context-aware refactoring» معنا پیدا می‌کنه.

refactoring ساده در مقابل context-aware

یه ابزار معمولی AI وقتی می‌گی «این تابع رو refactor کن» فقط همون تابع رو می‌بینه. نتیجه؟ شاید کد تمیزتر بشه، ولی:

  • یه متغیر که جای دیگه‌ای ازش استفاده می‌شه تغییر نام می‌گیره
  • یه side effect که تابع داشت حذف می‌شه
  • interface تابع تغییر می‌کنه و ۱۵ جای دیگه در کدبیس broken می‌شن

context-aware refactoring یعنی ابزار قبل از هر تغییری، کل کدبیس رو می‌فهمه — نه فقط فایل جلوی چشمش.

چه context‌هایی مهمن؟

وقتی داری از AI برای refactoring استفاده می‌کنی، چند لایهٔ context هست که باید پوشش داده بشن:

۱. Context معنایی (Semantic) مدل باید بدونه این تابع چیکار می‌کنه، نه فقط چطور نوشته شده. مثلاً اگه یه تابع calculateTax() داری که logic خاص ایران رو داره (مالیات ارزش افزوده، نرخ‌های مختلف)، refactoring نباید این semantics رو پاک کنه.

۲. Context وابستگی (Dependency) چه توابع دیگه‌ای این تابع رو صدا می‌زنن؟ چه توابعی صدا زده می‌شن؟ تغییر signature باید در همه‌جا propagate بشه.

۳. Context تست (Test) اگه unit test داری، refactoring نباید تست‌ها رو بشکنه — یا باید تست‌ها هم همزمان آپدیت بشن.

۴. Context تیمی و سبک (Style) آیا تیم شما از camelCase استفاده می‌کنه یا snake_case؟ آیا prefer می‌کنید early return باشه یا nested if؟ Context-aware refactoring باید سبک تیم رو رعایت کنه.

ابزارهای موجود و واقعیت آن‌ها

Cursor

Cursor با قابلیت «Codebase Context» می‌تونه کل repo رو index کنه. وقتی می‌گی refactor کن، معمولاً وابستگی‌ها رو هم می‌بینه. محدودیتش اینه که context window مدل محدوده — اگه repo خیلی بزرگه، همه چیز توی context جا نمی‌گیره.

مثال واقعی: در Cursor می‌تونی بنویسی:

این تابع رو به دو تابع کوچیک‌تر تقسیم کن. مطمئن شو همهٔ callsite هایی که ازش استفاده می‌کنن آپدیت بشن.

Cursor معمولاً فایل‌های مرتبط رو پیدا می‌کنه — ولی اگه codebase بزرگه، شاید همه رو پیدا نکنه.

GitHub Copilot

Copilot Chat می‌تونه context فایل فعلی رو بگیره، ولی برای refactoring cross-file نیاز به workspace indexing داره که در نسخه‌های جدید بهتر شده. برای تغییرات محدود به یه فایل، عملکرد خوبیه.

Continue.dev

ابزار open-source‌ای که می‌ذاره مدل LLM دلخواه رو انتخاب کنی. برای context-aware refactoring می‌تونی repo رو به عنوان context بدی، ولی نسبت به Cursor کار دستی‌تری نیاز داره.

Claude در API

اگه مستقیم با Claude API کار می‌کنی و کل کد رو توی context می‌ذاری، Claude یه ابزار فوق‌العاده برای refactoring پیچیده‌ست — چون context window طولانی‌اش (تا ۲۰۰K token در Claude 3.5 Sonnet) بهت امکان می‌ده کدهای بزرگ رو یکجا بدی.

یه workflow عملی برای refactoring با AI

اگه می‌خوای context-aware refactoring واقعی داشته باشی، این مراحل رو دنبال کن:

قدم ۱: قبل از prompt، context رو آماده کن به جای اینکه فقط تابع مورد نظر رو بدی، فایل‌های مرتبط رو هم اضافه کن. یه ابزار مثل grep یا find usages IDE ات رو برای پیدا کردن callsite ها استفاده کن.

قدم ۲: نیت رو صریح بگو «این تابع رو تمیزتر کن» کافی نیست. بگو:

می‌خوام این تابع رو refactor کنم تا:
۱. به جای یه تابع ۸۰ خطی، سه تابع کوچیک‌تر بشه
۲. خوانایی بالا بره
۳. تست‌پذیری بهتر بشه
مطمئن شو callsite ها هم آپدیت می‌شن.

قدم ۳: تغییرات رو incremental اعمال کن همه رو یک‌جا نده. اول یه تابع، ببین درست کار می‌کنه، بعد بقیه.

قدم ۴: تست بنویس قبل از refactoring اگه تست نداری، از AI بخواه اول تست‌های پوشش‌دهنده بنویسه. بعد refactor کن. این روش (test-first refactoring) ضامن اینه که رفتار تغییر نمی‌کنه.

مثال واقعی: refactoring یه service پیچیده

فرض کن یه UserAuthService داری که ۳۰۰ خط شده و همه چیز توشه — login، register، token refresh، password reset. می‌خوای تجزیه‌اش کنی.

یه prompt خوب می‌تونه اینجوری باشه:

این فایل UserAuthService.ts رو ببین (attach کردم).
همینطور این فایل‌ها که ازش استفاده می‌کنن: AuthController.ts، UserRouter.ts.

می‌خوام این service رو به چهار service جدا تقسیم کنم:
- LoginService (فقط login/logout)
- RegistrationService (register + email verification)
- TokenService (refresh + invalidation)
- PasswordService (reset + change)

لطفاً:
۱. ساختار هر service جدید رو پیشنهاد بده
۲. interface های لازم رو تعریف کن
۳. AuthController.ts و UserRouter.ts رو برای استفاده از service های جدید آپدیت کن

با این prompt، یه مدل خوب مثل Claude یا GPT-4 می‌تونه یه plan کامل بده که callsite ها هم پوشش داده شده باشن.

چه وقتی از AI برای refactoring استفاده نکنی

  • وقتی منطق کسب‌وکار پیچیده‌ای داری که باید دقیقاً بفهمیش — AI ممکنه semantics رو اشتباه بگیره
  • وقتی codebase خیلی بزرگه و کل context جا نمی‌گیره
  • وقتی تست پوشش کافی نداری و ریسک regression بالاست

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

همچنین بخوان

#کدنویسی با AI

ادامهٔ مسیر

همهٔ مقاله‌ها ←

بیشتر در «کدنویسی با AI»