---
title: "Code Refactoring with Parameterization"
description: "Reducing complexity by refactoring with parameterization."
canonical: https://oozou.com/blog/code-refactoring-with-parameterization-27
locale: en
date: 2017-07-10
author: "OOZOU Team"
---

# Code Refactoring with Parameterization

> Reducing complexity by refactoring with parameterization.

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

> _Update (13 July 2017): I fix the wrong weight average logic in the code and also provide a working example that you could run on your machine. :awesome:_

There are multiple occasion that I came across an ‘almost similar’ chunk of codes all over the code base. The problem with this kind of code smell is, once you want to change just a tiny bit of that particular function, you need to find all the implementation you did and change all of them which is not a good idea.

> _Duplicate code is a major cause of unmaintainable scripts.
> fancy-quote_

_Brian Marick @ Everyday Scripting with Ruby
_
The technique that I often use and find it’s super easy to do is _parameterization._ Today I’ll explain how that works by a nice little example.

**Finding weight average**

There are reports that I need to find a weight average of a _gross profit_ field and they are going to be weighted by _sale revenue_. Here is what I came up with. (in 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
```

Simple stuff right? Now we need another method that does this exact same thing but for another field called _cogs._ The easiest thing here is to just duplicate the method and change what’s need to be changed.

```
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
```

> _Make it work, then make it right ❤
> fancy-quote_

We got what we want right? Cool but what if we need weight average of other stuff? What if we need to change the weight from _sale_revenue_ to something else? Creating new method that shares this logic would lead us to the problem I was talking about earlier., the duplication problem.

**Parameterization in action**

Now what do we see, these two methods is almost identical right? The only different is the block I passed into the map function.

Extract the similar codes out and put them in the new method. I’ll call it w_avg then parameterized the differences.

> _Notes: Ruby can dynamically calls a function by passing string or symbol to the method_ [_send_](https://ruby-doc.org/core-2.4.1/Object.html#method-i-send)

I’ve remove the duplicate method now and our program look like this.

```
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
```

Now the logic of these two methods are in the same place. I can easily extend it to compute a weight_avg of any value from the report with a one-lined function.

[
Here is a link to a working version of this Ruby program](https://gist.github.com/vtno/667ec4e0c901e829251b01bbf4c97beb)

**_
Download it and run it
_**

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

**Going further**

Parameterization is a nice little trick but it is not a silver bullet. Sometimes it is wiser to have small amount of duplications than one over abstracted method than cannot be extended or modify. As Sandi Metz stated in RailsConference 2014

> [Duplication is far cheaper than the wrong abstraction.](https://www.sandimetz.com/blog/2016/1/20/the-wrong-abstraction)
> fancy-quote

**Final Note**

I believe we should focus not only on making things work but also on creating a clean code base that can be easily maintained by any developer carry on the project.

---

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

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