Say I have this code:
if ($this->ship == "e") {
$this->price->addLine($this->price->base * $this->price->e, 0, "Export");
$this->price->total += $this->price->base * $this->price->e;
} elseif ($this->ship == "d") {
$this->price->addLine($this->price->base * $this->price->d, 0, "Domestic");
$this->price->total += $this->price->base * $this->price->d;
}
I have multiple identical blocks of code like the above. I also have other code (other than $this->ship
) that is similar in structure. Basically, this code adds a Line
to a PDF, where the line says "Domestic" or "Export" along with other options. The code above also computes price for that line and adds it to the total.
My thoughts on refactoring this:
I want to remove duplication. I also want to abide by SOLID principles, i.e. separation of concerns. I see that code above does two things (computes price and adds a line item to PDF). I can surely split this code into two separate functions, but then I still end up with duplicated code -- I need to check if $this->ship
equals e
or d
in both places. That is no good. If I need to add a 3rd option, I have to change code in two places.
So then I can move my check for e
or d
into the main body of code, but still I have duplication because I will have
switch($this->ship)
{
case 'd': $cost = $this->getShippingCost($this->price->base, $this->price->d);break;
case 'e': $cost = $this->getShippingCost($this->price->base, $this->price->e);break;
}
I get these two long lines of code for basically a single character change. While maybe it is kind of acceptable, I am not quite liking it. If I need to change the number of parameters for example, or base parameter or etc, I will need to change it in more than one place.
Basically, so far no matter what way I spin this code, I end up with some duplication somewhere. I mean if it is unavoidable, I guess it's okay. But here I come for advice on seeing if there is a way to separate the concerns, and remove duplication and have minimal number of places (ideally one
) when I do need to change something. can this be done?
$this->price->d
is a ratio used for the type of shipping.$this
is a god-object (en.wikipedia.org/wiki/God_object) of everything$this
is a god-object, then refactoring this small portion of code should be the least of your concerns. It seems that you're using a deeply flawed architecture. This problem should be easily solved with polymorphism (e.g.$price = $Ship->getPrice(); $this->addToTotal($price)
). However, since you're mixing OOP ($this
) with procedural style (getShippingCost()
), it looks like a very fundamental rewrite and redesign is in order.$this->getShippingCost()
. I didn't quite catch what you meant by polymorphism.. If I had a chance to redesign this class .. I would try to redesign the immediate set of classes instead. But since these are line items, and corresponding prices for line items, I'd have to think about how to represent them best, basically go over entities, how they interact, etc. Aline item
will probably be an array of objects sitting inside of a container class, and line item object will contain the price for that item.