---
title: "إعادة هيكلة الكود باستخدام التعميم بالمعاملات (Parameterization)"
description: "تقليل التعقيد عبر إعادة هيكلة الكود بأسلوب التعميم بالمعاملات (parameterization)، مع مثال عملي بلغة Ruby."
canonical: https://oozou.com/ar/blog/code-refactoring-with-parameterization-27
locale: ar
date: 2017-07-10
author: "OOZOU Team"
---

# إعادة هيكلة الكود باستخدام التعميم بالمعاملات (Parameterization)

> تقليل التعقيد عبر إعادة هيكلة الكود بأسلوب التعميم بالمعاملات (parameterization).

Published: 2017-07-10 · Author: OOZOU Team (Engineering) · 4 min read

> _تحديث (13 يوليو 2017): أصلحت منطق حساب المتوسط المرجّح الخاطئ في الكود، وأضفت مثالًا عمليًا يمكنكم تشغيله على أجهزتكم. :awesome:_

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

> _الكود المكرر سبب رئيسي في صعوبة صيانة السكربتات.
> fancy-quote_

_Brian Marick في كتاب Everyday Scripting with Ruby
_
الأسلوب الذي أستخدمه كثيرًا وأجده سهلًا للغاية هو _التعميم بالمعاملات (parameterization)._ سأشرح اليوم كيف يعمل من خلال مثال صغير ولطيف.

**حساب المتوسط المرجّح**

لدي تقارير أحتاج فيها إلى حساب المتوسط المرجّح لحقل _إجمالي الربح_، على أن يكون الترجيح بحسب _إيرادات المبيعات_. وهذا ما توصلت إليه (بلغة Ruby).

```
def weight_avg_gross_profit(reports)
  # find total weight, sum of sale_revenue
  total_weight = reports.reduce(0) { |sum, r| sum + r.sale_revenue }

  # find sum products
  sum_prod = reports.reduce do |sum, r|
    sum + (r.percent_gross_profit * r.sale_revenue)
  end

  # simple weight average formula, (w1*x1 + w2*x2) / (w1 + w2)
  sum_prod / total_weight
end
lang-ruby
```

أمر بسيط، أليس كذلك؟ نحتاج الآن إلى دالة أخرى تفعل الشيء نفسه تمامًا، لكن لحقل آخر اسمه _cogs._ وأسهل ما يمكن فعله هنا هو نسخ الدالة وتغيير ما يلزم تغييره.

```
def weight_avg_gross_profit(reports)
  # find total weight, sum of sale_revenue
  total_weight = reports.reduce(0) { |sum, r| sum + r.sale_revenue }

  # find sum products
  sum_prod = reports.reduce(0) do |sum, r|
    sum + (r.percent_gross_profit * r.sale_revenue)
  end

  # simple weight average formula, (w1*x1 + w2*x2) / (w1 + w2)
  sum_prod / total_weight
end

def weight_avg_gross_profit(reports)
  # find total weight, sum of sale_revenue
  total_weight = reports.reduce(0) { |sum, r| sum + r.sale_revenue }

  # find sum products
  sum_prod = reports.reduce(0) do |sum, r|
    sum + (r.cogs * r.sale_revenue)
  end

  # simple weight average formula, (w1*x1 + w2*x2) / (w1 + w2)
  sum_prod / total_weight
end
lang-ruby
```

> _اجعله يعمل أولًا، ثم اجعله صحيحًا ❤
> fancy-quote_

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

**التعميم بالمعاملات عمليًا**

ماذا نلاحظ الآن؟ هاتان الدالتان متطابقتان تقريبًا، أليس كذلك؟ الفرق الوحيد هو الـ block الذي مررته إلى دالة map.

لنستخرج الكود المتشابه ونضعه في دالة جديدة سأسميها w_avg، ثم نحوّل الاختلافات إلى معاملات.

> _ملاحظة: تستطيع Ruby استدعاء دالة ديناميكيًا عبر تمرير string أو symbol إلى الدالة_ [_send_](https://ruby-doc.org/core-2.4.1/Object.html#method-i-send)

حذفت الدالة المكررة، وأصبح برنامجنا يبدو هكذا.

```
def weight_avg_gross_profit(reports)
  weight_avg(reports, 'gross_profit')
end

def weight_avg_cogs(reports)
  weight_avg(reports, 'cogs')
end

def weight_avg(reports, value)
  total_weight =   reports.reduce(0) { |sum, r| sum + r.sale_revenue }
  sum_prod = reports.reduce(0) do |sum, res|
    sum + (res.send(value) * res.sale_revenue)
  end

  sum_prod / total_weight
end
lang-ruby
```

أصبح منطق الدالتين الآن في مكان واحد. ويمكنني بسهولة توسيعه لحساب weight_avg لأي قيمة من التقرير بدالة من سطر واحد.

[
إليكم رابطًا لنسخة عاملة من برنامج Ruby هذا](https://gist.github.com/vtno/667ec4e0c901e829251b01bbf4c97beb)

**_
نزّلوه وشغّلوه
_**

```
ruby parameterized_working_example.rb
lang-bash
```

**خطوة أبعد**

التعميم بالمعاملات حيلة صغيرة لطيفة، لكنه ليس حلًا سحريًا. ففي بعض الأحيان يكون من الحكمة الإبقاء على قدر بسيط من التكرار بدلًا من دالة مفرطة في التجريد لا يمكن توسيعها أو تعديلها. وكما قالت Sandi Metz في RailsConference 2014

> [التكرار أقل تكلفة بكثير من التجريد الخاطئ.](https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction)
> fancy-quote

**ملاحظة أخيرة**

أؤمن بأن علينا ألا نركّز على جعل الأشياء تعمل فحسب، بل على بناء قاعدة كود نظيفة يسهل على أي مطوّر يواصل العمل على المشروع صيانتها.

---

Contact OOZOU: hello@oozou.com · +66 2544 0000 · https://oozou.com/ar/contact

More for AI agents: https://oozou.com/llms.txt · every page has a markdown twin at its URL plus ".md"
