الفرق بين المراجعتين ل"Refactoring/replace type code with state strategy"
Khaled-yassin (نقاش | مساهمات) (أنشأ الصفحة ب'<noinclude>{{DISPLAYTITLE: تبديل رموز الأنواع بالحالة/الاستراتيجية (Replace Type Code with State/Strategy)}}</noinclude> ما هو ر...') |
جميل-بيلوني (نقاش | مساهمات) ط (مراجعة وتدقيق) |
||
(مراجعة متوسطة واحدة بواسطة مستخدم واحد آخر غير معروضة) | |||
سطر 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 يحتوي على عنصرين ذوي نوع مرمز.]] | ||
− | == | + | === بعد إعادة التصميم === |
− | + | إنشاء كائن الحالة <code>EmployeeType</code> ليحل مكان عناصر ذات رمز نوع في الصنف <code>Employee</code>. | |
− | [[ملف: | + | [[ملف: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|تبديل رموز الأنواع بالأصناف الفرعية]]. |
== فوائد تطبيق الحل == | == فوائد تطبيق الحل == | ||
− | * تقنية إعادة التصميم هذه هي طريقة للخروج من الحالات التي يُغيِّر فيها حقل مع نوع مُرمَّز من قيمته طوال عمر الكائن. في هذه الحالة، | + | * تقنية إعادة التصميم هذه هي طريقة للخروج من الحالات التي يُغيِّر فيها حقل مع نوع مُرمَّز من قيمته طوال عمر الكائن. في هذه الحالة، تُستبدَل القيمة عن طريق استبدال كائن الحالة الذي يشير إليه الصنف الأصلي. |
* إذا دعت الحاجة إلى إضافة قيمة جديدة من نوع مُرمَّز، فيجب إضافة صنف حالة فرعي جديد دون تغيير الرمز الموجود (راجع مبدأ مفتوح/مغلق). | * إذا دعت الحاجة إلى إضافة قيمة جديدة من نوع مُرمَّز، فيجب إضافة صنف حالة فرعي جديد دون تغيير الرمز الموجود (راجع مبدأ مفتوح/مغلق). | ||
سطر 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/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
يحتوي على عنصرين ذوي نوع مرمز ولا يمكن استعمال الأصناف الفرعية للتخلص منهما.
بعد إعادة التصميم
إنشاء كائن الحالة EmployeeType
ليحل مكان عناصر ذات رمز نوع في الصنف Employee
.
لم إعادة التصميم؟
يؤثر رمز النوع على سلوك الصنف، لذلك لا يمكن استخدام تبديل رموز الأنواع بالأصناف.
يؤثر رمز النوع على سلوك الصنف ولكن لا يمكن إنشاء أصناف فرعية للنوع المُرمَّز بسبب التسلسل الهرمي للصنف الموجود أو لأسباب أخرى. مما يعني أنه لا يمكن أن تطبيق تبديل رموز الأنواع بالأصناف الفرعية.
فوائد تطبيق الحل
- تقنية إعادة التصميم هذه هي طريقة للخروج من الحالات التي يُغيِّر فيها حقل مع نوع مُرمَّز من قيمته طوال عمر الكائن. في هذه الحالة، تُستبدَل القيمة عن طريق استبدال كائن الحالة الذي يشير إليه الصنف الأصلي.
- إذا دعت الحاجة إلى إضافة قيمة جديدة من نوع مُرمَّز، فيجب إضافة صنف حالة فرعي جديد دون تغيير الرمز الموجود (راجع مبدأ مفتوح/مغلق).
مساوئ تطبيق الحل
إذا وجدت حالة بسيطة من رمز النوع ولكن استخدمت تقنية إعادة التصميم على أية حال، سيكون هناك الكثير من الأصناف الإضافية (غير الضرورية).
من الجيد أن نعرف
يمكن أن يستخدم تنفيذ تقنية إعادة التصميم واحدًا من نمطي التصميم التاليين: الحالة (State) أو الاستراتيجية (Strategy). ويكون التنفيذ متشابهًا بغض النظر عن استخدام أيٍّ من النمطين. لذا أي نمط يجب اختياره لكل موقف؟
إذا كنت بصدد محاولة تقسيم الشرط الذي يتحكم في تحديد الخوارزميات، فاستخدم نمط الاستراتيجية.
ولكن إذا كانت كل قيمة من النوع المُرمَّز مسؤولة ليس فقط عن تحديد الخوارزمية ولكن عن كامل شرط الصنف، وحالة الصنف، وقيم الحقل، والعديد من الإجراءات الأخرى، فسيكون استعمال نمط الحالة هو الأفضل لهذه المهمة.
آلية الحل
- استخدم التغليف الداخلي للحقل لإنشاء مُتلقي للحقل يحتوي على رمز النوع.
- أنشئ صنفًا جديدًا واعطه اسمًا ذا معنًى يتناسب مع الغرض من رمز النوع. سيلعب هذا الصنف دور الحالة (أو الاستراتيجية). أنشئ مُتلقي حقل مُرمَّز مجرد داخله.
- أنشئ أصنافًا فرعيةً لصنف الحالة لكل قيمة من النوع المُرمَّز. في كل صنف فرعي، أعد تعريف المُتلقي للحقل المُرمَّز بحيث تعيد القيمة المقابلة من النوع المُرمَّز.
- في صنف الحالة المجردة، أنشئ تابعًا منتجًا ساكنًا (static factory method) يقبل قيمة النوع المُرمَّز كمعامل. اعتمادًا على هذا المعامل، سيُنشئ التابع المنتج كائنات بحالات مختلفة. لهذا، أنشئ في رمزه شرطية كبيرة، إذ ستكون الوحيدة عند اكتمال إعادة تصميم.
- غيِّر نوع ترميز الحقل في الصنف الأصلي إلى صنف الحالة. استدعِ تابع حالة التصميم في ضابط الحقل للحصول على كائنات حالة جديدة.
- يمكن الآن البدء في نقل الحقول والتوابع من الصنف الأب إلى أصناف الحالة الفرعية المناظرة (باستخدام حقل الدفع إلى أسفل وتابع الدفع إلى أسفل).
- عند نقل كل ما يمكن نقله، استخدم تبديل الشرطيات بالتعدديّة الشكليّة من أجل التخلص من الشرطيات التي تستخدم رمز النوع مرة واحدة وإلى الأبد.
انظر أيضًا
- تبديل رموز الأنواع بالأصناف.
- تبديل رموز الأنواع بالأصناف الفرعية.
- التغليف الداخلي للحقل.
- حقل الدفع إلى أسفل.
- تابع الدفع إلى أسفل.
- تبديل الشرطيات بالتعدديّة الشكليّة.