تبديل رموز الأنواع بالأصناف الفرعية (Replace Type Code with Subclasses)

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث

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

المشكلة

يؤثر النوع المُرمَّز على سلوك البرنامج (تُطلِق قيم هذا الحقل رموز مختلفة في الشرطيات).

الحل

إنشاء أصناف فرعية لكل قيمة من النوع المُرمَّز. ثم استخراج السلوكيات ذات الصلة من الصنف الأصلي إلى هذه الأصناف الفرعية. وتبديل رموز التحكم في التدفق بالتعدديّة الشكليّة. Replace Type Code with Subclasses - After.png

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

تُعد تقنية إعادة التصميم هذه تطورًا أكثر تعقيدًا من تبديل رموز الأنواع بالأصناف.

كما هو الحال مع تابع إعادة التصميم الأول، يوجد مجموعة من القيم البسيطة التي تشكل كافة القيم المسموح بها للحقل. علي الرغم من تحديد هذه القيم غالبًا كثوابت ولها أسماء مفهومة، يجعل استخدامها شيفرتك البرمجية أكثر عرضة للخطأ لأنها لا تزال بدائية في التأثير. فعلي سبيل المثال، إذا وُجِد تابع يقبل إحدى هذه القيم كمُعامل. في لحظة معينة، بدلًا من أن يتلقى التابعُ الثابتَ USER_TYPE_ADMIN بالقيمة "ADMIN"، يتلقى نفس السلسلة النصية بالحروف الصغيرة ("admin")، والتي ستسبب تنفيذ شيء آخر لم يقصده المُبرمِج.

نحن نتعامل هنا مع رمز التحكم في التدفق مثل الشرطيات if و switch و ‎?:‎. وبعبارة أخرى، تُستخدم الحقول ذات القيم المُرمَّزة (مثل ‎$user->type === self::USER_TYPE_ADMIN) داخل شروط هذه العوامل. إذا كان لنا أن نستخدم تبديل رموز الأنواع بالأصناف هنا، سيكون من الأفضل نقل كل بُنى التحكم في التدفق هذه إلى صنف مسؤول عن نوع البيانات. في نهاية المطاف، سيُنشئ هذا بالطبع صنف نوع مشابهه جدًا للصنف الأصلي، ومع نفس المشاكل أيضًا.

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

  • حذف رمز تدفق التحكم. نقل الرموز إلى الأصناف الفرعية المناسبة بدلًا من switch بشكل ضخم في الصنف الأصلي. الأمر الذي يزيد من الالتزام بمبدأ المسؤولية الفردية (Single Responsibility Principle) ويجعل البرنامج أكثر قابلية للقراءة.
  • إذا دعت الحاجة إلى إضافة قيمة جديدة لنوع مُرمَّز، يجب إضافة صنف فرعي جديد دون المساس بالرمز الحالي (راجع مبدأ مفتوح/مغلق).
  • ويُسمح بالتلميح بنوع التوابع والحقول علي مستوي لغة البرمجة وذلك باستبدال رموز الأنواع بالأصناف. ولن يكون هذا ممكنًا باستخدام القيم الرقمية البسيطة أو السلاسل النصية المضمنة في النوع المُرمَّز.

متى يُترك هذا الحل؟

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

آلية الحل

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

انظر أيضًا

مصادر