الفرق بين المراجعتين ل"Refactoring/smells"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
(إضافة قسم "مشكلات أخرى")
ط
 
(مراجعة متوسطة واحدة بواسطة نفس المستخدم غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:اختلال الشيفرات ومشاكلها (Code Smells)}}</noinclude>
+
قد تعاني الشيفرات الكثير من الاختلالات والمشاكل الشكلية؛ فبمجرد اكتشاف تلك الاختلالات الظاهرية، يسهل علينا معرفة العلاج (التقنيات) وتطبيقه (إعادة التصميم) للحصول على شيفرة سليمة نظيفة. من هذه الاختلالات:<noinclude>{{DISPLAYTITLE:اختلال الشيفرات ومشاكلها (Code Smells)}}</noinclude>
 
== [[Refactoring/smells/bloaters|المبالغة والإطالة]] ==
 
== [[Refactoring/smells/bloaters|المبالغة والإطالة]] ==
 
قد يزداد حجم الشيفرات والتوابع (methods) والأصناف (classes) ازديادًا كبيرًا ليصل لمرحلةٍ يصعُب التعامل معها، ولا يحدث هذا بشكلٍ فجائيِّ دفعةً واحدةً، بل يكون ناتجًا عن تراكم الإضافات أثناء تطوير البرنامج (وخاصةً عندما لا يبذل أحدٌ جهدًا للحدِّ من ذلك التشعب)، ويبدو هذا التضخم واضحًا
 
قد يزداد حجم الشيفرات والتوابع (methods) والأصناف (classes) ازديادًا كبيرًا ليصل لمرحلةٍ يصعُب التعامل معها، ولا يحدث هذا بشكلٍ فجائيِّ دفعةً واحدةً، بل يكون ناتجًا عن تراكم الإضافات أثناء تطوير البرنامج (وخاصةً عندما لا يبذل أحدٌ جهدًا للحدِّ من ذلك التشعب)، ويبدو هذا التضخم واضحًا
# '''[[Refactoring/long method|التوابع  الطويلة (long methods):]]''' لاحتوائها على أسطر كثيرةٍ من الشيفرة، إذ لا يُفضَّل أن تزيد عن 10 أسطر.
+
# [[Refactoring/long method|التوابع  الطويلة (long methods):]] لاحتوائها على أسطر كثيرةٍ من الشيفرة، إذ لا يُفضَّل أن تزيد عن 10 أسطر.
# '''[[Refactoring/large class|الأصناف الواسعة (large classes):]]''' والتي تحتوي على عددٍ كبيرٍ من الحقول (fields) والتوابع (methods) وبشيفرةٍ طويلةٍ.
+
# [[Refactoring/large class|الأصناف الواسعة (large classes):]] والتي تحتوي على عددٍ كبيرٍ من الحقول (fields) والتوابع (methods) وبشيفرةٍ طويلةٍ.
# '''[[Refactoring/primitive obsession|هوس الحقول الأساسيّة (primitives obsession):]]''' مثل الثوابت (constants) لتشفير المعلومات أو الثوابت النصيّة (string constants) لاستخدامها كأسماء للحقول (fields) في المصفوفات.
+
# [[Refactoring/primitive obsession|هوس الحقول الأساسيّة (primitives obsession):]] مثل الثوابت (constants) لتشفير المعلومات أو الثوابت النصيّة (string constants) لاستخدامها كأسماء للحقول (fields) في المصفوفات.
# '''[[Refactoring/long parameter list|المعاملات الكثيرة في التوابع (long parameter list):]]''' عندما تزيد على 3 أو 4 معاملات لنفس التابع.
+
# [[Refactoring/long parameter list|المعاملات الكثيرة في التوابع (long parameter list):]] عندما تزيد على 3 أو 4 معاملات لنفس التابع.
# '''[[Refactoring/data clumps|البيانات المُجمَّعة (data clumps):]]''' عندما تتكرَّر مجموعةٌ من المتغيِّرات بشكلٍ متطابقٍ تمامًا في عدة أجزاء من الشيفرة.
+
# [[Refactoring/data clumps|البيانات المُجمَّعة (data clumps):]] عندما تتكرَّر مجموعةٌ من المتغيِّرات بشكلٍ متطابقٍ تمامًا في عدة أجزاء من الشيفرة.
  
 
== [[Refactoring/smells/oo abusers|الاستخدام الخطأ لمبادئ البرمجة كائنية التوجه]] ==
 
== [[Refactoring/smells/oo abusers|الاستخدام الخطأ لمبادئ البرمجة كائنية التوجه]] ==
 
من مشاكل الشيفرات أيضًا التطبيقُ الخطأ وغير المكتمل لمبادئ البرمجة كائنية التوجّه (Object-Oriented)، مثل:
 
من مشاكل الشيفرات أيضًا التطبيقُ الخطأ وغير المكتمل لمبادئ البرمجة كائنية التوجّه (Object-Oriented)، مثل:
# '''[[Refactoring/alternative classes with different interfaces|استخدام الأصناف البديلة (alternative) ذات الواجهات (interfaces) المختلفة:]]''' كأن يكون لصنفين المهمة (function) نفسها ولكن بأسماء مختلفة لتوابعهما (methods).
+
# [[Refactoring/alternative classes with different interfaces|استخدام الأصناف البديلة (alternative) ذات الواجهات (interfaces) المختلفة:]] كأن يكون لصنفين المهمة (function) نفسها ولكن بأسماء مختلفة لتوابعهما (methods).
# '''[[Refactoring/refused bequest|الوراثة الفائضة (refused bequest):]]''' عندما يستفيد الصنف الفرعيّ (subclass) من القليل (والقليل فقط) ممّا ورثه عن الصنف الأعلى (superclass).
+
# [[Refactoring/refused bequest|الوراثة الفائضة (refused bequest):]] عندما يستفيد الصنف الفرعيّ (subclass) من القليل (والقليل فقط) ممّا ورثه عن الصنف الأعلى (superclass).
# '''[[Refactoring/switch statements|الشكل المعقَّد لتعليمة switch:]]''' بشكلٍ معقّد للغاية، أو لدى استخدام تعليمات if بشكل متتابعٍ متداخل.
+
# [[Refactoring/switch statements|الشكل المعقَّد لتعليمة switch:]] بشكلٍ معقّد للغاية، أو لدى استخدام تعليمات if بشكل متتابعٍ متداخل.
# '''[[Refactoring/temporary field|الحقول المؤقّتة (temporary fields):]]''' والتي لن تُستخدَم إلّا في حالاتٍ معيّنة، وتبقى فارغةً فيما سواها.
+
# [[Refactoring/temporary field|الحقول المؤقّتة (temporary fields):]] والتي لن تُستخدَم إلّا في حالاتٍ معيّنة، وتبقى فارغةً فيما سواها.
  
 
== [[Refactoring/smells/change preventers|عرقلة التغيير]] ==
 
== [[Refactoring/smells/change preventers|عرقلة التغيير]] ==
 
قد يكون تطوير بعض الشيفرات مشكلةً حقيقيةً إذ عند إحداث أيّ تغييرٍ في جزءٍ منها لا بُدَّ وأن تتبعه عدّة تغييراتٍ أخرى في أجزاء متفرِّقة، وبالتالي سيصبح تطوير البرنامج شائكًا معقّدًا وبتكلفةٍ غير زهيدةٍ، من معوِّقات التغيير:
 
قد يكون تطوير بعض الشيفرات مشكلةً حقيقيةً إذ عند إحداث أيّ تغييرٍ في جزءٍ منها لا بُدَّ وأن تتبعه عدّة تغييراتٍ أخرى في أجزاء متفرِّقة، وبالتالي سيصبح تطوير البرنامج شائكًا معقّدًا وبتكلفةٍ غير زهيدةٍ، من معوِّقات التغيير:
# '''[[Refactoring/divergent change|التغيير المتشعِّب (divergent change):]]''' والحاجة لتغيير الكثير من التوابع التي لا علاقة لها بالأمر بمجرد تغيير أيّ جزءٍ في الصنف (class).
+
# [[Refactoring/divergent change|التغيير المتشعِّب (divergent change):]] والحاجة لتغيير الكثير من التوابع التي لا علاقة لها بالأمر بمجرد تغيير أيّ جزءٍ في الصنف (class).
# '''[[Refactoring/parallel inheritance hierarchies|الهيكليّة التفرعيّة للوراثة (parallel inheritance hierarchies):]]''' فتجد نفسك عند إنشاء صنفٍ فرعيٍّ (لأحد الأصناف) بحاجةٍ لإنشاء صنفٍ فرعيٍّ ثانٍ لصنفٍ آخر غيره.
+
# [[Refactoring/parallel inheritance hierarchies|الهيكليّة التفرعيّة للوراثة (parallel inheritance hierarchies):]] فتجد نفسك عند إنشاء صنفٍ فرعيٍّ (لأحد الأصناف) بحاجةٍ لإنشاء صنفٍ فرعيٍّ ثانٍ لصنفٍ آخر غيره.
# '''[[Refactoring/shotgun surgery|تغيير الأصناف المتعدِّدة (shotgun surgery):]]''' إذ يقتضي تعديلُ صنفٍ ما إجراءَ بعض التعديلات البسيطة على عدِّة أصناف أخرى.
+
# [[Refactoring/shotgun surgery|تغيير الأصناف المتعدِّدة (shotgun surgery):]] إذ يقتضي تعديلُ صنفٍ ما إجراءَ بعض التعديلات البسيطة على عدِّة أصناف أخرى.
  
 
== [[Refactoring/smells/dispensables|الأجزاء الفائضة]] ==
 
== [[Refactoring/smells/dispensables|الأجزاء الفائضة]] ==
 
وهي الأجزاء عديمة النفع في الشيفرة، وسيجعلُ التخلُّصُ منها الشيفرةَ نظيفةً يسيرة الفهم وأكثر فعاليّة، منها:
 
وهي الأجزاء عديمة النفع في الشيفرة، وسيجعلُ التخلُّصُ منها الشيفرةَ نظيفةً يسيرة الفهم وأكثر فعاليّة، منها:
# '''[[Refactoring/comments|التعليقات (comments):]]''' والتي تتمثّل بالشرح الزائد الذي لا طائل منه.
+
# [[Refactoring/comments|التعليقات (comments):]] والتي تتمثّل بالشرح الزائد الذي لا طائل منه.
# '''[[Refactoring/duplicate code|تكرار  الشيفرة (duplicates):]]''' بشكل متطابقٍ تمامًا في موقعين مختلفين.
+
# [[Refactoring/duplicate code|تكرار  الشيفرة (duplicates):]] بشكل متطابقٍ تمامًا في موقعين مختلفين.
# '''[[Refactoring/data class|أصناف البيانات (data classes):]]''' التي تحتوي على حقول البيانات (data fields) وبعض التوابع (methods) للوصول إليها وحسب.
+
# [[Refactoring/data class|أصناف البيانات (data classes):]] التي تحتوي على حقول البيانات (data fields) وبعض التوابع (methods) للوصول إليها وحسب.
# '''[[Refactoring/dead code|الشيفرة الميتة (dead code):]]''' كافّة المتغيِّرات (variables) أو المعاملات (parameters) أو الحقول (fields) أو التوابع (methods) أو الأصناف (classes) التي لم يعْد هنالك حاجةٌ لها فيما بعد ولن تُستخدَم مطلقًا ولكنها لا زالت موجودة.
+
# [[Refactoring/dead code|الشيفرة الميتة (dead code):]] كافّة المتغيِّرات (variables) أو المعاملات (parameters) أو الحقول (fields) أو التوابع (methods) أو الأصناف (classes) التي لم يعْد هنالك حاجةٌ لها فيما بعد ولن تُستخدَم مطلقًا ولكنها لا زالت موجودة.
# '''[[Refactoring/lazy class|الأصناف الخاملة (lazy classes):]]''' التي ليست بأهمية بالنسبة للبرنامج، إذ لكلِّ الأصناف متطلباتٌ دوريّةٌ من ناحية الزمن والتكلفة.
+
# [[Refactoring/lazy class|الأصناف الخاملة (lazy classes):]] التي ليست بأهمية بالنسبة للبرنامج، إذ لكلِّ الأصناف متطلباتٌ دوريّةٌ من ناحية الزمن والتكلفة.
# '''[[Refactoring/speculative generality|الخيال البرمجيّ (speculative generality):]]''' الذي يكون السبب بإنشاء الأصناف (classes) أو التوابع (methods) أو الحقول (fields) أو المعاملات (parameters) التي "قد" يحتاجها المبرمج مستقبلًا ولكنّها غير مستخدمةٍ بالوقت الحاليّ.
+
# [[Refactoring/speculative generality|الخيال البرمجيّ (speculative generality):]] الذي يكون السبب بإنشاء الأصناف (classes) أو التوابع (methods) أو الحقول (fields) أو المعاملات (parameters) التي "قد" يحتاجها المبرمج مستقبلًا ولكنّها غير مستخدمةٍ بالوقت الحاليّ.
  
 
== [[Refactoring/smells/couplers|الروابط الازدواجية]] ==
 
== [[Refactoring/smells/couplers|الروابط الازدواجية]] ==
 
يتلخّص هذا الجانب بعواقب إنشاء رابطٍ شديدٍ ازدواجيّ (ما بين صنفين [classes])، أو قد تظهر بدائل عنه كالتفويض المفرط (excessive delegation)، وتتمثل هذه المشكلة بالنقاط الآتية:
 
يتلخّص هذا الجانب بعواقب إنشاء رابطٍ شديدٍ ازدواجيّ (ما بين صنفين [classes])، أو قد تظهر بدائل عنه كالتفويض المفرط (excessive delegation)، وتتمثل هذه المشكلة بالنقاط الآتية:
# '''[[Refactoring/feature envy|التسلط على الكائنات الأخرى (feature envy):]]''' فقد تستخدم بعض التوابع (methods) بيانات الكائنات الأخرى أكثر مما تستخدم بياناتها ذاتها!
+
# [[Refactoring/feature envy|التسلط على الكائنات الأخرى (feature envy):]] فقد تستخدم بعض التوابع (methods) بيانات الكائنات الأخرى أكثر مما تستخدم بياناتها ذاتها!
# '''[[Refactoring/inappropriate intimacy|الارتباط الوثيق غير المناسب (inappropriate intimacy):]]''' عند استخدام أحد الأصناف للحقول (fields) والتوابع (methods) الداخليّة لصنف آخر بكثرة.
+
# [[Refactoring/inappropriate intimacy|الارتباط الوثيق غير المناسب (inappropriate intimacy):]] عند استخدام أحد الأصناف للحقول (fields) والتوابع (methods) الداخليّة لصنف آخر بكثرة.
# '''[[Refactoring/incomplete library class|أصناف المكتبة غير الكافية (incomplete library class):]]''' فقد لا تلبي أصناف المكتبة كافّة احتياجات البرنامج ولا يمكن تعديلها لأنّها للقراءة فقط (read-only).
+
# [[Refactoring/message chains|سلاسل الرسائل (message chains):]] وهي عدّة استدعاءاتٍ متسلسلةٍ مثل الشيفرة: <code>‎$a->b()->c()->d()‎</code>.
# '''[[Refactoring/message chains|سلاسل الرسائل (message chains):]]''' وهي عدّة استدعاءاتٍ متسلسلةٍ مثل الشيفرة: <code>‎$a->b()->c()->d()‎</code>.
+
# [[Refactoring/middle man|الوسيط (middle man):]] عندما يكون للصنف (class) مهمةٌ واحدةٌ فقط وهي تفويض المهام (delegation) لصنفٍ آخر. فما أهمية وجوده بالأصل؟
# '''[[Refactoring/middle man|الوسيط (middle man):]]''' عندما يكون للصنف (class) مهمةٌ واحدةٌ فقط وهي تفويض المهام (delegation) لصنفٍ آخر. فما أهمية وجوده بالأصل؟
 
  
== اختلالات ومشاكل أخرى ==
+
== [[Refactoring/smells/other smells|اختلالات ومشاكل أخرى]] ==
 
ستجد في هذا القسم الاختلالات والمشكلات التي لا تنحصر في صنف محدَّد.
 
ستجد في هذا القسم الاختلالات والمشكلات التي لا تنحصر في صنف محدَّد.
# [[Refactoring/incomplete library class|'''أصناف المكتبة غير الكافية (Incomplete Library Classes)''']]: لا تلبِّي أصناف المكتبة (library classes) كافّة احتياجات البرنامج مع استمرار تطوُّره، ولا يمكن تعديلها لأنّها مُخصَّصةٌ للقراءة فقط (read-only). ويكمن حل هذه المشكلة في [[Refactoring/introduce foreign method|تعريف التوابع الدخيلة]] أو [[Refactoring/introduce local extension|تعريف الإضافات المحليّة]].
+
# [[Refactoring/incomplete library class|أصناف المكتبة غير الكافية (Incomplete Library Classes)]]: لا تلبِّي أصناف المكتبة (library classes) كافّة احتياجات البرنامج مع استمرار تطوُّره، ولا يمكن تعديلها لأنّها مُخصَّصةٌ للقراءة فقط (read-only). ويكمن حل هذه المشكلة في [[Refactoring/introduce foreign method|تعريف التوابع الدخيلة]] أو [[Refactoring/introduce local extension|تعريف الإضافات المحليّة]].
  
 
== مصادر ==
 
== مصادر ==

المراجعة الحالية بتاريخ 20:18، 27 فبراير 2019

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

المبالغة والإطالة

قد يزداد حجم الشيفرات والتوابع (methods) والأصناف (classes) ازديادًا كبيرًا ليصل لمرحلةٍ يصعُب التعامل معها، ولا يحدث هذا بشكلٍ فجائيِّ دفعةً واحدةً، بل يكون ناتجًا عن تراكم الإضافات أثناء تطوير البرنامج (وخاصةً عندما لا يبذل أحدٌ جهدًا للحدِّ من ذلك التشعب)، ويبدو هذا التضخم واضحًا

  1. التوابع الطويلة (long methods): لاحتوائها على أسطر كثيرةٍ من الشيفرة، إذ لا يُفضَّل أن تزيد عن 10 أسطر.
  2. الأصناف الواسعة (large classes): والتي تحتوي على عددٍ كبيرٍ من الحقول (fields) والتوابع (methods) وبشيفرةٍ طويلةٍ.
  3. هوس الحقول الأساسيّة (primitives obsession): مثل الثوابت (constants) لتشفير المعلومات أو الثوابت النصيّة (string constants) لاستخدامها كأسماء للحقول (fields) في المصفوفات.
  4. المعاملات الكثيرة في التوابع (long parameter list): عندما تزيد على 3 أو 4 معاملات لنفس التابع.
  5. البيانات المُجمَّعة (data clumps): عندما تتكرَّر مجموعةٌ من المتغيِّرات بشكلٍ متطابقٍ تمامًا في عدة أجزاء من الشيفرة.

الاستخدام الخطأ لمبادئ البرمجة كائنية التوجه

من مشاكل الشيفرات أيضًا التطبيقُ الخطأ وغير المكتمل لمبادئ البرمجة كائنية التوجّه (Object-Oriented)، مثل:

  1. استخدام الأصناف البديلة (alternative) ذات الواجهات (interfaces) المختلفة: كأن يكون لصنفين المهمة (function) نفسها ولكن بأسماء مختلفة لتوابعهما (methods).
  2. الوراثة الفائضة (refused bequest): عندما يستفيد الصنف الفرعيّ (subclass) من القليل (والقليل فقط) ممّا ورثه عن الصنف الأعلى (superclass).
  3. الشكل المعقَّد لتعليمة switch: بشكلٍ معقّد للغاية، أو لدى استخدام تعليمات if بشكل متتابعٍ متداخل.
  4. الحقول المؤقّتة (temporary fields): والتي لن تُستخدَم إلّا في حالاتٍ معيّنة، وتبقى فارغةً فيما سواها.

عرقلة التغيير

قد يكون تطوير بعض الشيفرات مشكلةً حقيقيةً إذ عند إحداث أيّ تغييرٍ في جزءٍ منها لا بُدَّ وأن تتبعه عدّة تغييراتٍ أخرى في أجزاء متفرِّقة، وبالتالي سيصبح تطوير البرنامج شائكًا معقّدًا وبتكلفةٍ غير زهيدةٍ، من معوِّقات التغيير:

  1. التغيير المتشعِّب (divergent change): والحاجة لتغيير الكثير من التوابع التي لا علاقة لها بالأمر بمجرد تغيير أيّ جزءٍ في الصنف (class).
  2. الهيكليّة التفرعيّة للوراثة (parallel inheritance hierarchies): فتجد نفسك عند إنشاء صنفٍ فرعيٍّ (لأحد الأصناف) بحاجةٍ لإنشاء صنفٍ فرعيٍّ ثانٍ لصنفٍ آخر غيره.
  3. تغيير الأصناف المتعدِّدة (shotgun surgery): إذ يقتضي تعديلُ صنفٍ ما إجراءَ بعض التعديلات البسيطة على عدِّة أصناف أخرى.

الأجزاء الفائضة

وهي الأجزاء عديمة النفع في الشيفرة، وسيجعلُ التخلُّصُ منها الشيفرةَ نظيفةً يسيرة الفهم وأكثر فعاليّة، منها:

  1. التعليقات (comments): والتي تتمثّل بالشرح الزائد الذي لا طائل منه.
  2. تكرار  الشيفرة (duplicates): بشكل متطابقٍ تمامًا في موقعين مختلفين.
  3. أصناف البيانات (data classes): التي تحتوي على حقول البيانات (data fields) وبعض التوابع (methods) للوصول إليها وحسب.
  4. الشيفرة الميتة (dead code): كافّة المتغيِّرات (variables) أو المعاملات (parameters) أو الحقول (fields) أو التوابع (methods) أو الأصناف (classes) التي لم يعْد هنالك حاجةٌ لها فيما بعد ولن تُستخدَم مطلقًا ولكنها لا زالت موجودة.
  5. الأصناف الخاملة (lazy classes): التي ليست بأهمية بالنسبة للبرنامج، إذ لكلِّ الأصناف متطلباتٌ دوريّةٌ من ناحية الزمن والتكلفة.
  6. الخيال البرمجيّ (speculative generality): الذي يكون السبب بإنشاء الأصناف (classes) أو التوابع (methods) أو الحقول (fields) أو المعاملات (parameters) التي "قد" يحتاجها المبرمج مستقبلًا ولكنّها غير مستخدمةٍ بالوقت الحاليّ.

الروابط الازدواجية

يتلخّص هذا الجانب بعواقب إنشاء رابطٍ شديدٍ ازدواجيّ (ما بين صنفين [classes])، أو قد تظهر بدائل عنه كالتفويض المفرط (excessive delegation)، وتتمثل هذه المشكلة بالنقاط الآتية:

  1. التسلط على الكائنات الأخرى (feature envy): فقد تستخدم بعض التوابع (methods) بيانات الكائنات الأخرى أكثر مما تستخدم بياناتها ذاتها!
  2. الارتباط الوثيق غير المناسب (inappropriate intimacy): عند استخدام أحد الأصناف للحقول (fields) والتوابع (methods) الداخليّة لصنف آخر بكثرة.
  3. سلاسل الرسائل (message chains): وهي عدّة استدعاءاتٍ متسلسلةٍ مثل الشيفرة: ‎$a->b()->c()->d()‎.
  4. الوسيط (middle man): عندما يكون للصنف (class) مهمةٌ واحدةٌ فقط وهي تفويض المهام (delegation) لصنفٍ آخر. فما أهمية وجوده بالأصل؟

اختلالات ومشاكل أخرى

ستجد في هذا القسم الاختلالات والمشكلات التي لا تنحصر في صنف محدَّد.

  1. أصناف المكتبة غير الكافية (Incomplete Library Classes): لا تلبِّي أصناف المكتبة (library classes) كافّة احتياجات البرنامج مع استمرار تطوُّره، ولا يمكن تعديلها لأنّها مُخصَّصةٌ للقراءة فقط (read-only). ويكمن حل هذه المشكلة في تعريف التوابع الدخيلة أو تعريف الإضافات المحليّة.

مصادر