«Refactoring»: الفرق بين المراجعتين

من موسوعة حسوب
اذهب إلى: تصفح، ابحث
(كيف تكون الشيفرة نظيفة؟)
ط (اقتراح تعديل صياغة الجملة)
 
(9 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة)
سطر 30: سطر 30:
  
 
== [[Refactoring/how to|خطوات إعادة التصميم]] ==
 
== [[Refactoring/how to|خطوات إعادة التصميم]] ==
تجري عملية إعادة التصميم عبر عدّة خطواتٍ تُحدِث تغييرًا بسيطًا تدريجيًّا يجعل الشيفرة (مع كلِّ تغييرٍ) أفضل بقليلٍ، ولكنها لا توثر على أداء وفعاليّة البرنامج وتحافظ على استمرار عمله بشكلٍ سليمٍ، وتتلخص إعادة التصميم بالخطوات الآتية:
+
تجري عملية إعادة التصميم عبر عدّة خطواتٍ تُحدِث تغييرًا طفيفا تدريجيًّا يجعل الشيفرة (مع كلِّ تغييرٍ) أفضل بقليلٍ، ولكنها لا تؤثر على أداء وفعاليّة البرنامج وتحافظ على استمرار عمله بشكلٍ سليمٍ، وتتلخص إعادة التصميم بالخطوات الآتية:
 
* '''الحصول على شيفرةٍ نظيفة'''
 
* '''الحصول على شيفرةٍ نظيفة'''
 
* ''' لا مهام وظيفيّة جديدة أثناء إعادة التصميم'''
 
* ''' لا مهام وظيفيّة جديدة أثناء إعادة التصميم'''
سطر 36: سطر 36:
  
 
=== مثال ===
 
=== مثال ===
تفيد عملية إعادة التصميم في تبسيط التعليمات الشرطيّة المعقَّدة وذلك عبر عزل عملياتها في توابع مستقلَّة كما في المثال الآتي.
+
تفيد عملية إعادة التصميم في تسهيل التعليمات الشرطيّة المعقَّدة وذلك عبر عزل عملياتها في توابع مستقلَّة كما في المثال الآتي.
  
 
==== الشيفرة قبل إعادة التصميم ====
 
==== الشيفرة قبل إعادة التصميم ====
سطر 72: سطر 72:
 
من مشاكل الشيفرات أيضًا التطبيقُ الخطأ وغير المكتمل لمبادئ البرمجة كائنية التوجّه (Object-Oriented).
 
من مشاكل الشيفرات أيضًا التطبيقُ الخطأ وغير المكتمل لمبادئ البرمجة كائنية التوجّه (Object-Oriented).
 
=== [[Refactoring/smells/change preventers|عرقلة التغيير]] ===
 
=== [[Refactoring/smells/change preventers|عرقلة التغيير]] ===
قد يكون تطوير بعض الشيفرات مشكلةً حقيقيةً إذ عند إحداث أيّ تغييرٍ في جزءٍ منها لا بُدَّ وأن تتبعه عدّة تغييراتٍ أخرى في أجزاء متفرِّقة، وبالتالي سيصبح تطوير البرنامج شائكًا معقّدًا وبتكلفةٍ غير زهيدةٍ.
+
قد يكون تطوير بعض الشيفرات مشكلةً حقيقيةً إذ عند إحداث أيّ تغييرٍ في جزءٍ منها لا بُدَّ وأن تتبعه عدّة تغييراتٍ أخرى في أجزاء متفرِّقة، وبالتالي سيصبح تطوير البرنامج شائكًا ومعقّدًا وبتكلفةٍ غير زهيدةٍ.
 +
 
 
=== [[Refactoring/smells/dispensables|الأجزاء الفائضة]] ===
 
=== [[Refactoring/smells/dispensables|الأجزاء الفائضة]] ===
 
وهي الأجزاء عديمة النفع في الشيفرة، وسيجعلُ التخلُّصُ منها الشيفرةَ نظيفةً يسيرة الفهم وأكثر فعاليّة.
 
وهي الأجزاء عديمة النفع في الشيفرة، وسيجعلُ التخلُّصُ منها الشيفرةَ نظيفةً يسيرة الفهم وأكثر فعاليّة.
 
=== [[Refactoring/smells/couplers|الروابط الازدواجية]] ===
 
=== [[Refactoring/smells/couplers|الروابط الازدواجية]] ===
كإنشاء رابطٍ شديدٍ ازدواجيّ (ما بين صنفين [classes])، أو التفويض المفرط (excessive delegation).
+
مثل إنشاء رابطٍ شديدٍ ازدواجيّ (ما بين صنفين [classes])، أو التفويض المفرط (excessive delegation).
  
 
=== [[Refactoring/smells/other smells|مشاكل أخرى]] ===
 
=== [[Refactoring/smells/other smells|مشاكل أخرى]] ===
سطر 85: سطر 86:
  
 
===[[Refactoring/techniques/composing methods|إنشاء التوابع]]===
 
===[[Refactoring/techniques/composing methods|إنشاء التوابع]]===
تستهدف إعادة التصميم بشكل رئيسيٍّ إنشاء التوابع الصحيحة المناسبة، إذ تكون التوابع الطويلة سببًا للمشاكل في كثيرٍ من الحالات، وتجعل شيفرات بعض التوابع منطق التنفيذ (execution logic) غامضًا ويصبح التابع بهذا عصيَّ الفهم من جهةٍ وصعب التغييرٍ من جهة ثانية.
+
تستهدف إعادة التصميم بشكل رئيس إنشاء التوابع الصحيحة المناسبة، إذ تكون التوابع الطويلة سببًا للمشاكل في كثيرٍ من الحالات، وتجعل شيفرات بعض التوابع منطق التنفيذ (execution logic) غامضًا ويصبح التابع بهذا عصيَّ الفهم من جهةٍ وصعب التغييرٍ من جهة ثانية.
  
 
يشمل هذا القسم من الحلول كلَّ ما يتعلق بالتوابع وإزالة التكرار (duplicates) في الشيفرة ليسمح بإجراء التطويرات المستقبليّة.
 
يشمل هذا القسم من الحلول كلَّ ما يتعلق بالتوابع وإزالة التكرار (duplicates) في الشيفرة ليسمح بإجراء التطويرات المستقبليّة.
 +
 
===[[Refactoring/techniques/moving features between objects|نقل الميزات ما بين الكائنات]]===
 
===[[Refactoring/techniques/moving features between objects|نقل الميزات ما بين الكائنات]]===
 
تساعد عملية إعادة التصميم في توزيع المهام بشكل مثاليّ على الأصناف المختلفة في الشيفرة، وتضمن تقنيات الحل هذه طريقةً آمنةً لنقل المهام ما بين الأصناف، وإنشاء أصناف جديدة وحماية تفاصيل عملية التنفيذ من الوصول العام.
 
تساعد عملية إعادة التصميم في توزيع المهام بشكل مثاليّ على الأصناف المختلفة في الشيفرة، وتضمن تقنيات الحل هذه طريقةً آمنةً لنقل المهام ما بين الأصناف، وإنشاء أصناف جديدة وحماية تفاصيل عملية التنفيذ من الوصول العام.
 
===[[Refactoring/techniques/organizing data|تنظيم البيانات]]===
 
===[[Refactoring/techniques/organizing data|تنظيم البيانات]]===
تساعد تقنيات إعادة التصميم هذه بالتعامل مع البيانات، وتبديل أصناف ذات وظائف كثيرة مكان الأنواع الأساسية (primitives). نتيجة أخرى مهمة نحصل عليها بتطبيق هذه التقنيات هي فك ارتباطات صنف مما يجعل الصنف قابلًا للنقل وإعادة الاستعمال.
+
تساعد تقنيات إعادة التصميم التعامل مع البيانات، وتبديل أصناف ذات وظائف كثيرة مكان الأنواع الأساسية (primitives). نتيجة لتطبيق هذه التقنيات يمكن فك ارتباطات صنف مما يجعله قابلًا للنقل وإعادة الاستعمال.
===[[Refactoring/techniques/simplifying conditional expressions|تبسيط التعابير الشرطية]]===
+
 
تزداد البنية المنطقية للشروط تعقيدًا مع مرور الوقت، لذا هنالك الكثير من التقنيات لمواجهة هذا التعقيد وتبسيطه.
+
===[[Refactoring/techniques/simplifying conditional expressions|تسهيل التعابير الشرطية]]===
 +
تزداد البنية المنطقية للشروط تعقيدًا مع مرور الوقت، لذا هنالك الكثير من التقنيات لمواجهة هذا التعقيد وتسهيله.
  
===[[Refactoring/techniques/simplifying method calls|تبسيط استدعاءات التوابع]]===
+
===[[Refactoring/techniques/simplifying method calls|تسهيل استدعاءات التوابع]]===
تجعل التقنيات التي سيشار إليها في هذا القسم استدعاءات التوابع أبسط وأسهل للفهم والاستيعاب. سيؤدي ذلك بدوره إلى تبسيط الواجهات للتفاعل بين الأصناف.
+
تجعل التقنيات التي سيشار إليها في هذا القسم استدعاءات التوابع أسهل للفهم والاستيعاب. سيؤدي ذلك بدوره إلى تسهيل الواجهات للتفاعل بين الأصناف.
  
 
===[[Refactoring/techniques/dealing with generalization|التعامل مع التعميم]]===
 
===[[Refactoring/techniques/dealing with generalization|التعامل مع التعميم]]===
يملك التجريد (Abstraction) تقنيات إعادة التصميم الخاصة به والمرتبطة بشكل أساسي بوظيفة النقل على طول التسلسل الهرمي لوراثة الصنف (class inheritance hierarchy)، وبإنشاء أصناف وواجهات جديدة، وبتبديل التفويض مكان الوراثة أو العكس.  
+
للتجريد (Abstraction) تقنيات إعادة التصميم الخاصة به وهي المرتبطة بشكل أساسي بوظيفة النقل على طول التسلسل الهرمي لوراثة الصنف (class inheritance hierarchy)، وبإنشاء أصناف وواجهات جديدة، وبتبديل التفويض مكان الوراثة أو العكس.
  
 
== مصادر ==
 
== مصادر ==
 
* [https://refactoring.guru/ صفحة توثيق إعادة التصميم في موقع refactoring.guru]
 
* [https://refactoring.guru/ صفحة توثيق إعادة التصميم في موقع refactoring.guru]
 
[[تصنيف:Refactoring]]
 
[[تصنيف:Refactoring]]

المراجعة الحالية بتاريخ 12:47، 23 يونيو 2019

تهدف عملية إعادة التصميم (refactoring) للحصول على شيفرة جيّدة سهلة القراءة يسهل تطويرها والتخلُّص من المتطلَّبات التقنيّة الزائدة فيها، وهذا ما يُعرَف بالشيفرة النظيفة (clean code) لأنّ الشيفرة الرديئة لا بُدَّ من انعكاسها سلبًا على نجاح المشروع البرمجيّ.

كيف تكون الشيفرة نظيفة؟

هدف عملية إعادة التصميم (refactoring) هو التخلُّص من المتطلَّبات التقنيّة الزائدة، إذ تحوِّل كلَّ الفوضى المنتشرة في الشيفرة إلى شيفرةٍ نظيفةٍ (clean code) ذات تصميمٍ سهل، وهذا -لا بُدَّ- أمرٌ رائعٌ. من مميزات الشيفرة النظيفة:

  • واضحة ومقروءة
  • لا تكرار فيها
  • بأقل عددٍ ممكنٍ من الأصناف
  • تجتاز الاختبارات المختلفة بنجاح
  • سهلة ولا تحتاج الصيانة المتكرِّرة

فخ الأعباء التقنية

يقع الكثير من المبرمجين في فخ الأعباء التقنية وهذا مكلفٌ جدًا إن لم يُعالَج في وقت مبكِّر، ومن أسبابه:

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

متى نحتاج إعادة التصميم؟

نحتاج إلى إعادة التصميم:

  1. عند إضافة ميّزةٍ (feature) جديدة: إذ سيصبح التحكُّم بالشيفرة النظيفة (clean code) أكثر سهولةً، وبالتالي فإنّ إجراء التغييرات سيكون أسهل بكثيرٍ مما كان عليه قبل إعادة التصميم.
  2. عند إصلاح الأخطاء (bugs): إذ ستتَّضح الأخطاء بجهدٍ ووقتٍ أقل، وستغني إعادة التصميم المبكِّرة عن الحاجةَ لإعادة التصميم المُخصَّص لاحقًا.
  3. أثناء مراجعة الشيفرة (code review): إذ هي الفرصةُ الأخيرة لتوضيب الشيفرة قبل نشرها للعامّة.

خطوات إعادة التصميم

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

  • الحصول على شيفرةٍ نظيفة
  •  لا مهام وظيفيّة جديدة أثناء إعادة التصميم
  • اجتياز كافة الاختبارات السابقة

مثال

تفيد عملية إعادة التصميم في تسهيل التعليمات الشرطيّة المعقَّدة وذلك عبر عزل عملياتها في توابع مستقلَّة كما في المثال الآتي.

الشيفرة قبل إعادة التصميم

if (date.before(SUMMER_START) || date.after(SUMMER_END)) {
    charge = quantity * winterRate + winterServiceCharge;
}
else {
    charge = quantity * summerRate;
}

الشيفرة بعد التصميم

if (notSummer(date)) {
    charge = winterCharge(quantity);
}
else {
    charge = summerCharge(quantity);
}

والفرق واضحٌ ما بين الشيفرتين من ناحية التنظيم (organization) وسهولة كشف الأخطاء (bug detects) وقابليّة القراءة (readability) والصيانة (maintenance).

مشاكل الشيفرات

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

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

قد يزداد حجم الشيفرة ازديادًا كبيرًا ليصل لمرحلةٍ يصعُب التعامل معها، ويبدو هذا التضخم واضحًا.

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

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

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

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

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

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

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

مثل إنشاء رابطٍ شديدٍ ازدواجيّ (ما بين صنفين [classes])، أو التفويض المفرط (excessive delegation).

مشاكل أخرى

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

تقنيات إعادة التصميم

هنالك العديد من تقنيات إعادة التصميم التي يمكن استعمالها في حالات عديدة. تنقسم هذه التقنيات إلى:

إنشاء التوابع

تستهدف إعادة التصميم بشكل رئيس إنشاء التوابع الصحيحة المناسبة، إذ تكون التوابع الطويلة سببًا للمشاكل في كثيرٍ من الحالات، وتجعل شيفرات بعض التوابع منطق التنفيذ (execution logic) غامضًا ويصبح التابع بهذا عصيَّ الفهم من جهةٍ وصعب التغييرٍ من جهة ثانية.

يشمل هذا القسم من الحلول كلَّ ما يتعلق بالتوابع وإزالة التكرار (duplicates) في الشيفرة ليسمح بإجراء التطويرات المستقبليّة.

نقل الميزات ما بين الكائنات

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

تنظيم البيانات

تساعد تقنيات إعادة التصميم التعامل مع البيانات، وتبديل أصناف ذات وظائف كثيرة مكان الأنواع الأساسية (primitives). نتيجة لتطبيق هذه التقنيات يمكن فك ارتباطات صنف مما يجعله قابلًا للنقل وإعادة الاستعمال.

تسهيل التعابير الشرطية

تزداد البنية المنطقية للشروط تعقيدًا مع مرور الوقت، لذا هنالك الكثير من التقنيات لمواجهة هذا التعقيد وتسهيله.

تسهيل استدعاءات التوابع

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

التعامل مع التعميم

للتجريد (Abstraction) تقنيات إعادة التصميم الخاصة به وهي المرتبطة بشكل أساسي بوظيفة النقل على طول التسلسل الهرمي لوراثة الصنف (class inheritance hierarchy)، وبإنشاء أصناف وواجهات جديدة، وبتبديل التفويض مكان الوراثة أو العكس.

مصادر