الفرق بين المراجعتين ل"Refactoring/replace parameter with method call"

من موسوعة حسوب
اذهب إلى التنقل اذهب إلى البحث
ط
ط (مراجعة وتدقيق.)
سطر 1: سطر 1:
 
<noinclude>{{DISPLAYTITLE: تبديل المعاملات باستدعاءات التوابع (Replace Parameter with Method Call)}}</noinclude>  
 
<noinclude>{{DISPLAYTITLE: تبديل المعاملات باستدعاءات التوابع (Replace Parameter with Method Call)}}</noinclude>  
 
== المشكلة ==
 
== المشكلة ==
استدعاء تابع استعلام وتمرير نتائجه كمعاملات لتابع آخر، في حين أنه يمكن لهذا التابع استدعاء الاستعلام مباشرة.
+
استدعاء تابع استعلام (query method) وتمرير نتائجه كمعاملات لتابع آخر، في حين أنه يمكن لهذا التابع استدعاء الاستعلام مباشرة.
  
 
== الحل ==
 
== الحل ==
سطر 9: سطر 9:
  
 
==== قبل إعادة التصميم ====
 
==== قبل إعادة التصميم ====
في لغة Java:<syntaxhighlight lang="java">
+
تخزين القيمة التي يعيدها كلٌّ من التابعين <code>()getSeasonalDiscount</code> و <code>()getFees</code> في متغير ثم تمريرها إلى التابع <code>()discountedPrice</code>:
 +
 
 +
في لغة [[Java]]:<syntaxhighlight lang="java">
 
int basePrice = quantity * itemPrice;
 
int basePrice = quantity * itemPrice;
 
double seasonDiscount = this.getSeasonalDiscount();
 
double seasonDiscount = this.getSeasonalDiscount();
 
double fees = this.getFees();
 
double fees = this.getFees();
 
double finalPrice = discountedPrice(basePrice, seasonDiscount, fees);
 
double finalPrice = discountedPrice(basePrice, seasonDiscount, fees);
</syntaxhighlight>في لغة C#‎:<syntaxhighlight lang="c#">
+
</syntaxhighlight>في لغة [[C#]]‎:<syntaxhighlight lang="c#">
 
int basePrice = quantity * itemPrice;
 
int basePrice = quantity * itemPrice;
 
double seasonDiscount = this.GetSeasonalDiscount();
 
double seasonDiscount = this.GetSeasonalDiscount();
 
double fees = this.GetFees();
 
double fees = this.GetFees();
 
double finalPrice = DiscountedPrice(basePrice, seasonDiscount, fees);
 
double finalPrice = DiscountedPrice(basePrice, seasonDiscount, fees);
</syntaxhighlight>في لغة PHP:<syntaxhighlight lang="php">
+
</syntaxhighlight>في لغة [[PHP]]:<syntaxhighlight lang="php">
 
$basePrice = $this->quantity * $this->itemPrice;
 
$basePrice = $this->quantity * $this->itemPrice;
 
$seasonDiscount = $this->getSeasonalDiscount();
 
$seasonDiscount = $this->getSeasonalDiscount();
 
$fees = $this->getFees();
 
$fees = $this->getFees();
 
$finalPrice = $this->discountedPrice($basePrice, $seasonDiscount, $fees);
 
$finalPrice = $this->discountedPrice($basePrice, $seasonDiscount, $fees);
</syntaxhighlight>في لغة Python:<syntaxhighlight lang="python">
+
</syntaxhighlight>في لغة [[Python]]:<syntaxhighlight lang="python">
 
basePrice = quantity * itemPrice
 
basePrice = quantity * itemPrice
 
seasonalDiscount = this.getSeasonalDiscount()
 
seasonalDiscount = this.getSeasonalDiscount()
 
fees = this.getFees()
 
fees = this.getFees()
 
finalPrice = discountedPrice(basePrice, seasonalDiscount, fees)
 
finalPrice = discountedPrice(basePrice, seasonalDiscount, fees)
 +
</syntaxhighlight>في لغة [[TypeScript]]:<syntaxhighlight lang="typescript">
 +
let basePrice = quantity * itemPrice;
 +
const seasonDiscount = this.getSeasonalDiscount();
 +
const fees = this.getFees();
 +
const finalPrice = discountedPrice(basePrice, seasonDiscount, fees);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
==== بعد إعادة التصميم ====
 
==== بعد إعادة التصميم ====
في لغة Java:<syntaxhighlight lang="java">
+
استدعاء التابعين السابقين ضمن التابع <code>()discountedPrice</code> نفسه:
 +
 
 +
في لغة [[Java]]:<syntaxhighlight lang="java">
 
int basePrice = quantity * itemPrice;
 
int basePrice = quantity * itemPrice;
 
double finalPrice = discountedPrice(basePrice);
 
double finalPrice = discountedPrice(basePrice);
  
</syntaxhighlight>في لغة C#‎:<syntaxhighlight lang="c#">
+
</syntaxhighlight>في لغة [[C#‎]]:<syntaxhighlight lang="c#">
 
int basePrice = quantity * itemPrice;
 
int basePrice = quantity * itemPrice;
 
double finalPrice = DiscountedPrice(basePrice);
 
double finalPrice = DiscountedPrice(basePrice);
</syntaxhighlight>في لغة PHP:<syntaxhighlight lang="php">
+
</syntaxhighlight>في لغة [[PHP]]:<syntaxhighlight lang="php">
 
$basePrice = $this->quantity * $this->itemPrice;
 
$basePrice = $this->quantity * $this->itemPrice;
 
$finalPrice = $this->discountedPrice($basePrice);
 
$finalPrice = $this->discountedPrice($basePrice);
</syntaxhighlight>في لغة Python:<syntaxhighlight lang="python">
+
</syntaxhighlight>في لغة [[Python]]:<syntaxhighlight lang="python">
 
basePrice = quantity * itemPrice
 
basePrice = quantity * itemPrice
 
finalPrice = discountedPrice(basePrice)
 
finalPrice = discountedPrice(basePrice)
 +
</syntaxhighlight>في [[TypeScript]]:<syntaxhighlight lang="typescript">
 +
let basePrice = quantity * itemPrice;
 +
let finalPrice = discountedPrice(basePrice);
 
</syntaxhighlight>
 
</syntaxhighlight>
  
 
== لم إعادة التصميم؟ ==
 
== لم إعادة التصميم؟ ==
من الصعب فهم قائمة طويلة من المعاملات. إضافة إلى ذلك، غالبًا ما تشبه استدعاءات مثل هذه التوابع سلسلةً من الشلالات، ذات حسابات قيم ملتوية ومتكررة والتي يصعب تتبعها مع وجوب تمريرها إلى التابع. لذا إذا كان يمكن حساب قيمة المعامل بمساعدة تابع ما، فافعل ذلك داخل التابع نفسه وتخلص من المعامل.
+
من الصعب فهم قائمة طويلة من المعاملات. إضافة إلى ذلك، غالبًا ما تشبه استدعاءات مثل هذه التوابع سلسلةً من الشلالات، ذات حسابات قيم ملتوية ومتكررة يصعب تتبعها مع وجوب تمريرها إلى التابع. لذا، إذا كان يمكن حساب قيمة المعامل بمساعدة تابع ما، فافعل ذلك داخل التابع نفسه وتخلص من المعامل.
  
 
== فوائد تطبيق الحل ==
 
== فوائد تطبيق الحل ==
سطر 54: سطر 66:
  
 
== مساوئ تطبيق الحل ==
 
== مساوئ تطبيق الحل ==
* قد تحتاج إلى المعامل في الغد القريب لتلبية احتياجاتٍ أخرى... الأمر الذي يجعلك تعيد كتابة التابع.
+
* قد تحتاج إلى المعامل في الغد القريب لتلبية احتياجاتٍ أخرى الأمر الذي يجعلك تعيد كتابة التابع.
  
 
== آلية الحل ==
 
== آلية الحل ==
# تأكد من أن شيفرة الحصول على القيمة لا تستخدم معاملات من التابع الحالي، لأنها لن تكون متاحة من داخل التوابع أخرى. إذا كان الأمر كذلك، فلن يكون من الممكن نقل الشيفرة البرمجية.
+
# تأكد من أنَّ شيفرة الحصول على القيمة لا تستخدم معاملات من التابع الحالي، لأنَّها لن تكون متاحة من داخل التوابع أخرى. إذا كان الأمر كذلك، فلن يكون من الممكن نقل الشيفرة البرمجية.
 
# إذا كانت الشيفرة البرمجية ذات الصلة أكثر تعقيدًا من استدعاء تابع أو دالة منفردَين، استخدم [[Refactoring/extract method|استخراج التوابع]] لعزل هذه الشيفرة البرمجية في تابع جديد وجعل الاستدعاء بسيطًا.
 
# إذا كانت الشيفرة البرمجية ذات الصلة أكثر تعقيدًا من استدعاء تابع أو دالة منفردَين، استخدم [[Refactoring/extract method|استخراج التوابع]] لعزل هذه الشيفرة البرمجية في تابع جديد وجعل الاستدعاء بسيطًا.
 
# استبدل جميع المراجع إلى المعامل المراد استبداله بالاستدعاءات إلى التابع الذي يحصل على القيمة داخل شيفرة التابع الرئيسي.
 
# استبدل جميع المراجع إلى المعامل المراد استبداله بالاستدعاءات إلى التابع الذي يحصل على القيمة داخل شيفرة التابع الرئيسي.
سطر 66: سطر 78:
 
[[تصنيف:Refactoring]]
 
[[تصنيف:Refactoring]]
 
[[تصنيف:Refactoring Techniques]]
 
[[تصنيف:Refactoring Techniques]]
[[تصنيف:Simplifying Method Calls]]
+
[[تصنيف:Refactoring Simplifying Method Calls]]

مراجعة 07:49، 26 فبراير 2019

المشكلة

استدعاء تابع استعلام (query method) وتمرير نتائجه كمعاملات لتابع آخر، في حين أنه يمكن لهذا التابع استدعاء الاستعلام مباشرة.

الحل

بدلًا من تمرير القيمة من خلال المعامل، حاول وضع استدعاء الاستعلام داخل متن التابع.

مثال

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

تخزين القيمة التي يعيدها كلٌّ من التابعين ()getSeasonalDiscount و ()getFees في متغير ثم تمريرها إلى التابع ()discountedPrice:

في لغة Java:

int basePrice = quantity * itemPrice;
double seasonDiscount = this.getSeasonalDiscount();
double fees = this.getFees();
double finalPrice = discountedPrice(basePrice, seasonDiscount, fees);

في لغة C#‎:

int basePrice = quantity * itemPrice;
double seasonDiscount = this.GetSeasonalDiscount();
double fees = this.GetFees();
double finalPrice = DiscountedPrice(basePrice, seasonDiscount, fees);

في لغة PHP:

$basePrice = $this->quantity * $this->itemPrice;
$seasonDiscount = $this->getSeasonalDiscount();
$fees = $this->getFees();
$finalPrice = $this->discountedPrice($basePrice, $seasonDiscount, $fees);

في لغة Python:

basePrice = quantity * itemPrice
seasonalDiscount = this.getSeasonalDiscount()
fees = this.getFees()
finalPrice = discountedPrice(basePrice, seasonalDiscount, fees)

في لغة TypeScript:

let basePrice = quantity * itemPrice;
const seasonDiscount = this.getSeasonalDiscount();
const fees = this.getFees();
const finalPrice = discountedPrice(basePrice, seasonDiscount, fees);

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

استدعاء التابعين السابقين ضمن التابع ()discountedPrice نفسه:

في لغة Java:

int basePrice = quantity * itemPrice;
double finalPrice = discountedPrice(basePrice);

في لغة C#‎:

int basePrice = quantity * itemPrice;
double finalPrice = DiscountedPrice(basePrice);

في لغة PHP:

$basePrice = $this->quantity * $this->itemPrice;
$finalPrice = $this->discountedPrice($basePrice);

في لغة Python:

basePrice = quantity * itemPrice
finalPrice = discountedPrice(basePrice)

في TypeScript:

let basePrice = quantity * itemPrice;
let finalPrice = discountedPrice(basePrice);

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

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

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

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

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

  • قد تحتاج إلى المعامل في الغد القريب لتلبية احتياجاتٍ أخرى الأمر الذي يجعلك تعيد كتابة التابع.

آلية الحل

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

مصادر