اختلال الشيفرات ومشاكلها (Code Smells)
قد تعاني الشيفرات الكثير من الاختلالات والمشاكل الشكلية؛ فبمجرد اكتشاف تلك الاختلالات الظاهرية، يسهل علينا معرفة العلاج (التقنيات) وتطبيقه (إعادة التصميم) للحصول على شيفرة سليمة نظيفة. من هذه الاختلالات:
المبالغة والإطالة
قد يزداد حجم الشيفرات والتوابع (methods) والأصناف (classes) ازديادًا كبيرًا ليصل لمرحلةٍ يصعُب التعامل معها، ولا يحدث هذا بشكلٍ فجائيِّ دفعةً واحدةً، بل يكون ناتجًا عن تراكم الإضافات أثناء تطوير البرنامج (وخاصةً عندما لا يبذل أحدٌ جهدًا للحدِّ من ذلك التشعب)، ويبدو هذا التضخم واضحًا
- التوابع الطويلة (long methods): لاحتوائها على أسطر كثيرةٍ من الشيفرة، إذ لا يُفضَّل أن تزيد عن 10 أسطر.
- الأصناف الواسعة (large classes): والتي تحتوي على عددٍ كبيرٍ من الحقول (fields) والتوابع (methods) وبشيفرةٍ طويلةٍ.
- هوس الحقول الأساسيّة (primitives obsession): مثل الثوابت (constants) لتشفير المعلومات أو الثوابت النصيّة (string constants) لاستخدامها كأسماء للحقول (fields) في المصفوفات.
- المعاملات الكثيرة في التوابع (long parameter list): عندما تزيد على 3 أو 4 معاملات لنفس التابع.
- البيانات المُجمَّعة (data clumps): عندما تتكرَّر مجموعةٌ من المتغيِّرات بشكلٍ متطابقٍ تمامًا في عدة أجزاء من الشيفرة.
الاستخدام الخطأ لمبادئ البرمجة كائنية التوجه
من مشاكل الشيفرات أيضًا التطبيقُ الخطأ وغير المكتمل لمبادئ البرمجة كائنية التوجّه (Object-Oriented)، مثل:
- استخدام الأصناف البديلة (alternative) ذات الواجهات (interfaces) المختلفة: كأن يكون لصنفين المهمة (function) نفسها ولكن بأسماء مختلفة لتوابعهما (methods).
- الوراثة الفائضة (refused bequest): عندما يستفيد الصنف الفرعيّ (subclass) من القليل (والقليل فقط) ممّا ورثه عن الصنف الأعلى (superclass).
- الشكل المعقَّد لتعليمة switch: بشكلٍ معقّد للغاية، أو لدى استخدام تعليمات if بشكل متتابعٍ متداخل.
- الحقول المؤقّتة (temporary fields): والتي لن تُستخدَم إلّا في حالاتٍ معيّنة، وتبقى فارغةً فيما سواها.
عرقلة التغيير
قد يكون تطوير بعض الشيفرات مشكلةً حقيقيةً إذ عند إحداث أيّ تغييرٍ في جزءٍ منها لا بُدَّ وأن تتبعه عدّة تغييراتٍ أخرى في أجزاء متفرِّقة، وبالتالي سيصبح تطوير البرنامج شائكًا معقّدًا وبتكلفةٍ غير زهيدةٍ، من معوِّقات التغيير:
- التغيير المتشعِّب (divergent change): والحاجة لتغيير الكثير من التوابع التي لا علاقة لها بالأمر بمجرد تغيير أيّ جزءٍ في الصنف (class).
- الهيكليّة التفرعيّة للوراثة (parallel inheritance hierarchies): فتجد نفسك عند إنشاء صنفٍ فرعيٍّ (لأحد الأصناف) بحاجةٍ لإنشاء صنفٍ فرعيٍّ ثانٍ لصنفٍ آخر غيره.
- تغيير الأصناف المتعدِّدة (shotgun surgery): إذ يقتضي تعديلُ صنفٍ ما إجراءَ بعض التعديلات البسيطة على عدِّة أصناف أخرى.
الأجزاء الفائضة
وهي الأجزاء عديمة النفع في الشيفرة، وسيجعلُ التخلُّصُ منها الشيفرةَ نظيفةً يسيرة الفهم وأكثر فعاليّة، منها:
- التعليقات (comments): والتي تتمثّل بالشرح الزائد الذي لا طائل منه.
- تكرار الشيفرة (duplicates): بشكل متطابقٍ تمامًا في موقعين مختلفين.
- أصناف البيانات (data classes): التي تحتوي على حقول البيانات (data fields) وبعض التوابع (methods) للوصول إليها وحسب.
- الشيفرة الميتة (dead code): كافّة المتغيِّرات (variables) أو المعاملات (parameters) أو الحقول (fields) أو التوابع (methods) أو الأصناف (classes) التي لم يعْد هنالك حاجةٌ لها فيما بعد ولن تُستخدَم مطلقًا ولكنها لا زالت موجودة.
- الأصناف الخاملة (lazy classes): التي ليست بأهمية بالنسبة للبرنامج، إذ لكلِّ الأصناف متطلباتٌ دوريّةٌ من ناحية الزمن والتكلفة.
- الخيال البرمجيّ (speculative generality): الذي يكون السبب بإنشاء الأصناف (classes) أو التوابع (methods) أو الحقول (fields) أو المعاملات (parameters) التي "قد" يحتاجها المبرمج مستقبلًا ولكنّها غير مستخدمةٍ بالوقت الحاليّ.
الروابط الازدواجية
يتلخّص هذا الجانب بعواقب إنشاء رابطٍ شديدٍ ازدواجيّ (ما بين صنفين [classes])، أو قد تظهر بدائل عنه كالتفويض المفرط (excessive delegation)، وتتمثل هذه المشكلة بالنقاط الآتية:
- التسلط على الكائنات الأخرى (feature envy): فقد تستخدم بعض التوابع (methods) بيانات الكائنات الأخرى أكثر مما تستخدم بياناتها ذاتها!
- الارتباط الوثيق غير المناسب (inappropriate intimacy): عند استخدام أحد الأصناف للحقول (fields) والتوابع (methods) الداخليّة لصنف آخر بكثرة.
- سلاسل الرسائل (message chains): وهي عدّة استدعاءاتٍ متسلسلةٍ مثل الشيفرة:
$a->b()->c()->d()
. - الوسيط (middle man): عندما يكون للصنف (class) مهمةٌ واحدةٌ فقط وهي تفويض المهام (delegation) لصنفٍ آخر. فما أهمية وجوده بالأصل؟
اختلالات ومشاكل أخرى
ستجد في هذا القسم الاختلالات والمشكلات التي لا تنحصر في صنف محدَّد.
- أصناف المكتبة غير الكافية (Incomplete Library Classes): لا تلبِّي أصناف المكتبة (library classes) كافّة احتياجات البرنامج مع استمرار تطوُّره، ولا يمكن تعديلها لأنّها مُخصَّصةٌ للقراءة فقط (read-only). ويكمن حل هذه المشكلة في تعريف التوابع الدخيلة أو تعريف الإضافات المحليّة.