الفرق بين المراجعتين لصفحة: «Refactoring/separate query from modifier»

من موسوعة حسوب
طلا ملخص تعديل
ط مراجعة وتدقيق.
 
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE: فصل الاستعلامات عن المُعدِّلات (Separate Query from Modifier)}}</noinclude>   
<noinclude>{{DISPLAYTITLE: فصل الاستعلامات عن المُعدِّلات (Separate Query from Modifier)}}</noinclude>   
== المشكلة ==
== المشكلة ==
هل لديك تابع يُعيد قيمة ما ولكن يغيِّر أيضا شيئًا ما داخل الكائن؟
هل لديك تابعٌ يُعيد قيمةً ما ولكن يغيِّر أيضا شيئًا ما داخل الكائن؟


== الحل ==
== الحل ==
سطر 9: سطر 9:


==== قبل إعادة التصميم ====
==== قبل إعادة التصميم ====
[[ملف:Separate Query from Modifier - Before.png|بديل=تابع يُعيد قيمة ويغيِّر شيئًا ما داخل الكائن.|بدون|تصغير|تابع يُعيد قيمة ويغيِّر  شيئًا ما داخل الكائن.]]
ينفذ التابع <code>()getTotlaOutstandingAndSetReadyForSummaries</code> في الصنف <code>Customer</code> مهمتين، إذ يعيد قيمة ويضبط قيمة أخرى في الكائن:[[ملف:Separate Query from Modifier - Before.png|بديل=تابع يُعيد قيمة ويغيِّر شيئًا ما داخل الكائن.|بدون|تصغير|تابع يُعيد قيمة ويغيِّر  شيئًا ما داخل الكائن.]]


==== بعد إعادة التصميم ====
==== بعد إعادة التصميم ====
[[ملف:Separate Query from Modifier - After.png|بديل=يقسَّم التابع إلى تابعَين منفصلَين.|بدون|تصغير|يقسَّم التابع إلى تابعَين منفصلَين.]]
فصل التابع التابع <code>()getTotlaOutstandingAndSetReadyForSummaries</code> إلى تابعين هما: الأول <code>()getTotlaOutstanding</code> لجلب قيمة، والآخر <code>()setReadyForSummaries</code> لضبط حالةٍ في الكائن:[[ملف:Separate Query from Modifier - After.png|بديل=يقسَّم التابع إلى تابعَين منفصلَين.|بدون|تصغير|يقسَّم التابع إلى تابعَين منفصلَين.]]


== لم إعادة التصميم؟ ==
== لم إعادة التصميم؟ ==
تفصل تقنية إعادة التصميم هذه مسؤولية الأوامر عن الاستعلامات (Command and Query Responsibility Segregation). ويدعو هذا المبدأ إلى فصل شيفرة الحصول على البيانات عن الشيفرة التي تغير شيئًا داخل الكائن.
تفصل تقنية إعادة التصميم هذه مسؤولية الأوامر عن الاستعلامات (Command and Query Responsibility Segregation). ويدعو هذا المبدأ إلى فصل شيفرة الحصول على البيانات عن الشيفرة التي تغير شيئًا داخل الكائن.


وتسمَّى شيفرة الحصول علي البيانات الاستعلام (query). وتسمَّى شيفرة تغيير الأشياء في الحالة المرئية للكائن مُعدِّل modifier. عند الجمع بين الاستعلام والمُعدِّل، لن يكون لديك سبيل للحصول علي البيانات دون إجراء تغييرات علي حالتها. وبعبارة أخرى، يمكنك أن تطرح السؤال وتغيير الإجابة حتى أثناء تلقيها. وتزداد هذه المشكلة حدة عندما لا يعرف الشخص الذي يستدعي الاستعلام عن "الآثار الجانبية" للتابع، التي كثيرًا ما تؤدي إلى أخطاء وقت التشغيل.
وتسمَّى شيفرة التي تجلب بيانات "استعلام" (query). وتسمَّى شيفرة التي تغير الأشياء في الحالة المرئية (visible state) للكائن "مُعدِّل" (modifier). عند الجمع بين الاستعلام والمُعدِّل، لن يكون لديك سبيل للحصول على البيانات دون إجراء تغييرات على حالتها. وبعبارة أخرى، يمكنك أن تطرح السؤال وتغير الإجابة حتى أثناء تلقيها. وتزداد هذه المشكلة حدةً عندما لا يعرف الشخص الذي يستدعي الاستعلام عن "الآثار الجانبية" للتابع، التي كثيرًا ما تؤدي إلى أخطاء وقت التشغيل.


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


== فوائد تطبيق الحل ==
== فوائد تطبيق الحل ==
سطر 25: سطر 25:


== مساوئ تطبيق الحل ==
== مساوئ تطبيق الحل ==
* في بعض الحالات يكون من الملائم الحصول على البيانات بعد تنفيذ الأمر. على سبيل المثال، عند حذف شيء من قاعدة البيانات تريد أن تعرف عدد الصفوف التي حُذفت.
* في بعض الحالات يكون من الملائم الحصول على البيانات بعد تنفيذ أمر. على سبيل المثال، عند حذف شيء من قاعدة البيانات، تريد أن تعرف عدد الصفوف التي حُذفت.


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


== انظر أيضًا ==
== انظر أيضًا ==
سطر 40: سطر 40:
[[تصنيف:Refactoring]]
[[تصنيف:Refactoring]]
[[تصنيف:Refactoring Techniques]]
[[تصنيف:Refactoring Techniques]]
[[تصنيف:Simplifying Method Calls]]
[[تصنيف:Refactoring Simplifying Method Calls]]

المراجعة الحالية بتاريخ 14:17، 25 فبراير 2019

المشكلة

هل لديك تابعٌ يُعيد قيمةً ما ولكن يغيِّر أيضا شيئًا ما داخل الكائن؟

الحل

تقسيم التابع إلى تابعَين منفصلَين. كما يمكن أن نتوقع، يجب على أحدهما أن يعيد القيمة ويُغيِّر الآخر الكائن.

مثال

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

ينفذ التابع ()getTotlaOutstandingAndSetReadyForSummaries في الصنف Customer مهمتين، إذ يعيد قيمة ويضبط قيمة أخرى في الكائن:

تابع يُعيد قيمة ويغيِّر شيئًا ما داخل الكائن.
تابع يُعيد قيمة ويغيِّر شيئًا ما داخل الكائن.

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

فصل التابع التابع ()getTotlaOutstandingAndSetReadyForSummaries إلى تابعين هما: الأول ()getTotlaOutstanding لجلب قيمة، والآخر ()setReadyForSummaries لضبط حالةٍ في الكائن:

يقسَّم التابع إلى تابعَين منفصلَين.
يقسَّم التابع إلى تابعَين منفصلَين.

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

تفصل تقنية إعادة التصميم هذه مسؤولية الأوامر عن الاستعلامات (Command and Query Responsibility Segregation). ويدعو هذا المبدأ إلى فصل شيفرة الحصول على البيانات عن الشيفرة التي تغير شيئًا داخل الكائن.

وتسمَّى شيفرة التي تجلب بيانات "استعلام" (query). وتسمَّى شيفرة التي تغير الأشياء في الحالة المرئية (visible state) للكائن "مُعدِّل" (modifier). عند الجمع بين الاستعلام والمُعدِّل، لن يكون لديك سبيل للحصول على البيانات دون إجراء تغييرات على حالتها. وبعبارة أخرى، يمكنك أن تطرح السؤال وتغير الإجابة حتى أثناء تلقيها. وتزداد هذه المشكلة حدةً عندما لا يعرف الشخص الذي يستدعي الاستعلام عن "الآثار الجانبية" للتابع، التي كثيرًا ما تؤدي إلى أخطاء وقت التشغيل.

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

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

  • إذا كان لديك استعلام لا يغير حالة البرنامج، يمكنك استدعائه مرات عديدة كما تريد دون الحاجة إلى القلق حول التغييرات غير المقصودة في النتيجة الناتجة عن مجرد حقيقة استدعاء التابع.

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

  • في بعض الحالات يكون من الملائم الحصول على البيانات بعد تنفيذ أمر. على سبيل المثال، عند حذف شيء من قاعدة البيانات، تريد أن تعرف عدد الصفوف التي حُذفت.

آلية الحل

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

انظر أيضًا

مصادر