الفرق بين المراجعتين لصفحة: «Refactoring/extract variable»

من موسوعة حسوب
طلا ملخص تعديل
ط مراجعة وتدقيق.
 
(1 مراجعات متوسطة بواسطة نفس المستخدم غير معروضة)
سطر 1: سطر 1:
<noinclude>{{DISPLAYTITLE:استخراج المتغيرات (Extract Methods)}}</noinclude>
<noinclude>{{DISPLAYTITLE:استخراج المتغيرات (Extract Variables)}}</noinclude>
== المشكلة ==
== المشكلة ==
وجود تعبيرٍ (expression) معقِّد يصعُب فهمه.
وجود تعبيرٍ (expression) معقِّد يصعُب فهمه.
سطر 11: سطر 11:
نلاحظ وجود تعبيرٍ شرطيٍّ (conditional expression) معقَّدٍ وبعدّة أجزاء كما في الشيفرة الآتية:
نلاحظ وجود تعبيرٍ شرطيٍّ (conditional expression) معقَّدٍ وبعدّة أجزاء كما في الشيفرة الآتية:


a<syntaxhighlight lang="java">
في لغة Java:<syntaxhighlight lang="java">
void renderBanner() {
void renderBanner() {
   if ((platform.toUpperCase().indexOf("MAC") > -1) &&
   if ((platform.toUpperCase().indexOf("MAC") > -1) &&
سطر 17: سطر 17:
         wasInitialized() && resize > 0 )
         wasInitialized() && resize > 0 )
   {
   {
     // do something
     // افعل شيئًا
   }
   }
}
}


</syntaxhighlight>في لغة #C:<syntaxhighlight lang="c#">
void RenderBanner()
{
  if ((platform.ToUpper().IndexOf("MAC") > -1) &&
      (browser.ToUpper().IndexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // افعل شيئًا
  }
}
</syntaxhighlight>في لغة PHP:<syntaxhighlight lang="php">
if (($platform->toUpperCase()->indexOf("MAC") > -1) &&
    ($browser->toUpperCase()->indexOf("IE") > -1) &&
      $this->wasInitialized() && $this->resize > 0)
{
  // افعل شيئًا
}
</syntaxhighlight>في لغة Python:<syntaxhighlight lang="python">
def renderBanner(self):
    if (self.platform.toUpperCase().indexOf("MAC") > -1) and \
      (self.browser.toUpperCase().indexOf("IE") > -1) and \
      self.wasInitialized() and (self.resize > 0):
        # افعل شيئًا
</syntaxhighlight>في لغة TypeScript:<syntaxhighlight lang="typescript">
renderBanner(): void {
  if ((platform.toUpperCase().indexOf("MAC") > -1) &&
      (browser.toUpperCase().indexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // افعل شيئًا
  }
}
</syntaxhighlight>
</syntaxhighlight>


=== بعد إعادة التصميم ===
=== بعد إعادة التصميم ===
ستحتوي كلٌّ من المتغيِّرات <code>isMacOs</code> و <code>isIE</code> و <code>wasResized</code> قيمةً منطقيّةً (boolean) ناتجةً عن المُعامِل المنطقي <code><</code>، وستُستخدَم تلك المتغيِّرات في الشرط ليصبح أسهل فهمًا وقراءةً كما في الشيفرة:<syntaxhighlight lang="java">
ستحتوي كلٌّ من المتغيِّرات <code>isMacOs</code> و <code>isIE</code> و <code>wasResized</code> قيمةً منطقيّةً (boolean) ناتجةً عن المُعامِل المنطقي <code><</code>، وستُستخدَم تلك المتغيِّرات في الشرط ليصبح أسهل فهمًا وقراءةً كما في الشيفرة:
 
في لغة Java:<syntaxhighlight lang="java">
void renderBanner() {
void renderBanner() {
   final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
   final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
سطر 35: سطر 69:
}
}


</syntaxhighlight>في لغة #C:<syntaxhighlight lang="c#">
void RenderBanner()
{
  readonly bool isMacOs = platform.ToUpper().IndexOf("MAC") > -1;
  readonly bool isIE = browser.ToUpper().IndexOf("IE") > -1;
  readonly bool wasResized = resize > 0;
  if (isMacOs && isIE && wasInitialized() && wasResized)
  {
    // افعل شيئًا
  }
}
</syntaxhighlight>في لغة PHP:<syntaxhighlight lang="php">
$isMacOs = $platform->toUpperCase()->indexOf("MAC") > -1;
$isIE = $browser->toUpperCase()->indexOf("IE")  > -1;
$wasResized = $this->resize > 0;
if ($isMacOs && $isIE && $this->wasInitialized() && $wasResized) {
  // افعل شيئًا
}
</syntaxhighlight>في لغة Python:<syntaxhighlight lang="python">
def renderBanner(self):
    isMacOs = self.platform.toUpperCase().indexOf("MAC") > -1
    isIE = self.browser.toUpperCase().indexOf("IE") > -1
    wasResized = self.resize > 0
    if isMacOs and isIE and self.wasInitialized() and wasResized:
        # افعل شيئًا
</syntaxhighlight>في لغة TypeScript:<syntaxhighlight lang="typescript">
renderBanner(): void {
  const isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
  const isIE = browser.toUpperCase().indexOf("IE") > -1;
  const wasResized = resize > 0;
  if (isMacOs && isIE && wasInitialized() && wasResized) {
    // افعل شيئًا
  }
}
</syntaxhighlight>
</syntaxhighlight>


سطر 58: سطر 130:
* [[Refactoring/extract method|استخراج التوابع]].
* [[Refactoring/extract method|استخراج التوابع]].
* [[Refactoring/inline method|دمج التوابع]].
* [[Refactoring/inline method|دمج التوابع]].
* [[Refactoring/inline tem|دمج المتغيِّر المؤقّت]].
* [[Refactoring/inline temp|دمج المتغيِّر المؤقّت]].


= مصادر =
= مصادر =
* [https://refactoring.guru/extract-variable صفحة توثيق استخراج المتغيرات في موقع refactoring.guru.]
* [https://refactoring.guru/extract-variable صفحة توثيق استخراج المتغيرات في موقع refactoring.guru.]
[[تصنيف: Refactoring]]
[[تصنيف:Refactoring]]
[[تصنيف:Refactoring Techniques]]
[[تصنيف:Refactoring Composing Methods]]

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

المشكلة

وجود تعبيرٍ (expression) معقِّد يصعُب فهمه.

الحل

وضع ناتج التعبير أو جزءٍ منه في متغيِّرات (variables) واضحةٍ تُسهِّل الفهم.

مثال

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

نلاحظ وجود تعبيرٍ شرطيٍّ (conditional expression) معقَّدٍ وبعدّة أجزاء كما في الشيفرة الآتية:

في لغة Java:

void renderBanner() {
  if ((platform.toUpperCase().indexOf("MAC") > -1) &&
       (browser.toUpperCase().indexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // افعل شيئًا
  }
}

في لغة #C:

void RenderBanner() 
{
  if ((platform.ToUpper().IndexOf("MAC") > -1) &&
       (browser.ToUpper().IndexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // افعل شيئًا
  }
}

في لغة PHP:

if (($platform->toUpperCase()->indexOf("MAC") > -1) &&
     ($browser->toUpperCase()->indexOf("IE") > -1) &&
      $this->wasInitialized() && $this->resize > 0)
{
  // افعل شيئًا
}

في لغة Python:

def renderBanner(self):
    if (self.platform.toUpperCase().indexOf("MAC") > -1) and \
       (self.browser.toUpperCase().indexOf("IE") > -1) and \
       self.wasInitialized() and (self.resize > 0):
        # افعل شيئًا

في لغة TypeScript:

renderBanner(): void {
  if ((platform.toUpperCase().indexOf("MAC") > -1) &&
       (browser.toUpperCase().indexOf("IE") > -1) &&
        wasInitialized() && resize > 0 )
  {
    // افعل شيئًا
  }
}

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

ستحتوي كلٌّ من المتغيِّرات isMacOs و isIE و wasResized قيمةً منطقيّةً (boolean) ناتجةً عن المُعامِل المنطقي <، وستُستخدَم تلك المتغيِّرات في الشرط ليصبح أسهل فهمًا وقراءةً كما في الشيفرة:

في لغة Java:

void renderBanner() {
  final boolean isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
  final boolean isIE = browser.toUpperCase().indexOf("IE") > -1;
  final boolean wasResized = resize > 0;

  if (isMacOs && isIE && wasInitialized() && wasResized) {
    // افعل شيئًا هنا
  }
}

في لغة #C:

void RenderBanner() 
{
  readonly bool isMacOs = platform.ToUpper().IndexOf("MAC") > -1;
  readonly bool isIE = browser.ToUpper().IndexOf("IE") > -1;
  readonly bool wasResized = resize > 0;

  if (isMacOs && isIE && wasInitialized() && wasResized) 
  {
    // افعل شيئًا
  }
}

في لغة PHP:

$isMacOs = $platform->toUpperCase()->indexOf("MAC") > -1;
$isIE = $browser->toUpperCase()->indexOf("IE")  > -1;
$wasResized = $this->resize > 0;

if ($isMacOs && $isIE && $this->wasInitialized() && $wasResized) {
  // افعل شيئًا
}

في لغة Python:

def renderBanner(self):
    isMacOs = self.platform.toUpperCase().indexOf("MAC") > -1
    isIE = self.browser.toUpperCase().indexOf("IE") > -1
    wasResized = self.resize > 0

    if isMacOs and isIE and self.wasInitialized() and wasResized:
        # افعل شيئًا

في لغة TypeScript:

renderBanner(): void {
  const isMacOs = platform.toUpperCase().indexOf("MAC") > -1;
  const isIE = browser.toUpperCase().indexOf("IE") > -1;
  const wasResized = resize > 0;

  if (isMacOs && isIE && wasInitialized() && wasResized) {
    // افعل شيئًا
  }
}

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

يهدف استخراجُ المتغيِّرات إلى تبسيط التعابير المعقَّدة عبر تقسيمها لعدّة أجزاء مرحليّة، وهذا يشمل:

  • التعابير الشرطيّة للمعامل if أو أيَّ جزءٍ من المعامل الثلاثي ‎?:‎ في لغات البرمجة المعتمدة على لغة C‏ (C-based).
  • التعابير الرياضيّة (arithmetic) الطويلة غير المعتمدة على النتائج المرحليّة.
  • الأسطر الطويلة متعددة الأجزاء.

وقد يكون استخراج المتغيِّرات كخطوةٍ سابقةٍ لاستخراج التوابع (extract methods) إن كان التعبير المُستخرَج مستخدمًا بمواضع متفرِّقة في الشيفرة.

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

الحصول على شيفرة واضحةٍ سهلة القراءة وخاصّة بإعطاء المتغيِّرات أسماء معبِّرةً مساعدةً توضِّح عيانًا الهدف من المتغيِّر، مثل: customerTaxValue و cityUnemploymentRate و clientSalutationString و ...إلخ. إذ كلما زادت قابلية قراءة الشيفرة (code readability) قلّت الحاجة إلى التعليقات (comments) التوضيحيّة الطويلة.

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

احتواء الشيفرة متغيِّراتٍ إضافيّةً ولكنّ توضيح الشيفرة وتحسينها يبرِّران ذلك.

آلية الحل

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

انظر أيضًا

مصادر