Free

ترك Claude يعيد الهيكلة

لإعادة الهيكلة لا أعراض — حين يخطئ Claude لا ترى ذلك. ثلاثة حواجز: اختبارات، commits ذرية، نقر يدوي.


إعادة الهيكلة هي المهمة التي يكون فيها Claude في أخطر حالاته. للأخطاء أعراض — زر لا يستجيب، قيمة undefined، stack trace — فتستطيع أن تحكم إن كان إصلاح Claude سليماً أم لا. إعادة الهيكلة لا أعراض لها. "لا يزال يعمل" قد يعني "الاختبارات لا تزال تمر" بينما السلوك تغيّر بصمت، ولم تنتبه، وبعد أسبوع يشتعل الإنتاج.

مؤخراً أجريت مع Claude إعادة هيكلة كبيرة نسبياً على how2claude: نقلت مدفوعات x402 من PaymentHandler + FacilitatorClient مكتوبتين يدوياً (139 سطراً) إلى gem x402-rails، وفي الوقت نفسه استخرجت تعيين الحقول لـ Purchase.create! / Subscription.create! — المكرر في كونترولرين — إلى دوال صنف على الموديل. commit واحد، 4 ملفات تغيرت، 2 حُذفت، 2 أُضيفت.

كان البرومبت كلمة واحدة: "refactor."

أمكن أن يكون بهذا القصر لأن الحواجز كانت موضوعة حوله.

الحاجز #1: لا إعادة هيكلة بدون اختبارات

حين وصل الفرع إلى تلك النقطة، كان لديه 221 اختباراً. كل المسارات الحرجة في تدفق الدفع مغطاة.

التصرف الافتراضي لـ Claude قبل إعادة الهيكلة ليس "انظر إلى الاختبارات أولاً." لذا أمرته أن يشغّل bin/rails test أولاً، ويتأكد من الأخضر، ثم يلمس أي شيء.

بعد إعادة الهيكلة، شغّلها مرة أخرى. لا تزال خضراء. هذا لا يعني غياب الانحدار — يعني أن السلوك المعروف لم يُكسر.

إذا كان مسار الكود غير مغطى بالاختبارات، اجعل Claude يكتب اختباراً أدنى يثبّت السلوك الحالي. شغّله، commit. ثم أعد الهيكلة. وإلا فما يفعله ليس إعادة هيكلة، بل إعادة كتابة — ولا طريقة للتحقق من التكافؤ.

الحاجز #2: اجعله يقسم التغيير إلى commits ذرية

هذه الإعادة كانت في الواقع شيئين:

  1. خلفية x402: يدوية → gem
  2. تعيين حقول Purchase / Subscription: controller → دوال صنف على الموديل

في الواجهة الأمامية شيء ثالث: إعادة كتابة تدفق التوقيع على جانب JS باستخدام viem + x402-fetch.

أجبرت Claude على التقسيم وفق الحدود الطبيعية: الخلفية + استخراج الموديل في commit واحد (9f3e239)، الواجهة الأمامية في commit منفصل (93746d8). كل commit يحمل وصفاً كاملاً، قائمة ملفات، وسبب التغيير.

الفوائد:
- الـ diff تبقى قابلة للقراءة. commit واحد، شيء واحد.
- دقة الـ rollback. إذا وقع خطأ واجهة أمامية في الإنتاج، git revert 93746d8 يعيد الواجهة فقط ويُبقي الخلفية.
- انتباه Claude نفسه يبقى مركّزاً. commit واحد شيء واحد — وانتباهه يغطي ذلك الشيء فقط.

الحاجز #3: اقرأ الـ diff قبل إعلان الانتهاء

حين تكتمل إعادة الهيكلة، أُوقف Claude وأجعله يُظهر لي git diff --staged. لا تشغّل الاختبارات. لا تشغّل التطبيق. اقرأ الـ diff أولاً.

الإشارات التي أفحصها:

  • ماذا حذف؟ app/services/x402/payment_handler.rb حُذف بالكامل — حسناً، هذا هو بيت القصيد من الانتقال إلى الـ gem. لكن إن حذف شيئاً لم أطلب لمسه، أتوقف وأسأل.
  • هل تغيّر تعيين الحقول؟ Purchase.create!(wallet_address: verify_result["payer"], ...)Purchase.record_x402!(payment:, settlement:) يقرأ الآن payment[:payer]. المصدر تغيّر (request.env الخاص بالـ gem مقابل قيمة الإرجاع من العميل القديم)، لكن يجب أن تتطابق الحقول واحداً بواحد.
  • تغييرات "على الطريق." يحب Claude أن يُصلح ما يبدو "خطأ" أثناء إعادة الهيكلة — إعادة صياغة رسائل الخطأ، إعادة تسمية متغيرات، استخراج دالة يظن أنها يجب أن تكون موجودة. تنبّه لهذه. وعد إعادة الهيكلة هو "تكافؤ السلوك." تغيير عابر يكسر ذلك.

فخّان وقع فيهما Claude هذه المرة

الفخ الأول: Stimulus controllers الخاصة بالـ gem لم تُحمَّل بصمت

gem x402-rails يُشحن مع Stimulus controllers خاصة به. كتب Claude الكود، مرّت الاختبارات خضراء. نقرتُ زر الدفع يدوياً — لا شيء.

السبب: config/importmap.rb كان فيه pin لـ @hotwired/stimulus يُشير إلى ملف vendor غير موجود، وimportmap أسقط ذلك الـ pin بصمت. فلم تُحمَّل controllers الـ gem أبداً. الاختبارات لا يمكنها التقاط هذا لأن bin/rails test لا ينفّذ JS.

الفخ الثاني: YAML حلّل 0x... كعدد صحيح

wallet_address: 0x833589... — بلا علامات اقتباس. رأى YAML البادئة 0x فقرأها كعدد صحيح ست عشري. استلم الـ facilitator قيمة غير نصية فرفض. لم يتوقف Claude للتفكير في قواعد تحليل YAML أثناء كتابة الإعدادات.

كلا الفخّين التُقطا لأنني نقرت الزر الفعلي. نجاح الاختبارات ليس كنجاح الميزة. التحقق اليدوي بعد إعادة الهيكلة ليس اختيارياً.

تدفق إعادة الهيكلة الكامل مع Claude

  1. شغّل مجموعة الاختبارات كاملة. أكّد الأخضر. إن لم يكن للكود المستهدف تغطية، اجعل Claude يكتب اختباراً أدنى يثبّت السلوك الحالي، ثم commit.
  2. قل ما السطح الذي تريد استخراجه. "Refactor" تكفي حين يكون التكرار واضحاً؛ وإلا قل "استخرج تعيين حقول X إلى دوال صنف في Y."
  3. قسّم إلى commits ذرية. commit واحد، شيء واحد.
  4. اقرأ الـ diff بنفسك. ماذا حُذف، هل يصمد تعيين الحقول، هل غيّر شيئاً على الطريق.
  5. شغّل الاختبارات مرة أخرى. أخضر.
  6. إن لامست مساراً مرئياً للمستخدم، انقر خلال الميزة يدوياً. طبقات لا تصل إليها الاختبارات — JS، importmap، CDN، تحليل YAML — عليك أن تراها بعينيك.

إعادة الهيكلة هي أعلى السيناريوهات خطراً في "اترك Claude يقود." الحواجز ليست من أجل Claude. هي من أجلك — لتلتقط أخطاء Claude في 5 دقائق، لا في حريق إنتاج.