Let's fight this monster

/thread
First rule: test coverage, no changes can be made if you're not secured
ideally with mutation testing showing us alive mutants
We're killing this mutant with new tests
Repeat killing mutants until this specific part of code (the IF/ELSE monster) has 100% coverage

please note: I'm not advising the whole project to be 100% covered - only the place which you want to change
Detect the possible types in the IF/ELSE branches

In this case, those are different kinds of products with different behaviour.
Now the goal is to carefully refactor the conditions so that the top-level IF is all about the type. Let's look how we can do it safely and quickly to rearrange the conditions.
Flattening technique
We can merge conditions from subsequent IFs.
Thanks to this, the "type" condition travels one level above.
(remember our goal is to make them to top-level)
Remember DeMorgan laws from Algebra classes?

They can be used to reduce the number of negations in the conditions.
the obvious tip: extract methods for better readability
another attempt to reduce the number of negative conditions

here we rely on knowing that there are only 4 types of products - we can replace the negation with checking for different types

we want to have positive flow instead of negative
at top-level we want to have one IF body per each type
we duplicate OR bodies to achieve that
thanks to this duplication some logic is now clearly wrong

here it's all about spotting that it's an impossible condition - A and ! A - where A is sulfuras
we end with this top-level IF
We move the behaviour to new objects, we use factory methods to create those objects - we use polymorphism to maintain the same API for the new objects. They have the same "update" method.
Those new objects are nice, but they seem to have the same problem - Primitive Obsession. Let's extract a Quality object, instead of treating it as a primitive integer
They look simpler when they use the Quality object
Quality object became a new home for some of the IF rules
Now the main IF/ELSE method is reduced to this.

While the journey is not over (some IFs are to be refactored in those type objects) we can claim some improvement.
If you liked this refactoring session you will enjoy my new "Anti IF" online class

http://arkency.com/anti-ifs/ 

You can access the first edition by the end of Monday. The practical exercises are based on the Gilded Rose refactoring kata. This kata exists in all mainstream languages.
The class also contains the community part - you can post the IF/ELSE monsters that you fight against in your projects and we will help you prepare the refactoring steps.

See you there!
You can follow @andrzejkrzywda.
Tip: mention @twtextapp on a Twitter thread with the keyword “unroll” to get a link to it.

Latest Threads Unrolled: