شرح روائح الكود

تاريخ النشر 13 يوليو 2026
لقطة مقربة للغاية لوجه رجل غاضب
By Dave Bergmann

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

ابتكر Kent Beck مصطلح Code Smell، ثم شاع استخدامه بعد صدور الكتاب المرجعي عام 1999، الذي شارك في تأليفه مع Martin Fowler،" Refactoring: Improving the Design of Existing Code وتحديدًا في الفصل المعنون Bad Smells in Code. ويصف Martin Fowler روائح الشفرة البرمجية بإيجاز بأنها: "مؤشر سطحي يدل غالبًا على وجود مشكلة أعمق داخل النظام.1

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

بالنسبة لمهندس برمجيات متمرس، فإن بعض الأنماط في التعليمات البرمجية لا تبدو "صحيحة" ببساطة. وبمرور الوقت ، قد يربط المرء غريزيًا وجودها ببعض التعقيدات أو أوجه القصور أو المشكلات المستقبلية. إن تسمية ونشر روائح الكود المحددة يسهل التعرف على هذه الأنماط غير المنتجة (أو "الأنماط المضادة") ومبادئ التصميم التي تنتهكها. هذه الألفة بدورها تجعل هذه الأنماط المضادة أكثر احتمالا للملاحظة ومعالجتها أثناء تقييم الكود. وكما يوضح Martin Fowler: "الرائحة، بحكم تعريفها، شيء يسهل اكتشافه ."أو استشعاره ".

وتُسهم روائح الشفرة البرمجية، إذا تُرِكت دون معالجة، إسهامًا كبيرًا في تراكم الدين التقني. وتشير إحدى الدراسات إلى أن 75% من العيوب التي تُكتشف أثناء تقييم الكود لا تؤثر في تنفيذ البرنامج، ولكنها "تؤثر في قابلية البرمجيات للتطور".2 وحتى إذا لم يتسبب نمط برمجي غير مرغوب أو عادة برمجية سيئة في حدوث خطأ اليوم، فإنه يزيد بدرجة كبيرة احتمال ظهور أخطاء، أو أعطال أو ثغرات أمنية في قاعدة الكود مستقبلًا . وفي الحد الأدنى، يؤدي وجود روائح معروفة في الكود إلى تقليل سهولة قراءتها وصيانتها، ويزيد صعوبة فهمها، وتحديثها، وتحسينها.

أنواع روائح الكود

ورغم أن كثيرًا من روائح الكود الشائعة ما زالت تحمل الأسماء التي وضعها Kent Beck وMartin Fowler في كتاب Refactoring فلا توجد قائمة معيارية واحدة تحظى بقبول عالمي لهذه الروائح. كما أن الخلاف حول تسمية رائحة معينة، أو تصنيفها نمطًا غير مرغوب مستقلًا بدلًا من اعتبارها نوعًا فرعيًا من نمط آخر، لا يحمل أهمية كبيرة. فالأهم أن يكون اسم رائحة الكود ووصفها واضحين وسهلَي الفهم بما يساعد فرق تطوير البرمجيات على تبادل مبادئ التصميم الجيدة وتطبيقها بفاعلية.

وبالمثل، لا يوجد تصنيف موحد يحظى بإجماع عالمي لفئات روائح الشفرة البرمجية المختلفة. تعتمد هذه المقالة أساسًا على التصنيف الذي اقترحه Jerzyk وMadeyski عام 2023.3 ونُشرت نتائجهما في الدليل المرجعي الذي يديره موقع codesmells.org، والذي يوفر معلومات إضافية، وأمثلة على الكود، وأساليب مناسبة لإعادة الهيكلة (Refactoring) لكل نوع من روائح الكود.

ويشير Jerzyk وMadeyski إلى أن أكثر تصنيفات روائح الكود شيوعًا يستند إلى المجموعات الخمس التي اقترحها Mäntylä وLassenius عام 2006، إذ صنفا 22 نوعًا من روائح الكود التي قدمها Fowler وBeck، (إلى جانب نوع إضافي من اقتراحهما)، ضمن خمس فئات رئيسية هي: Bloaters, Object-Orientation Abusers, Change Preventers, Dispensables و Couplers.4 وبعد مراجعة شاملة للأدبيات المنشورة رسميًا، إلى جانب الأدبيات غير الرسمية (Grey Literature) (مثل المدونات، والمنتديات، والويكي)، صنف Jerzyk وMadeyski 56 نوعًا مختلفًا من روائح الكود ضمن تسع فئات، تشمل الفئات الخمس المذكورة سابقًا.

ورغم أن هذا القسم يتبع في معظمه البنية المكونة من تسع فئات التي اقترحاها، فمن المهم الإشارة إلى أن هذه التصنيفات غير رسمية وتعتمد على الاجتهاد الشخصي. لذا، يبقى التصنيف الأكثر فائدة هو التصنيف الذي تجده الأكثر وضوحًا وسهولة في الفهم. كما أن فهم أنواع المشكلات أو أوجه القصور التي قد تُحدثها روائح الكود يمنح تصورًا أعمق لها مقارنةً بحفظ أسمائها دون استيعاب معناها."**⁵ وكما يوضح Mäntylä: "عند التعامل مع قائمة طويلة ومسطحة من روائح الكود، يسهل فقدان الصورة الكاملة."5

مضخمات الكود Bloaters

تشير مضخمات الكود Bloaters إلى روائح الكود التي تؤدي غالبًا إلى تضخم الأساليب (Methods)، أو الفئات (Classes)، أو كتل الكود، حتى تصبح كبيرة ومعقدة ويصعب التعامل معها. ويقلل ذلك من سهولة قراءة الكود، ويزيد صعوبة صيانته أو تعديله.

تشمل أمثلة Bloaters ما يلي:

  • تجمعات البيانات: مجموعات من المتغيرات التي تظهر معًا بشكل متكرر في كل مكان.

  • فئة كبيرة: فئة تحاول القيام بالكثير من المتغيرات وتحتوي على عدد كبير جدًا من المتغيرات، وتفتقر إلى التماسك.

  • دالة طويلة (طريقة طويلة): طريقة تحتوي على عدد كبير جدًا من أسطر التعليمات البرمجية.

  • قائمة معلمات طويلة: الدوال التي تتطلب الكثير من الوسيطات لتعمل بشكل صحيح.

  • الهوس البدائي: استخدام أنواع البيانات البدائية بدلاً من الكائنات الصغيرة المتخصصة.

عوامل منع التغيير Change preventers

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

وتنتهك هذه الأنواع من روائح الكود مبدأ المسؤولية الفردية (SRP) الذي وضعه Robert C. Martin، والذي ينص على أن التغييرات التي تطرأ على أي وحدة برمجية يجب أن تنبع من سبب واحد فقط. وكما يوضح Martin في إحدى تدويناته حول هذا المبدأ: "اجمع العناصر التي تتغير للأسباب نفسها. وافصل العناصر التي تتغير لأسباب مختلفة.6

تتضمن أمثلة أدوات معوقات التغيير Change Preventers ما يلي:

  • الجراحة العشوائية Shotgun surgery: يتطلب تنفيذ تغيير واحد إجراء تعديلات متزامنة في عدد كبير من الوحدات البرمجية المتفرقة (وهو عكس مشكلة Large Class تقريبًا).

  • التغيير المتباين Divergent change: على النقيض من Shotgun surgery، يتطلب تنفيذ تغيير واحد إجراء عدد كبير من التعديلات داخل فئة (Class) واحدة.

  • فوضى دوال الاستدعاء Callback hell: بنية كود تتداخل فيها أساليب عديدة داخل بعضها بعضًا عبر مستويات متعددة من الإزاحة والأقواس المعقوفة، مما يحجب العلاقة بين السبب والنتيجة، ويجعل قراءة الكود وصيانته أكثر صعوبة.

مسببات الاقتران Couplers

تشير مسببات الاقتران Couplers إلى روائح الكود التي تنتهك المبدأ التصميمي القائم على ضعف الاقتران من خلال إنشاء اعتماديات مفرطة بين الفئات المختلفة. ويقلل ذلك من قابلية إعادة استخدام الكود، ويعقد اختبار الوحدات المستقل (أو يمنعه بالكامل).

تشمل أمثلة مسببات الاقتران Couplers ما يلي:

  • التطفل على الخصائص Feature envy: يعتمد أحد الأساليب بصورة مفرطة على بيانات كائن (Object) آخر.

  • التطفل الداخلي Insider trading (المعروف أيضًا باسم الألفة غير المناسبة): تستخدم إحدى الفئات الحقول أو الأساليب الداخلية لفئة أخرى.

  • سلاسل الاستدعاءات Message chains: سلسلة طويلة من استدعاءات الأساليب المترابطة بين الكائنات.

وسطاء البيانات Data dealers

وسطاء البيانات Data dealers تمرير البيانات عبر عدد من الفئات أو الدوال يفوق الحاجة الفعلية. وينتج عن ذلك اعتماديات غير ضرورية، وتعقيد إضافي، كما يؤدي غالبًا إلى عناصر برمجية يقتصر دورها على الاحتفاظ بالبيانات أو تمريرها دون توفير أي سلوك وظيفي ذي قيمة.

تتضمن أمثلة وسطاء البيانات ما يلي:

  • الوسيط Middle man: فئة يقتصر دورها على تفويض العمليات إلى فئات أخرى.

  • البيانات العابرة Tramp data: انتقال البيانات عبر سلسلة من الأساليب التي لا تستخدمها مطلقًا، وكأنها "تتنقل بالمجان".

  • البيانات العامة Global data: بنية تسمح بتعديل المتغيرات من أي موضع داخل قاعدة الكود، مما يجعل جميع الدوال موضع اشتباه عند حدوث أي خلل.

العناصر القابلة للاستغناء Dispensables

العناصر القابلة للاستغناء Dispensables هي، عناصر الكود التي يمكن الاستغناء عنها، إذ يؤدي حذفها إلى جعل قاعدة الكود أكثر نظافة وأسهل قراءة دون تأثير يُذكر في الوظائف الأساسية.

تتضمن أمثلة العناصر القابلة للاستغناء ما يلي:

  • التعليقات Comments: تمثل التعليقات ممارسة جيدة في معظم الحالات، لكنها تُستخدم أحيانًا بوصفها "مزيلًا للروائح" (Deodorant) لروائح الكود، فتكتفي بشرح المشكلة بدلًا من تحسين الكود نفسه. على سبيل المثال، إذا وصف تعليق ما يحدث في قسم معين من الكود، فإنه يُستخدم لإخفاء حقيقة أن الكود لا يتمتع بالوضوح أو سهولة القراءة الكافيين بمفرده. وقد تصبح التعليقات الفردية أيضًا زائدة عن الحاجة أو قديمة بمرور الوقت. وتندرج سلوكيات أكثر تحديدًا للتعليقات ضمن أنواع أخرى من روائح الكود.

  • فئة البيانات Data class: فئات تحتوي على حقول وأساليب وصول (Accessors) فقط، وتفتقر إلى أي سلوك وظيفي ذي معنى..

  • الكود المهمل Dead code: عناصر كود لم تعد تُنفَّذ لأن إعادة الهيكلة والتعديلات الأخرى جعلتها غير مستخدمة.

  • الكود المكرر Duplicate code: هياكل كود متطابقة أو متشابهة جدًا تتكرر في مواضع متعددة.

  • الفئة قليلة الاستخدام Lazy class (المعروفة أيضا بالعناصر قليلة الاستخدام): فئات أو دوال تؤدي قدرًا ضئيلًا جدًا من العمل لا يبرر وجودها.

  • التعميم الاستباقي Speculative generality: كود غير ضروري أُضيف لدعم ميزات مستقبلية افتراضية.

مسيئو استخدام البرمجة الوظيفية Functional abusers

يُشير مسيئو استخدام البرمجة الوظيفية Functional abusers إلى روائح الكود التي تتجاهل مبادئ البرمجة الكائنية التوجه من خلال فرض أنماط البرمجة الوظيفية داخل قاعدة كود كائنية التوجه.

تشمل أمثلة Functional abusers ما يلي:

  • الحلقاتLoops: استخدام الحلقات التقليدية بدلًا من عمليات مسارات المعالجة (Pipeline Operations) الحديثة. ورغم أن Fowler عدَّ معظم الحلقات أسلوبًا قديمًا، يرى Jerzyk أن الحلقات الإمْرية (Imperative Loops)، تمثل المشكلة الأساسية.

  • البيانات المتغيرة Mutable data: متغيرات تتغير حالتها على نحو غير متوقع، مما يؤدي إلى آثار جانبية يصعب التنبؤ بها.

  • الآثار الجانبية (أو الدوال غير النقية impure functions): أساليب تنفذ مهامًا تتجاوز ما يوحي به اسمها أو غرضها الأساسي.

مسيئو الاستخدام اللغوي Lexical abusers

مسيئو الاستخدام اللغوي Lexical abusers هم روائح الكود الناتجة عن ضعف قواعد التسمية، أو عدم اتساق التنسيق، أو استخدام بناء نحوي غامض. وبعبارة أخرى، هي حالات لا تعكس فيها صياغة الكود سلوكه الفعلي بصورة واضحة، مما يضعف سهولة قراءته.

تشمل أمثلة Lexical abusers ما يلي:

  • الرقم السحري Magic number: أرقام تُدرج في الكود دون اسم أو شرح أو سياق كافٍ.

  • التعليق المضلل Fallacious comment: تعليقات لم تعد صحيحة لأن الكود المحيط بها تغيّر. ونظرًا إلى أن التعليقات لا تُنفَّذ، فإن أدوات فحص الكود Linters وغيرها من أدوات التحقق الآلية غالبًا لا تكتشفها.

  • الاسم الغامض Mysterious name: دوال أو متغيرات تحمل أسماء غير معبرة تخفي الغرض الحقيقي منها.

  • اسم الطريقة المضلل Fallacious method name: دوال تحمل أسماء مضللة تخالف الأعراف والتوقعات الشائعة. فعلى سبيل المثال، دالة باسم getSomething لا تُرجع أي قيمة.

عناصر التعتيم Obfuscators

عناصر التعتيم هي عناصر كود كُتبت بأسلوب معقد أو متشابك أو "ذكي" على نحو غير ضروري، مما يخفي الغرض الحقيقي للكود خلف مستويات غير لازمة من التجريد (Abstraction). وتجعل روائح الكود هذه الشفرة المصدرية صعبة القراءة، وتزيد صعوبة فهمها وتعديلها مستقبلًا.

تشمل أمثلة Obfuscators ما يلي:

  • الفصل الرأسي Vertical separation: وجود مسافات كبيرة غير ضرورية بين عناصر الكود المرتبطة، مثل تعريف متغير في بداية أحد الأساليب وعدم استخدامه إلا بعد خمسين سطرًا.

  • الغرض المُعتَّم Obscured intent: فئة عامة تضم الدوال، والمتغيرات، والأسماء، والأرقام التي لا يكون الغرض منها واضحًا أو مفهومًا من السياق.

  • التعبير المنطقي البولياني المعقد (Complicated Boolean Expression): تدفقات منطقية معقدة ومتشابكة، مثل تلك التي تتضمن نفيًا مزدوجًا أو سلاسل منطقية معقدة من IF و IF NOT و AND و AND NOT .IF NOT

  • الكود الذكي Clever code: هو كود يعمل بصورة صحيحة، لكنه يستخدم أساليب معقدة أو غير مألوفة بدلًا من الاعتماد على الحلول القياسية والمفهومة على نطاق واسع.

مسيئو استخدام البرمجة كائنية التوجه Object-oriented abusers

مسيئو استخدام البرمجة كائنية التوجه Object-oriented abusers أو (Object-orientation abusers) هم روائح الكود التي لا تطبق مبادئ التصميم كائني التوجه تطبيقًا كاملًا أو صحيحًا. فعلى سبيل المثال، تُعد عبارات التبديل switch مفيدة في البرمجة الإجرائية، لكن يُفضل تجنبها في البرمجة كائنية التوجه.

تشمل أمثلة Object-oriented abusers ما يلي:

  • فئة بديلة ذات واجهات مختلفة Alternative class with different interfaces: فئات تؤدي وظائف متشابهة، لكنها تستخدم أسماء أساليب مختلفة تمامًا.

  • الوراثة المرفوضة Refused bequest: فئات فرعية لا تحتاج إلى الأساليب الموروثة أو لا تستخدمها.

  • تعليمات switch (ويُعرف أيضًا باسم Conditional Complexity أو Repeated Switches): تكرار عبارة switch نفسها في مواضع متعددة داخل قاعدة الكود.

  • حقل مؤقت Temporary field: متغير يُنشأ في مواضع لا تستدعي وجوده غالبًا، ولا يُستخدم إلا في حالات محددة.

إعادة هيكلة روائح الكود Refactoring code smells

تكمن الفائدة الأساسية من فهم روائح الكود في أن التعرف إليها يساعد على تنفيذ إعادة الهيكلة Refactoring بكفاءة أكبر، وهي عملية تحديث الشفرة المصدرية دون تغيير سلوكها أو وظائفها الخارجية. ويُعد تحسين الكود بصورة دورية من خلال إعادة الهيكلة أمرًا ضروريًا للحد من الدَّين التقني (Technical Debt)، ولتسهيل إدخال التحسينات والإضافات بسرعة وكفاءة إلى قاعدة الكود مع مرور الوقت.

ويمكن النظر إلى إعادة الهيكلة على أنها عملية تحديد روائح الكود ومعالجتها. إذ تهدف إلى معالجة المشكلات قبل أن تؤثر سلبًا في وظائف البرمجيات. أما إذا بدأت المشكلات تؤثر في الوظائف، فإن العملية تصبح أقرب إلى تصحيح الأخطاء (Debugging) منها إلى إعادة الهيكلة.

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

مؤلف

Dave Bergmann

Senior Staff Writer, AI Models

IBM Think

حلول ذات صلة
IBM Bob

تسريع تسليم البرمجيات مع IBM Bob، شريكك المدعوم بالذكاء الاصطناعي للتطوير الآمن والمدرك للنية.

استكشف IBM Bob®
حلول الذكاء الاصطناعي للمطورين.

تطوير تطبيقات الذكاء الاصطناعي ونشرها وإدارتها بوتيرة أسرع باستخدام أدوات جاهزة للمؤسسات.

استكشِف حلول الذكاء الاصطناعي للمطورين.
خدمات تحديث التطبيقات

إعادة تصوُّر الأنظمة القديمة من خلال التحديث الذكي بالذكاء الاصطناعي.

استكشِف خدمات تحديث التطبيقات.
اتخِذ الخطوة التالية

الاستفادة من الذكاء الاصطناعي التوليدي والأتمتة المتقدمة لتقديم تعليمات برمجية جاهزة للمؤسسات بسرعة واتساق أكبر. تعزز نماذج Bob مهارات المطورين، ما يؤدي إلى تبسيط مسارات عمل التحديث ويجعل مهام التطوير المعقدة أكثر سهولة.

  1. اكتشِف وكيل البرمجة المدعوم بالذكاء الاصطناعي.
  2. استكشِف حلول الذكاء الاصطناعي للمطورين.