كان الدرس 3.2 عن تحديد النطاق بحسب الملف. وهذا الدرس عن تحديد النطاق بدرجة أدقّ — بحسب الشيء داخل الملف الذي تهتمّ به فعلًا.
إن كان لديك اسم، فلستَ بحاجة إلى موقع. الاسم هو السؤال.
أكثر الفضول في الكود يحدث عند مستوى function واحدة، أو component واحد، أو class واحدة — لا ملف واحد. يقول زميل «الـ bug في handleContact». تصطدم بـ stack trace يشير إلى saveMessage. تقرأ ملفًا فترى استدعاءً لـ sendNotification لم تتتبّعه قط. لستَ بحاجة إلى إيجاد الملف أولًا. كل ما عليك أن تسأل في المحادثة.
الخطوة
اكتب هذا في Claude:
where is handleContact and what does it do?
سيقوم Claude بما يلي:
- يبحث في المشروع عن
handleContact. - يفتح الملف الذي يعيش فيه.
- يقرأ الـ function (وعادةً الأسطر المحيطة بها مباشرةً).
- يخبرك بما تفعله — بلغة بسيطة.
تعرف أين هو وماذا يفعل في الإجابة نفسها. عصفوران بسؤال واحد.
لماذا هذا أكبر مما يبدو
قبل Claude، كان العثور على function بالاسم مهمّةً صغيرة بحدّ ذاتها. كنتَ تفتح المشروع في محرّر، وتضغط «Go to symbol»، وتمرّر عبر النتائج، وتجرّب ملفين، وتعثر عليها في النهاية. أو كنتَ تشغّل بحثًا نصّيًّا عبر المشروع، فتحصل على جدار من المطابقات، وتنتقي الصحيحة بعينك.
ليس هذا صعبًا. إنه مجرد احتكاك. والاحتكاك يقتل الفضول — أكثر الناس يتوقفون عن طرح السؤال لأن إيجاد الإجابة يستغرق وقتًا طويلًا.
مع Claude، اختفى الاحتكاك. السؤال والإجابة يستغرقان العدد نفسه من الثواني. تستطيع أن تتحمّل أن تكون فضوليًا حيال كل اسم لا تعرفه، بدلًا من الأسماء التي تبدو مهمّة فقط.
بضعة أشكال مفيدة
النسخة الأساسية:
explain handleContact
حين يبدو اسمان متشابهين ولستَ متأكدًا من الفرق بينهما:
what's the difference between saveMessage and loadMessages in this project?
حين تريد عمقًا، لا مجرد تحديد:
walk me through saveMessage line by line. What does it do, what does it call, and what does it return?
حين تريد معرفة ما إذا كانت الـ function آمنة للتغيير:
what calls handleContact? Would changing how it handles errors break anything obvious?
ذلك الشكل الأخير — «ما الذي يستدعي هذا؟» — هو فكرة كبيرة بحدّ ذاته، وله درسه الخاص تاليًا.
النقطة التي تربك الناس
فخّان.
أولًا، يفترض المتعلّمون أن Claude يحتاج إلى تهجئة مثالية. لا يحتاج. «ابحث عن الـ function التي تعالج الـ contact form» ينجح. «هناك شيء اسمه شبيه بـ contactHandler أو handleContact، ابحث عنه» ينجح. Claude متسامح حيال التسمية — أعطِه وصفًا وسيستنتج الـ symbol.
ثانيًا، يفترض المتعلّمون أن «ابحث عن هذه الـ function» تعني «ابحث عن function بهذا الاسم بالضبط». ليس بالضرورة. «ابحث عن الـ function التي ترسل إشعار الـ email» سؤال جيد تمامًا. أنت تبحث بحسب ما يفعله، لا بحسب ما اسمه. أحيانًا لا تعرف الاسم بعد — وهذا لا بأس به.
وحدة الفضول هي الشيء-الذي-تريد-فهمه، لا الشيء-المسمّى-بهذا-بالضبط.
الربط بمفرداتك الموجودة
في الدرس 3.7 تعلّمتَ أن الـ codebase هو مجلد من الملفات. الملفات تحتوي functions. الـ functions هي ما يفعل الأشياء — إنها أفعال البرنامج.
في أغلب الأحيان، حين يحدث شيء مثير للاهتمام في الكود، تكون function مسؤولةً عنه. تُعالَج الـ contact form لأن function ما اشتغلت. تُحفَظ الرسالة لأن function ما كتبتها. يخرج إشعار الـ email لأن function ما قرّرت إرساله.
معرفة كيفية السؤال عن functions بالاسم هي، بمعنى حقيقي، تعلُّمُ كيفية السؤال عن ما يفعله برنامجك فعلًا.
ماذا يفعل Claude في الخفاء
حين تسأل «أين saveMessage؟»، يقوم Claude بالمطاردة نفسها التي كنتَ ستقوم بها يدويًّا — يبحث في كل ملف في المشروع عن ذلك الاسم. الفرق هو ما يحدث بعد ذلك.
الطريقة القديمة كانت تُلقي كومةً من المطابقات الخام في حِجرك: saveMessage يظهر في server/messages.js (السطر 12)، وفي server/index.js (السطر 30)، وعليك أن تفرز بعينك أيّها التعريف وأيّها استدعاء. Claude يقوم بتلك القراءة نيابةً عنك. يفتح تلك الملفات، وينظر إلى الأسطر حول كل مطابقة، ويسلّمك جملة: «saveMessage مُعرَّف في server/messages.js ومُستدعى مرةً واحدة من server/index.js، حيث يسلّمه الـ contact endpoint رسالةً ليخزّنها». البحث نفسه — دون شيء من الاحتكاك.
ما التالي
ما إن تستطيع السؤال عن function واحدة، يصبح السؤال التالي البديهي «وما الذي يلمسها أيضًا؟» — من أين تُستدعى، وإلى أين يذهب return value الخاص بها، ومن أين تأتي البيانات التي تعتمد عليها. ذلك هو التتبّع، وهو أعلى قراءة رفعًا في هذا المستوى بأكمله.