Refactor to prevent duplication

Link to this posting

Postby Ursego » 21 Feb 2013, 21:05

Refactor identical code. Merge functions with duplicating functionality into one generic function.

If such a functions appear in classes inherited from a same ancestor, create the generic function in the ancestor and call it from the descendants. If the classes are not inherited from one ancestor then create the generic function in a third class (even if you have to create that class only for one function!). If you find yourself thinking whether to duplicate code using copy-paste (10 minutes of work) or take it to a third place (2 hours including testing) - stop thinking immediately! NEVER THINK ABOUT THAT, even in last days of your contract with that company- SIMPLY TAKE THE CODE TO A THIRD PLACE and call it from where needed. If you are still in doubt about spending your time (which really belongs to the company) - ask your manager, but it's better to do the work well and after that, if needed, to explain the manager why it has taken longer time: if the manager understands what the quality programming is then your effort will be appreciated!

Refactor similar code. Merge functions with similar functionality into one generic function.

If the functions, being taken by you into a third place to prevent duplication, are very similar but not exactly identical, then you need to exploit your brain a little bit more. Do the following:
1. Merge the original scripts as described in "Refactor identical code" removing code duplication in the maximum way you can.
2. Supply the different stuff (unique for each original function) from the original location of the moved code.
For example, we have two original functions in different classes that are like these (fragments 1 and 2 of the second object are exactly as fragments 1 and 2 accordingly of the first class, but the DataObjects are different):

*** BAD code: ***

someFunction() of the first class:
Code: Select all
[fragment 1]
this.entityDesc = "Car";
[fragment 2]

someFunction() of the second class:
Code: Select all
[fragment 1] // exactly like [fragment 1] in the first class
this.entityDesc = "Bike"; // oops, this line is different...
[fragment 2] // exactly like [fragment 2] in the first class

*** GOOD code: ***

someFunction() taken into the ancestor class:
Code: Select all
[fragment 1]
this.entityDesc = this.getEntityDesc();
[fragment 2]

So, we use the function getEntityDesc() to overcome the problem of difference between two the discussed functions. getEntityDesc() is created in the ancestor class. Create it as a virtual function if your programming language supports them. If doesn't support (so you are forced to implement the function in the ancestor level) then display an error message or throw an exception letting know that this code must not be ever called, and the purpose of this function is to be overridden. The function must be implemented in the descendant classes to supply the circumstances-specific information (entities descriptions in our example): in the first descendant the function should be coded as return "Car";, in the second one - as return "Bike";.

If the function is taken into a third class (which doesn't belong to the inheritance hierarchy) then the SPECIFIC (different) data can be supplied as argument(s) of the new merged function, so the fragment this.entityDesc = this.getEntityDesc(); will become this.entityDesc = newEntityDesc; where newEntityDesc is the function's argument.

Finally, there is one more method to achieve the goal - we can populate the entityDesc instance variable while initializing the instance (for example, in its constructor), but this approach is not always applicable.

So, that is the rule to obey:


In one of my projects the old problem of duplicated "almost same" code was so serious that I suggested to perform refactoring of entire application sub-system, and my suggestion was accepted - I spent a week doing that, and it was one of the most interesting tasks in my career! As a result, my resume was decorated with the following beautiful fragment:

Proposed and performed code refactoring of existing corporative reporting system, moving duplicating functionality from descendant to ancestor classes. Facilitated maintenance and troubleshooting and made adding of new reports much easier and quicker.

But, of course, it's better to spend some time before development and think how to organize classes instead of thoughtless straightforward coding which forces the keys Ctrl+C and Ctrl+V to work hard.
User avatar
Site Admin
Posts: 124
Joined: 19 Feb 2013, 20:33

IF you want to ((lose weight) OR (have unbelievable (brain function AND mental clarity))) THEN click:

free counters

eXTReMe Tracker