في هندسة البرمجيات، هناك جملة تتكرر كثيرًا: “اثنان فقط من أصعب الأمور في علوم الحاسب: إبطال التخزين المؤقت، وتسمية الأشياء.” ما يثير السخرية أن التسمية تبدو سهلة من الخارج: أنت تختار كلمة، وتضعها في مكانها، وتمضي. لكنها في الواقع من أكثر المهام استهلاكًا للطاقة الذهنية، وأكثرها تأثيرًا على جودة الكود على المدى الطويل[reference:0].

الوجه الآخر للمشكلة هو فهم كود الآخرين. تشير الدراسات الميدانية إلى أن المطورين يقضون حوالي 58% من وقتهم في فهم البرامج، لا في كتابتها. وبعض التقديرات تذهب إلى أن نسبة الوقت بين القراءة والكتابة تتجاوز 10 إلى 1 في بيئات العمل الحقيقية. أي أن “القراءة” ليست تحضيرًا للعمل، بل هي العمل نفسه.

هذا الدليل يربط بين المشكلتين: لماذا تتعثر التسمية؟ وكيف تتحول الأسماء الرديئة إلى حائط أمام من يقرأ الكود لاحقًا؟ ثم يقدم استراتيجيات عملية للتسمية الجيدة، وتقنيات مجربة لفهم أكواد غير مألوفة أو قديمة، مع دور الأدوات الحديثة بما فيها الذكاء الاصطناعي التوليدي.

نظرة سريعة: وجهان لمشكلة واحدة

الجدول التالي يلخص الفروق بين مشكلة التسمية ومشكلة فهم الكود، رغم أنهما وجهان لنفس العملية: نقل المعرفة بين البشر عبر الكود.

البعد صعوبة التسمية صعوبة فهم كود الآخرين
طبيعة المشكلة اختيار كلمة تعبر عن النية إعادة بناء نظرية النظام في ذهنك
السبب الجذري التواصل البشري أصعب من التواصل مع الآلة السياق Knowledge لا يوجد في الكود وحده
المظهر في الكود أسماء غامضة، مختصرة، أو مضللة تدفق غير واضح، تبعيات خفية، تسميات سيئة
التكلفة وقت مراجعة أطول وأخطاء فهم وقت طويل في القراءة قبل أي تعديل
الحل الأساسي أسماء كاشفة عن النية + مراجعة مدخلات، مسار طلب واحد، اختبارات، تاريخ Git

لماذا التسمية صعبة إلى هذا الحد؟

صعوبة التسمية وفهم كود الآخرين

التسمية ليست مجرد “اختيار كلمة”. إنها قرار تصميمي مصغر، وقرار تواصل، وقرار معرفي في الوقت نفسه. والأسباب التي تجعلها صعبة أعمق من مجرد نقص الخيال.

التسمية تواصل بشري، لا تواصل مع الآلة

الكود يعمل سواء سميت المتغير x أو expiredCouponCount. الآلة لا تهتم. لكن البشر يهتمون. ولهذا فإن جزءًا كبيرًا من صعوبة التسمية يأتي من أنها تواصل مع أشخاص آخرين، في وقت لاحق، بسياق مختلف، وربما بلغة مختلفة. أنت لا تكتب اسمًا لنفسك الآن، بل لشخص سيفتح الملف بعد ستة أشهر.

الاسم لا يرتبط ماديًا بما يسميه

في التجريد البرمجي، لا توجد علاقة طبيعية بين الاسم والشيء المسمى. يمكنك أن تسمي دالة تحسب الضريبة calculateTax أو processData أو doThing، والكود سيُرجم في الحالات الثلاث. هذه الحرية الكاملة هي مصدر الصعوبة: لا توجد إجابة “صحيحة” يفرضها المترجم، بل إجابة “أوضح” يفرضها القارئ.

تغيير الاسم لاحقًا مكلف

قيل إن جزءًا من صعوبة التسمية هو أن إعادة التسمية صعبة، لذا من الأفضل تسمية الشيء بشكل صحيح من المرة الأولى. صحيح أن أدوات إعادة الهيكلة الحديثة جعلت إعادة التسمية أسهل تقنيًا، لكنها لا تحل المشكلة المعرفية: أنت ما زلت بحاجة إلى معرفة الاسم الأفضل، وقد لا تعرف الاسم “الحقيقي” للشيء إلا بعد أن تفهمه بالكامل، وقد يحدث ذلك بعد شهور من كتابته.

ماذا تفعل الأسماء السيئة بالكود؟

الأسماء ليست تفصيلًا جماليًا. الأبحاث في هندسة البرمجيات تشير إلى أن المبرمجين يعتمدون على الأسماء لفهم الكود، وأن الأسماء تعمل كـ “منارات” أثناء القراءة. وعندما تكون الأسماء سيئة، تزداد الحمل المعرفي ويتعثر التعاون.

الأرقام هنا مفيدة. في دراسة تجريبية شملت 72 مطورًا محترفًا، وجد الباحثون أن استخدام كلمات كاملة كأسماء معرفات أدى إلى زيادة سرعة اكتشاف العيوب بنسبة 19% مقارنة بالأسماء المكونة من حرف واحد أو اختصارات لا معنى لها[reference:9]. وفي سياق مراجعة الكود، تشير مصادر عملية إلى أن الأسماء الوصفية الكاشفة عن النية يمكن أن تقلل وقت المراجعة بنسبة 30–40%، وتغني عن كثير من التعليقات التفسيرية.

المشكلة لا تتوقف عند السرعة. الأسماء السيئة تخلق التباسًا دلاليًا: هل status يعني حالة الطلب أم حالة المستخدم؟ هل process() تعالج الدفع أم تتحقق من صحة البيانات؟ هذه الالتباسات تتراكم في الكود الكبير، وتجعل تتبع الأثر (traceability) صعبًا، وترفع احتمال الأخطاء.

التسمية الكاشفة عن النية: القاعدة الأولى

المبدأ الأكثر تكرارًا في أدبيات الكود النظيف هو أن الاسم يجب أن يكشف عن النية (intention-revealing). أي أن الاسم يجيب عن ثلاثة أسئلة: لماذا يوجد هذا الشيء؟ ماذا يفعل؟ وكيف يُستخدم؟ وإذا احتاج الاسم إلى تعليق ليشرحه، فالمشكلة في الاسم نفسه.

لنأخذ مثالًا بسيطًا. الدالة التالية تعمل، لكن اسمها لا يكشف عن نيتها:

// اسم غامض: ماذا تعني process؟ ماذا تُرجع؟
function process($data) {
    $result = [];
    foreach ($data as $item) {
        if ($item['status'] === 'expired') {
            $result[] = $item;
        }
    }
    return $result;
}

بعد إعادة التسمية، يقرأ القارئ الدالة دون تعليق:

// اسم كاشف عن النية: ماذا تفعل الدالة وما الذي تُرجعه
function findExpiredSubscriptions(array $subscriptions): array {
    return array_filter(
        $subscriptions,
        fn ($subscription) => $subscription->isExpired()
    );
}

لاحظ أن الدالة الثانية لا تحتاج إلى تعليق. الاسم نفسه صار شرحًا. هذا هو المعيار العملي: إذا احتجت إلى كتابة تعليق يشرح ماذا يفعل المتغير أو الدالة، فغالبًا لديك فرصة لتحسين الاسم بدلًا من إضافة تعليق.

أنماط تسمية سيئة شائعة

معظم مشاكل التسمية لا تأتي من الجهل، بل من أنماط متكررة تترسخ في العادات. الجدول التالي يلخص أكثرها شيوعًا.

النمط السيئ مثال المشكلة البديل الأفضل
أسماء عامة جدًا data، info، manager لا تحمل أي معلومة عن المحتوى pendingInvoices، retryPolicy
حروف أو اختصارات بلا معنى x، tmp، proc تفرض على القارئ تخمين المعنى remainingAttempts، parsedResponse
اسم يصف النوع لا الغرض stringList، integerValue يكرر ما يعرفه المحرر، ولا يشرح الدور failedValidationMessages
اسم سلبي أو مزدوج النفي notDisabled، isNotInvalid يزيد الحمل الذهني عند الشرط isEnabled، isValid
اسم لا يطابق السلوك getUser() لكنها تنشئ مستخدمًا تضليل صريح يسبب أخطاء getOrCreateUser()
اسم عام يخفي مسؤوليات متعددة handle()، process() يجمع أفعالًا لا علاقة لها ببعضها تقسيم الدالة وتسمية كل جزء بفعله

قواعد عملية للتسمية في العمل اليومي

لا تحتاج إلى حفظ قائمة طويلة. هذه القواعد الست تغطي معظم الحالات اليومية:

  • اجعل الاسم يجيب عن “لماذا” و“ماذا” قبل “كيف”. calculateShippingCost أفضل من loopOverItemsAndSum.
  • استخدم كلمات كاملة، لا اختصارات غامضة. البحث في الكود يصبح أسهل، والقراءة أسرع، كما رأينا في نتائج الدراسة التجريبية.
  • اجعل طول الاسم متناسبًا مع اتساع النطاق. i مقبول كعدّاد حلقة قصيرة، لكنه غير مقبول لمتغير يُستخدم عبر مئات الأسطر.
  • لا تخفِ نوع البيانات في الاسم. userList أو userMap قد يكون مفيدًا إذا كان النوع جزءًا من العقد، لكن لا تجعل النوع هو المعنى الوحيد.
  • حافظ على الاتساق داخل المشروع. إذا اخترت fetch للشبكة، فلا تخلطها مع get أو retrieve لنفس المعنى في نفس الطبقة.
  • اعتبر إعادة التسمية جزءًا من إعادة الهيكلة. عندما تكتشف الاسم الحقيقي للشيء، أعِد تسميته فورًا، ولا تترك الاسم القديم “لأنه يعمل”.

لماذا يستهلك فهم كود الآخرين معظم وقتك؟

إذا كانت التسمية صعبة، فإن قراءة كود كتبه شخص آخر (أو أنت قبل سنة) أصعب. والسبب ليس أن الكود “سيئ” بالضرورة، بل لأن نظرية النظام لا تعيش في الكود وحده. بيتر ناور قال في 1985 إن البرنامج ليس شيفرته المصدرية؛ النظرية العاملة للنظام تعيش في أذهان من بنوه، ولا يمكن إعادة بنائها من الكود والتوثيق وحدهما. أنت لا تستطيع “قراءة” النظرية، بل تعيد بناءها بالتخمين والتحقق.

هذا يفسر لماذا يشعر المطورون الجدد أن قراءة الكود أبطأ من الكتابة. إنهم لا يقرأون فقط؛ إنهم يبنون خريطة ذهنية، ويختبرون فرضيات، ويصححون فهمًا خاطئًا. وكلما كانت الأسماء سيئة، زادت تكلفة هذه العملية.

استراتيجيات عملية لقراءة كود غير مألوف

لا تبدأ من شجرة الملفات. هذه نصيحة تتكرر في الأدلة العملية: ابدأ من نقاط الدخول (main، جدول المسارات، أوامر CLI)، ومن إعدادات البناء والنشر، لا من مجلد src/utils. شجرة الملفات قرار أرشفة، وليست تصميمًا.

اتبع طلبًا واحدًا من البداية إلى النهاية

اختر سلوكًا حقيقيًا يطلقه المستخدم أو نظام آخر، وتتبعه عبر كل طبقة يلمسها: نقطة الدخول، التوجيه، التحقق، طبقة الخدمة، الوصول إلى البيانات، الاستدعاءات الخارجية، الاستجابة. هذا الشريحة العمودية يعلمك التقسيم الطبقي ومعالجة الأخطاء واصطلاحات التسمية بالترتيب الذي يهم.

اقرأ الاختبارات لتفهم السلوك المقصود

الاختبارات الجيدة توثق السلوك المتوقع بلغة قابلة للتنفيذ. عندما لا تفهم دالة، ابحث عن اختبار يستدعيها. وإذا لم تجد، فهذه معلومة مفيدة بحد ذاتها: هذه المنطقة غير محمية، وتحتاج إلى حذر أكبر.

استخدم تاريخ Git لفهم “لماذا”

git blame وgit log لا يخبرانك فقط من كتب السطر، بل غالبًا لماذا كُتب. ابحث عن الـ commit الذي أدخل التعقيد، واقرأ رسالته. كثير من الأكواد “الغريبة” كانت استجابة لمتطلب أو خطأ لم يعد ظاهرًا في الكود الحالي.

لا تحفظ الكود، بل اطرح أسئلة عليه

اقرأ لتجيب عن أسئلة محددة: أين تُنشأ هذه القيمة؟ من يعدلها؟ ما الذي يحدث إذا فشل هذا الاستدعاء؟ دوّن الأسئلة، وأجب عنها بالتجربة أو بالقراءة، لا بالافتراض.

التعامل مع الكود القديم: اختبارات التوصيف ونقاط الالتحام

الكود القديم يضاعف المشكلة: غالبًا لا توجد اختبارات، والتوثيق قديم أو مضلل، والمؤلف الأصلي غادر. في هذه الحالة، لا تبدأ بالتعديل. ابدأ بتثبيت السلوك الحالي.

اختبارات التوصيف (characterization tests) هي اختبارات تكتبها لتصف ما يفعله الكود الآن، لا ما تعتقد أنه يجب أن يفعله. الغرض منها إنشاء شبكة أمان قبل أي تغيير. أما نقاط الالتحام (seams) فهي أماكن في الكود يمكنك تغيير السلوك عندها دون تعديل الكود نفسه، مثل استخراج دالة أو حقن واجهة، لتمكين الاختبار أو العزل.

القاعدة العملية: لا تخلط إعادة الهيكلة مع إضافة ميزة جديدة في نفس التغيير. ثبّت السلوك أولًا، ثم أعد الهيكلة، ثم أضف الميزة. هذا الفصل يجعل كل خطوة قابلة للمراجعة والتراجع.

الأدوات والذكاء الاصطناعي في فهم الكود

أدوات الذكاء الاصطناعي التوليدي أصبحت جزءًا عمليًا من فهم الأكواد القديمة، لا مجرد تجربة. تشير تقييمات 2025 إلى أن أدوات مثل Cursor وClaude Code وCopilot وWindsurf وAider وCody وSwimm تساعد المطورين على إظهار قواعد العمل، وتلخيص المنطق، وتحديد التبعيات، وتقليل الوقت اللازم لفهم الأنظمة الكبيرة.

لكن الأدوات لا تغني عن الفهم. الاستخدام الفعال لها يكون بأسئلة محددة: “أين تُنشأ هذه القيمة؟”، “ما المسار الذي يسلكه هذا الطلب؟”، “أي الملفات تعتمد على هذه الدالة؟”. الأسئلة العامة مثل “اشرح لي هذا المشروع” تعطي إجابات سطحية. والأهم: تحقق من الإجابة في الكود. الأداة تقترح، وأنت تتحقق.

المهمة ما تفعله الأداة ما يجب أن تفعله أنت
تحديد نقطة الدخول تقترح ملفات main والمسارات تشغّل التطبيق وتتحقق
تلخيص منطق دالة تنتج شرحًا نصيًا تقارن الشرح بالكود وتختبر الحالات الحدية
تتبع التبعيات ترسم خريطة استدعاءات تتحقق من التبعيات الديناميكية والحقن
اقتراح إعادة تسمية تقترح أسماء بديلة تختار الاسم الذي يعكس نية الفريق

ممارسات الفريق التي تقلل المعاناة

المشكلة ليست فردية فقط. الفريق الذي يهمل التسمية وقراءة الكود يدفع الثمن في كل دورة تطوير. هذه الممارسات تخفض التكلفة:

  • مراجعة الكود بتركيز على الأسماء. اجعل “هل هذا الاسم يكشف النية؟” سؤالًا ثابتًا في كل مراجعة.
  • اصطلاحات تسمية مكتوبة ومُطبَّقة آليًا. لا تترك التنسيق للأذواق؛ استخدم أدوات التحليل الساكن لفرض الاصطلاحات.
  • توثيق القرارات المعمارية. سجل قرار التصميم (ADR) يشرح “لماذا”، ويوفر على القارئ ساعات من التخمين.
  • اختبارات كأدب. الاختبارات الواضحة التسمية توثق السلوك وتقلل الحاجة إلى الشرح الشفهي.
  • خصص وقتًا للقراءة. إذا كان 58% من الوقت يذهب إلى الفهم، فالفريق يحتاج إلى ممارسات تجعل هذا الوقت منتجًا، لا إلى تجاهله.

قائمة تحقق نهائية

  • هل الاسم يجيب عن “لماذا” و“ماذا” قبل “كيف”؟ ← أعِد التسمية حتى يجيب
  • هل تحتاج إلى تعليق ليشرح الاسم؟ ← الاسم هو المشكلة، لا التعليق
  • هل تبدأ قراءة كود جديد من شجرة الملفات؟ ← ابدأ من نقاط الدخول والبناء
  • هل تتبعت طلبًا واحدًا كاملًا قبل الحكم على التصميم؟ ← الشريحة العمودية أولًا
  • هل توجد اختبارات تحمي السلوك الحالي قبل التعديل؟ ← اكتب اختبارات توصيف أولًا
  • هل تستخدم أداة ذكاء اصطناعي دون التحقق من إجابتها؟ ← تحقق دائمًا في الكود
  • هل تخلط إعادة الهيكلة مع الميزات الجديدة؟ ← افصل التغييرات دائمًا

فيما يلي روابط يمكنك الرجوع إليها لفهم أعمق للموضوع:

أسئلة شائعة

هل التسمية الجيدة تبطئ التطوير في البداية؟

قد تستهلك دقائق إضافية عند الكتابة، لكنها توفر ساعات في المراجعة والصيانة. الأرقام تشير إلى أن الأسماء الوصفية تقلل وقت المراجعة بنسبة 30–40%، وتزيد سرعة فهم الكود بنسبة 19% على الأقل. الاستثمار صغير والعائد تراكمي.

هل الأسماء القصيرة أفضل دائمًا؟

لا. القِصر مفيد فقط عندما يكون النطاق ضيقًا جدًا والاسم واضحًا من السياق، مثل i في حلقة قصيرة. في النطاقات الأوسع، الكلمات الكاملة تتفوق لأنها تحمل معلومات أكثر وتقلل الالتباس.

هل يمكن الاعتماد على الذكاء الاصطناعي لفهم الكود بدلًا من القراءة؟

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

ما أول خطوة عند استلام كود قديم بلا اختبارات؟

شغّل التطبيق محليًا، وحدد نقاط الدخول، ثم اكتب اختبارات توصيف للسلوك الحالي قبل أي تعديل. لا تبدأ بإعادة الهيكلة قبل أن يكون لديك شبكة أمان.

هل صعوبة التسمية مشكلة خبرة أم مشكلة لغة؟

هي مشكلة تواصل بشري قبل أن تكون مشكلة لغة. المبتدئ والخبير يواجهانها، لكن الخبير يكون قد بنى حساسية للسياق ونية القارئ. الممارسة والمراجعة المنتظمة تحسنانها أكثر من أي شيء آخر.