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

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
ط
ط (مراجعة)
 
سطر 1: سطر 1:
 
<noinclude>{{DISPLAYTITLE: تغليف المجموعات (Encapsulate Collection)}}</noinclude>
 
<noinclude>{{DISPLAYTITLE: تغليف المجموعات (Encapsulate Collection)}}</noinclude>
 
== المشكلة ==
 
== المشكلة ==
صنف يحتوي على حقل مجموعة ومتلقي (getter) وضابط (setter) بسيط للعمل مع المجموعة.
+
صنف يحتوي على حقل مجموعة وجالب (getter) وضابط (setter) بسيط للعمل مع المجموعة.
 
== الحل ==
 
== الحل ==
ضبط القيمة المعادة من المُتلقي لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.
+
ضبط القيمة المعادة من الجالب لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.
  
 
=== مثال ===
 
=== مثال ===
  
 
==== قبل إعادة التصميم ====
 
==== قبل إعادة التصميم ====
[[ملف:Encapsulate Collection - Before.png|بديل=صنف يحتوي على حقل مجموعة ومتلقي (getter) وضابط (setter) بسيط للعمل مع المجموعة.|بدون|تصغير|صنف يحتوي على حقل مجموعة ومتلقي (getter) وضابط (setter) بسيط للعمل مع المجموعة.]]
+
يحتوي الصنف <code>Person</code> على جالب <code>getCourses</code> وضابط <code>setCourses</code> بسيطين للتحكم بالدروس التي سجل بها الشخص:[[ملف:Encapsulate Collection - Before.png|بديل=صنف يحتوي على حقل مجموعة ومتلقي (getter) وضابط (setter) بسيط للعمل مع المجموعة.|بدون|تصغير|صنف يحتوي على حقل مجموعة وجالب (getter) وضابط (setter) بسيط للعمل مع المجموعة.]]
  
 
==== بعد إعادة التصميم ====
 
==== بعد إعادة التصميم ====
[[ملف:Encapsulate Collection - After.png|بديل=ضبط القيمة المعادة من المتلقي لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.|بدون|تصغير|ضبط القيمة المعادة من المتلقي لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.]]
+
ضبط القيمة المعادة من الجالب <code>setCourses</code> لتصبح للقراءة فقط وإضافة تابعين جديدين أحدهما لإضافة دروس جديدة للشخص (أي <code>addCourses</code>)، والآخر لحذف دروس محددة (أي <code>removeCourses</code>):[[ملف:Encapsulate Collection - After.png|بديل=ضبط القيمة المعادة من المتلقي لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.|بدون|تصغير|ضبط القيمة المعادة من الجالب لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.]]
  
 
== لم إعادة التصميم؟ ==
 
== لم إعادة التصميم؟ ==
يحتوي الصنف على حقل يحتوي بدوره على مجموعة من الكائنات. يمكن أن تكون هذه المجموعة مصفوفة أو قائمة أو مجموعة أو مُتجه (vector). يُنشَأ مُتلقي وضابط طبيعي للعمل مع المجموعة.
+
يحتوي الصنف على حقل يحتوي بدوره على مجموعة من الكائنات. يمكن أن تكون هذه المجموعة مصفوفة أو قائمة أو مجموعة أو مُتجه (vector). يُنشَأ جالب وضابط طبيعي للعمل مع المجموعة.
  
ولكن يجب استخدام المجموعات بواسطة بروتوكول يختلف قليلا عن الذي تستخدمه أنواع البيانات الأخرى. لا يجب أن يُعيد تابع المُتلقي كائن المجموعة ذاته، لأن هذا سيسمح للعملاء بتغيير محتويات المجموعة بدون معرفة صنف المالك. بالإضافة إلى ذلك، سيظهر هذا الكثيرَ من الهياكل الداخلية لبيانات الكائن إلى العملاء. ويجب أن يُعيد تابع الحصول على عناصر المجموعة قيمة لا تسمح بتغيير المجموعة أو كشف المزيد من البيانات عن هيكلها.
+
ولكن يجب استخدام المجموعات بواسطة بروتوكول يختلف قليلا عن الذي تستخدمه أنواع البيانات الأخرى. لا يجب أن يُعيد التابع الجالب كائن المجموعة ذاته، لأن هذا سيسمح للعملاء بتغيير محتويات المجموعة بدون معرفة صنف المالك. بالإضافة إلى ذلك، سيظهر هذا الكثيرَ من الهياكل الداخلية لبيانات الكائن إلى العملاء. ويجب أن يُعيد تابع الحصول على عناصر المجموعة قيمة لا تسمح بتغيير المجموعة أو كشف المزيد من البيانات عن هيكلها.
  
 
بالإضافة إلى ذلك، يجب ألَّا يكون هناك تابع يحدد قيمة للمجموعة. بدلًا من ذلك ينبغي أن تكون هناك عمليات لإضافة العناصر وحذفها. بفضل هذا، يتحكم الكائن المالك في إضافة عناصر المجموعة وحذفها.
 
بالإضافة إلى ذلك، يجب ألَّا يكون هناك تابع يحدد قيمة للمجموعة. بدلًا من ذلك ينبغي أن تكون هناك عمليات لإضافة العناصر وحذفها. بفضل هذا، يتحكم الكائن المالك في إضافة عناصر المجموعة وحذفها.
سطر 23: سطر 23:
  
 
== فوائد تطبيق الحل ==
 
== فوائد تطبيق الحل ==
* تغليف حقل المجموعة داخل صنف. عند استدعاء المُتلقي، يُعيد نسخة من المجموعة، الأمر الذي يمنع التغيير العرضي أو الكتابة فوق عناصر المجموعة بدون معرفة الصنف الذي يحتوي على المجموعة.
+
* تغليف حقل المجموعة داخل صنف. عند استدعاء الجالب، يُعيد نسخة من المجموعة، الأمر الذي يمنع التغيير العرضي أو الكتابة فوق عناصر المجموعة بدون معرفة الصنف الذي يحتوي على المجموعة.
 
* إذا كانت عناصر المجموعة موجودة داخل نوع بسيط، مثل مصفوفة، فإنك بذلك تُنشئ توابعًا أكثر ملاءمة للعمل مع المجموعة.
 
* إذا كانت عناصر المجموعة موجودة داخل نوع بسيط، مثل مصفوفة، فإنك بذلك تُنشئ توابعًا أكثر ملاءمة للعمل مع المجموعة.
 
* إذا كانت عناصر المجموعة موجودة داخل حاوية غير بسيطة (صنف المجموعة القياسية)، بواسطة تغليف المجموعة، فيمكن تقييد الوصول إلى التوابع القياسية غير المرغوب فيها للمجموعة (مثل تقييد إضافة عناصر جديدة).
 
* إذا كانت عناصر المجموعة موجودة داخل حاوية غير بسيطة (صنف المجموعة القياسية)، بواسطة تغليف المجموعة، فيمكن تقييد الوصول إلى التوابع القياسية غير المرغوب فيها للمجموعة (مثل تقييد إضافة عناصر جديدة).
سطر 31: سطر 31:
 
# تعيين مجموعة فارغة إلى الحقل كقيمة أولية إذا لم يتم ذلك في مُنشِئ الصنف.
 
# تعيين مجموعة فارغة إلى الحقل كقيمة أولية إذا لم يتم ذلك في مُنشِئ الصنف.
 
# ابحث عن استدعاءات ضابط حقل المجموعة. تغيير الضابط بحيث انه يستخدم عمليات لإضافة وحذف العناصر، أو حمل هذه العمليات على استدعاء الشيفرة البرمجية للعميل. علمًا بأنه يمكن استخدام الضوابط فقط لاستبدال كافة عناصر المجموعة بأخرى. ولذلك قد يكون من المستحسن تغيير اسم الضابط ([[Refactoring/rename method|تابع إعادة التسمية Rename]]) إلى <code>replace</code>.
 
# ابحث عن استدعاءات ضابط حقل المجموعة. تغيير الضابط بحيث انه يستخدم عمليات لإضافة وحذف العناصر، أو حمل هذه العمليات على استدعاء الشيفرة البرمجية للعميل. علمًا بأنه يمكن استخدام الضوابط فقط لاستبدال كافة عناصر المجموعة بأخرى. ولذلك قد يكون من المستحسن تغيير اسم الضابط ([[Refactoring/rename method|تابع إعادة التسمية Rename]]) إلى <code>replace</code>.
# ابحث عن استدعاءات مُتلقي المجموعة والتي تتغير بعدها المجموعة. غَيِّر الشيفرة البرمجية بحيث تستخدم التوابع الجديدة لإضافة وحذف عناصر من المجموعة.
+
# ابحث عن استدعاءات جالب المجموعة والتي تتغير بعدها المجموعة. غَيِّر الشيفرة البرمجية بحيث تستخدم التوابع الجديدة لإضافة وحذف عناصر من المجموعة.
# غَيِّر المُتلقي، وبذلك يُعيد تمثيل قابل للقراءة فقط للمجموعة.
+
# غَيِّر الجالب، وبذلك يُعيد تمثيل قابل للقراءة فقط للمجموعة.
 
# افحص الشيفرة البرمجية للعميل التي تستخدم المجموعة للشيفرة البرمجية التي قد تبدو أفضل داخل صنف المجموعة نفسها.
 
# افحص الشيفرة البرمجية للعميل التي تستخدم المجموعة للشيفرة البرمجية التي قد تبدو أفضل داخل صنف المجموعة نفسها.
 
== انظر أيضًا ==
 
== انظر أيضًا ==
سطر 39: سطر 39:
  
 
== مصادر ==
 
== مصادر ==
* [https://refactoring.guru/encapsulate-collection صفحة توثيق تغليف المجموعات في موقع refactoring.guru].     [[تصنيف:Refactoring]]     [[تصنيف:Refactoring Techniques]]     [[تصنيف:Refactoring Organizing Data]]
+
* [https://refactoring.guru/encapsulate-collection صفحة توثيق تغليف المجموعات في موقع refactoring.guru].     [[تصنيف:Refactoring]]     [[تصنيف:Refactoring Techniques]]     [[تصنيف:Refactoring Organizing Data]]

المراجعة الحالية بتاريخ 11:55، 2 مارس 2019

المشكلة

صنف يحتوي على حقل مجموعة وجالب (getter) وضابط (setter) بسيط للعمل مع المجموعة.

الحل

ضبط القيمة المعادة من الجالب لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.

مثال

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

يحتوي الصنف Person على جالب getCourses وضابط setCourses بسيطين للتحكم بالدروس التي سجل بها الشخص:

صنف يحتوي على حقل مجموعة ومتلقي (getter) وضابط (setter) بسيط للعمل مع المجموعة.
صنف يحتوي على حقل مجموعة وجالب (getter) وضابط (setter) بسيط للعمل مع المجموعة.

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

ضبط القيمة المعادة من الجالب setCourses لتصبح للقراءة فقط وإضافة تابعين جديدين أحدهما لإضافة دروس جديدة للشخص (أي addCourses)، والآخر لحذف دروس محددة (أي removeCourses):

ضبط القيمة المعادة من المتلقي لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.
ضبط القيمة المعادة من الجالب لتكون للقراءة فقط وإنشاء توابع لإضافة/حذف عناصر المجموعة.

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

يحتوي الصنف على حقل يحتوي بدوره على مجموعة من الكائنات. يمكن أن تكون هذه المجموعة مصفوفة أو قائمة أو مجموعة أو مُتجه (vector). يُنشَأ جالب وضابط طبيعي للعمل مع المجموعة.

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

بالإضافة إلى ذلك، يجب ألَّا يكون هناك تابع يحدد قيمة للمجموعة. بدلًا من ذلك ينبغي أن تكون هناك عمليات لإضافة العناصر وحذفها. بفضل هذا، يتحكم الكائن المالك في إضافة عناصر المجموعة وحذفها.

يُغلِّف مثل هذا البروتوكول المجموعة بشكل صحيح، مما يقلل في النهاية من درجة الارتباط بين الصنف المالك وشيفرة العميل.

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

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

آلية الحل

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

انظر أيضًا

مصادر