Refactoring could be defined as a process of changing a software system in such a way that it does not alter the external behavior of the code yet improves its internal structure. It is a disciplined way to clean up code that minimizes the chances of introducing bugs. Refactoring certainly makes your program to run slower but it makes more amenable to performance tuning.
Below are some of the methods to identify if your code needs refactoring.
1. Sequence diagram relations differs from Class diagram
This is a very easy catch, the moment you see that a class in a sequence diagram is reaching out to a directly non dependent class, as per class diagram, then you certainly needs to investigate for a refactoring. For example let us consider a class called customer that has a relation with vehicle and which in turn relates with manufacturing company, if there is any access to company class from customer class then there is certainly a need to refactor.
2. Single Responsibility
If any of your classes or its attributes display more than one behavior, it is a sign that there is a scope for breaking down the object and refactor it.
3. Duplicate code
If a block of code is repeated and you think it might change in future, it is time to separate it using (extract method). This is an application of DRY concept.
4. Renaming of classes and properties
Is it worth it? Absolutely, good code should communicate what it does clearly and attribute names are a key to clear code.
5. Method should use data in its own object
In most cases method should be on the object whose data it uses. Other wise there is a possibility of having unwanted interdependence.
6. Too many temporary variables
Temps are often a problem in that they cause lot of parameters to be passed around when don’t have to be. You can easily loose track of what they are there for. They are particularly insidious in long methods. You can use “replace temp with query”.
7. Switch statement based on attribute of another object
It is a bad idea to do a switch based on a attribute of another object. If you must use a switch, it should be on your own data, not on someone else’s. You should consider moving these switch statements to the object whose data it uses.
8. Replace conditional with polymorphism
Apply state/strategy pattern if any of your conditional statements can be made more robust. Better distributed responsibilities are always a sign of good software design.
When not to refactor
Rewrite from scratch is easier. Lots of bugs exists, it is important that current code needs to work correctly for refactoring. Tight deadline. This can be kept for later as tech debts.
An alternative could be to split the software into components with strong encapsulation and this makes it easier to refactor as we go.