I am basically a PHP programmer; always writing code in procedural way. A PHP developer won't get much chance to apply object oriented concepts; the server side functionality will be simpler or most of the classes will be already available in the PHP framework he is using.
A few months ago, I started working on Java for an android application. I had to start coding based on high level requirements, and I had no idea what types of classes needed. Moreover, for the first time I was working on a pure object oriented application.
After finishing few modules, got more clear picture of the classes needed in the system. By the time the design of code became complicated: a lot of duplicate code across several classes (violation of DRY principle) and many classes and methods was doing too many tasks( violation of KISS principle). I realized it was high time to improve the design of code. Those days I was deeply thinking how to improve the design.
Finally, I had to improve the design for adding a new feature; otherwise the module for the new feature will be complicated. One weekend I took my laptop to my room and started to make the design better.
- Some classes have similar methods and member variables- Better to create a super class out of these features.
- Some sub-classes of the same parent have similar methods- Better to generalize the method and move to super class.
- Network-connector class have three set of methods. One set is for POST method and another for GET method. The third set is common to both- Better to create two sub-classes (one for POST and another for GET). In future, new HTTP methods will be added as sub-classes.
- Some methods consist of multiple small tasks- Better to create methods to each task and invoke the methods from the original method.
- Some classes are highly coupled- Better to introduce listener classes. (Observer pattern in Design pattern terminology.)
- Most of the anonymous classes extended Network-connector-listener contains many empty methods- Better to introduce adapter classes. (No relation with Adapter pattern).
I was improving the design based on my thoughts and observations without knowing the systematic way of doing it. There is a systematic way to accomplish it; known as refactoring. Refactoring is the technique to improve the design of an already written code by making it simple to understand so that it can be modified easily. If you have experience in object oriented programming, you may have applied many refactoring techniques. The first four steps, I explained above, are given below in refactoring terminology:
- Extract Superclass.
- Pull Up Method
- Extract Subclass
- Extract Method
Exercise for YOU: Find out the refactoring terms for the remaining two steps.
You wanna learn refactoring? You will get good idea about refactoring from Code Complete. You can refer Martin Fowler's classic work Refactoring: Improving The Design Of Existing Code for detailed examples and the systematic way of implementing each refactoring.
According to Martin Fowler, the first major work on refactoring is done by William Opdyke in his doctoral thesis Refactoring Object-Oriented Frameworks. It focus on automating the refactoring process. The large part of refactoring is mechanical work: renaming identifier to make its intention clear, create class by extracting some code from one or more classes, move some code from sub-classes to super class, etc. Automated tools can be used to perform the mechanical task in order to save time and to eliminate manual errors.
You gonna refactor now? Be careful! Refactoring may break your application. Systematic procedure can eliminate the chance of introducing bugs. Use automated tools to avoid manual errors, and run test cases after applying each refactoring.
The first time you do something, you just do it. The second time you do something similar, you wince at the duplication, but you do the duplicate thing anyway. The third time you do something similar, you refactor - Don Robert
Happy and Safe Refactoring!