الفرق بين المراجعتين ل"Refactoring/replace type code with state strategy"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
ط (مراجعة وتدقيق)
 
سطر 1: سطر 1:
 
<noinclude>{{DISPLAYTITLE: تبديل رموز الأنواع بالحالة/الاستراتيجية (Replace Type Code with State/Strategy)}}</noinclude>
 
<noinclude>{{DISPLAYTITLE: تبديل رموز الأنواع بالحالة/الاستراتيجية (Replace Type Code with State/Strategy)}}</noinclude>
ما هو رمز النوع؟ يحدث رمز النوع عندما يوجد مجموعة من الأرقام أو السلاسل النصية التي تشكل قائمة بالقيم المسموح بها لبعض العناصر بدلًا من استخدام نوع بيانات منفصل. وغالبًا ما تُعطى هذه الأرقام والسلاسل المحددة أسماءً مفهومة عن طريق الثوابت، وهو السبب في استخدام هذه الرموز بشكل كبير.
+
ما هو رمز النوع؟ يحدث رمز النوع عندما يوجد مجموعة من الأرقام أو السلاسل النصية التي تشكل قائمة بالقيم المسموح بها لبعض العناصر بدلًا من استخدام نوع بيانات منفصل. وغالبًا ما تُعطَى هذه الأرقام والسلاسل المحددة أسماءً مفهومة عن طريق الثوابت، وهو السبب في استخدام هذه الرموز بشكل كبير.
  
 
== المشكلة ==
 
== المشكلة ==
 
يؤثر نوع مُرمَّز على سلوك البرنامج ولكن لا يمكن استخدام الأصناف الفرعية للتخلص منه.
 
يؤثر نوع مُرمَّز على سلوك البرنامج ولكن لا يمكن استخدام الأصناف الفرعية للتخلص منه.
[[ملف:Replace Type Code with State-Strategy - Before.png|بدون|تصغير]]
+
== الحل ==
 +
استبدال رمز النوع بكائن حالة. إذا كان من الضروري استبدال قيمة حقل برمز النوع، فسيكون كائن حالة آخر "موصولًا" ("plugged-in").
 +
 
 +
== مثال ==
 +
 
 +
=== قبل إعادة التصميم ===
 +
الصنف <code>Employee</code> يحتوي على عنصرين ذوي نوع مرمز ولا يمكن استعمال الأصناف الفرعية للتخلص منهما.[[ملف:Replace Type Code with State-Strategy - Before.png|بدون|تصغير|بديل=الصنف Employee يحتوي على عنصرين ذوي نوع مرمز.|240x240بك|الصنف Employee يحتوي على عنصرين ذوي نوع مرمز.]]
  
== الحل ==
+
=== بعد إعادة التصميم ===
استبدال رمز النوع بكائن حالة. إذا كان من الضروري استبدال قيمة حقل برمز النوع، يكون كائن حالة آخر "موصولًا" ("plugged-in").
+
إنشاء كائن الحالة <code>EmployeeType</code> ليحل مكان عناصر ذات رمز نوع في الصنف <code>Employee</code>.  
[[ملف:Replace Type Code with State-Strategy - After.png]]
+
[[ملف:Replace_Type_Code_with_State-Strategy_-_After.png|بديل=استعمال كائن الحالة EmployeeType ووصله بالصنف Employee.|بدون|تصغير|354x354بك|استعمال كائن الحالة EmployeeType ووصله بالصنف Employee.]]
  
 
== لم إعادة التصميم؟ ==
 
== لم إعادة التصميم؟ ==
 
يؤثر رمز النوع على سلوك الصنف، لذلك لا يمكن استخدام [[Refactoring/replace type code with class|تبديل رموز الأنواع بالأصناف]].
 
يؤثر رمز النوع على سلوك الصنف، لذلك لا يمكن استخدام [[Refactoring/replace type code with class|تبديل رموز الأنواع بالأصناف]].
  
يؤثر رمز النوع علي سلوك الصنف ولكن لا يمكن إنشاء أصناف فرعية للنوع المُرمَّز بسبب التسلسل الهرمي للصنف الموجود أو لأسباب أخرى. مما يعني أنه لا يمكن أن تطبيق [[Refactoring/replace type code with subclasses|تبديل رموز الأنواع بالأصناف الفرعية]].
+
يؤثر رمز النوع على سلوك الصنف ولكن لا يمكن إنشاء أصناف فرعية للنوع المُرمَّز بسبب التسلسل الهرمي للصنف الموجود أو لأسباب أخرى. مما يعني أنه لا يمكن أن تطبيق [[Refactoring/replace type code with subclasses|تبديل رموز الأنواع بالأصناف الفرعية]].
  
 
== فوائد تطبيق الحل ==
 
== فوائد تطبيق الحل ==
* تقنية إعادة التصميم هذه هي طريقة للخروج من الحالات التي يُغيِّر فيها حقل مع نوع مُرمَّز من قيمته طوال عمر الكائن. في هذه الحالة، تُستبدل القيمة عن طريق استبدال كائن الحالة الذي يشير إليه الصنف الأصلي.
+
* تقنية إعادة التصميم هذه هي طريقة للخروج من الحالات التي يُغيِّر فيها حقل مع نوع مُرمَّز من قيمته طوال عمر الكائن. في هذه الحالة، تُستبدَل القيمة عن طريق استبدال كائن الحالة الذي يشير إليه الصنف الأصلي.
 
* إذا دعت الحاجة إلى إضافة قيمة جديدة من نوع مُرمَّز، فيجب إضافة صنف حالة فرعي جديد دون تغيير الرمز الموجود (راجع مبدأ مفتوح/مغلق).
 
* إذا دعت الحاجة إلى إضافة قيمة جديدة من نوع مُرمَّز، فيجب إضافة صنف حالة فرعي جديد دون تغيير الرمز الموجود (راجع مبدأ مفتوح/مغلق).
  
سطر 23: سطر 29:
  
 
== من الجيد أن نعرف ==
 
== من الجيد أن نعرف ==
يمكن أن يستخدم تنفيذ تقنية إعادة التصميم واحدًا من نمطي التصميم: الحالة (State) أو الاستراتيجية (Strategy). ويكون التنفيذ متشابهًا بغض النظر عن استخدام أي النمطين. لذا أي نمط يجب اختياره لكل موقف؟
+
يمكن أن يستخدم تنفيذ تقنية إعادة التصميم واحدًا من نمطي التصميم التاليين: الحالة (State) أو الاستراتيجية (Strategy). ويكون التنفيذ متشابهًا بغض النظر عن استخدام أيٍّ من النمطين. لذا أي نمط يجب اختياره لكل موقف؟
  
إذا كنا بصدد محاولة تقسيم الشرط الذي يتحكم في تحديد الخوارزميات، تُستخدم الاستراتيجية.
+
إذا كنت بصدد محاولة تقسيم الشرط الذي يتحكم في تحديد الخوارزميات، فاستخدم نمط الاستراتيجية.
  
ولكن إذا كانت كل قيمة من النوع المُرمَّز مسؤولة ليس فقط عن تحديد الخوارزمية ولكن عن كامل شرط الصنف، وحالة الصنف، وقيم الحقل، والعديد من الإجراءات الأخرى، ستكون الحالة هي الأفضل لهذه المهمة.
+
ولكن إذا كانت كل قيمة من النوع المُرمَّز مسؤولة ليس فقط عن تحديد الخوارزمية ولكن عن كامل شرط الصنف، وحالة الصنف، وقيم الحقل، والعديد من الإجراءات الأخرى، فسيكون استعمال نمط الحالة هو الأفضل لهذه المهمة.
  
 
== آلية الحل ==
 
== آلية الحل ==
# استخدم [[Refactoring/self encapsulate field|التغليف الداخلي للحقل]] لإنشاء مُتلقي للحقل الذي يحتوي على رمز النوع.
+
# استخدم [[Refactoring/self encapsulate field|التغليف الداخلي للحقل]] لإنشاء مُتلقي للحقل يحتوي على رمز النوع.
# أنشئ صنف جديد واعطه اسم له معنى يتناسب مع الغرض من رمز النوع. سيلعب هذا الصنف دور الحالة (أو الاستراتيجية). أنشئ مُتلقي حقل مُرمَّز مجرد داخله.
+
# أنشئ صنفًا جديدًا واعطه اسمًا ذا معنًى يتناسب مع الغرض من رمز النوع. سيلعب هذا الصنف دور الحالة (أو الاستراتيجية). أنشئ مُتلقي حقل مُرمَّز مجرد داخله.
# أنشئ أصناف فرعية لصنف الحالة لكل قيمة من النوع المُرمَّز. في كل صنف فرعي، أعد تعريف المُتلقي للحقل المُرمَّز بحيث تقوم بإعادة القيمة المقابلة من النوع المُرمَّز.
+
# أنشئ أصنافًا فرعيةً لصنف الحالة لكل قيمة من النوع المُرمَّز. في كل صنف فرعي، أعد تعريف المُتلقي للحقل المُرمَّز بحيث تعيد القيمة المقابلة من النوع المُرمَّز.
# في صنف الحالة المجردة، أنشئ تابع تصميم ساكن يقبل قيمة النوع المُرمَّز كمعامل. اعتمادًا علي هذا المعامل، سيُنشئ تابعُ التصميم كائنات بحالات مختلفة. لهذا، أنشئ في رمزه شرطية كبيرة؛ فستكون الوحيدة عند اكتمال إعادة تصميم.
+
# في صنف الحالة المجردة، أنشئ تابعًا منتجًا ساكنًا (static factory method) يقبل قيمة النوع المُرمَّز كمعامل. اعتمادًا على هذا المعامل، سيُنشئ التابع المنتج كائنات بحالات مختلفة. لهذا، أنشئ في رمزه شرطية كبيرة، إذ ستكون الوحيدة عند اكتمال إعادة تصميم.
 
# غيِّر نوع ترميز الحقل في الصنف الأصلي إلى صنف الحالة. استدعِ تابع حالة التصميم في ضابط الحقل للحصول على كائنات حالة جديدة.
 
# غيِّر نوع ترميز الحقل في الصنف الأصلي إلى صنف الحالة. استدعِ تابع حالة التصميم في ضابط الحقل للحصول على كائنات حالة جديدة.
# يمكن الآن البدء في نقل الحقول والتوابع من الصنف الفائق إلى أصناف الحالة الفرعية المناظرة (باستخدام [[Refactoring/push down field|حقل الدفع إلى أسفل]] و<nowiki/>[[Refactoring/push down method|تابع الدفع إلى أسفل]]).
+
# يمكن الآن البدء في نقل الحقول والتوابع من الصنف الأب إلى أصناف الحالة الفرعية المناظرة (باستخدام [[Refactoring/push down field|حقل الدفع إلى أسفل]] و<nowiki/>[[Refactoring/push down method|تابع الدفع إلى أسفل]]).
 
# عند نقل كل ما يمكن نقله، استخدم [[Refactoring/replace conditional with polymorphism|تبديل الشرطيات بالتعدديّة الشكليّة]] من أجل التخلص من الشرطيات التي تستخدم رمز النوع مرة واحدة وإلى الأبد.
 
# عند نقل كل ما يمكن نقله، استخدم [[Refactoring/replace conditional with polymorphism|تبديل الشرطيات بالتعدديّة الشكليّة]] من أجل التخلص من الشرطيات التي تستخدم رمز النوع مرة واحدة وإلى الأبد.
  
سطر 47: سطر 53:
  
 
== مصادر ==
 
== مصادر ==
* [https://refactoring.guru/replace-type-code-with-state-strategy صفحة توثيق رموز الأنواع بالحالة/الاستراتيجية في موقع refactoring.guru]. [[تصنيف:Refactoring]] [[تصنيف:Refactoring Techniques]] [[تصنيف:Refactoring Organizing Data]]
+
* [https://refactoring.guru/replace-type-code-with-state-strategy صفحة توثيق رموز الأنواع بالحالة/الاستراتيجية في موقع refactoring.guru].   [[تصنيف:Refactoring]]   [[تصنيف:Refactoring Techniques]]   [[تصنيف:Refactoring Organizing Data]]

المراجعة الحالية بتاريخ 06:45، 19 ديسمبر 2018

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

المشكلة

يؤثر نوع مُرمَّز على سلوك البرنامج ولكن لا يمكن استخدام الأصناف الفرعية للتخلص منه.

الحل

استبدال رمز النوع بكائن حالة. إذا كان من الضروري استبدال قيمة حقل برمز النوع، فسيكون كائن حالة آخر "موصولًا" ("plugged-in").

مثال

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

الصنف Employee يحتوي على عنصرين ذوي نوع مرمز ولا يمكن استعمال الأصناف الفرعية للتخلص منهما.

الصنف Employee يحتوي على عنصرين ذوي نوع مرمز.
الصنف Employee يحتوي على عنصرين ذوي نوع مرمز.

بعد إعادة التصميم

إنشاء كائن الحالة EmployeeType ليحل مكان عناصر ذات رمز نوع في الصنف Employee.

استعمال كائن الحالة EmployeeType ووصله بالصنف Employee.
استعمال كائن الحالة EmployeeType ووصله بالصنف Employee.

لم إعادة التصميم؟

يؤثر رمز النوع على سلوك الصنف، لذلك لا يمكن استخدام تبديل رموز الأنواع بالأصناف.

يؤثر رمز النوع على سلوك الصنف ولكن لا يمكن إنشاء أصناف فرعية للنوع المُرمَّز بسبب التسلسل الهرمي للصنف الموجود أو لأسباب أخرى. مما يعني أنه لا يمكن أن تطبيق تبديل رموز الأنواع بالأصناف الفرعية.

فوائد تطبيق الحل

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

مساوئ تطبيق الحل

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

من الجيد أن نعرف

يمكن أن يستخدم تنفيذ تقنية إعادة التصميم واحدًا من نمطي التصميم التاليين: الحالة (State) أو الاستراتيجية (Strategy). ويكون التنفيذ متشابهًا بغض النظر عن استخدام أيٍّ من النمطين. لذا أي نمط يجب اختياره لكل موقف؟

إذا كنت بصدد محاولة تقسيم الشرط الذي يتحكم في تحديد الخوارزميات، فاستخدم نمط الاستراتيجية.

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

آلية الحل

  1. استخدم التغليف الداخلي للحقل لإنشاء مُتلقي للحقل يحتوي على رمز النوع.
  2. أنشئ صنفًا جديدًا واعطه اسمًا ذا معنًى يتناسب مع الغرض من رمز النوع. سيلعب هذا الصنف دور الحالة (أو الاستراتيجية). أنشئ مُتلقي حقل مُرمَّز مجرد داخله.
  3. أنشئ أصنافًا فرعيةً لصنف الحالة لكل قيمة من النوع المُرمَّز. في كل صنف فرعي، أعد تعريف المُتلقي للحقل المُرمَّز بحيث تعيد القيمة المقابلة من النوع المُرمَّز.
  4. في صنف الحالة المجردة، أنشئ تابعًا منتجًا ساكنًا (static factory method) يقبل قيمة النوع المُرمَّز كمعامل. اعتمادًا على هذا المعامل، سيُنشئ التابع المنتج كائنات بحالات مختلفة. لهذا، أنشئ في رمزه شرطية كبيرة، إذ ستكون الوحيدة عند اكتمال إعادة تصميم.
  5. غيِّر نوع ترميز الحقل في الصنف الأصلي إلى صنف الحالة. استدعِ تابع حالة التصميم في ضابط الحقل للحصول على كائنات حالة جديدة.
  6. يمكن الآن البدء في نقل الحقول والتوابع من الصنف الأب إلى أصناف الحالة الفرعية المناظرة (باستخدام حقل الدفع إلى أسفل وتابع الدفع إلى أسفل).
  7. عند نقل كل ما يمكن نقله، استخدم تبديل الشرطيات بالتعدديّة الشكليّة من أجل التخلص من الشرطيات التي تستخدم رمز النوع مرة واحدة وإلى الأبد.

انظر أيضًا

مصادر