Refactoring Steps

In Continuation of previous post: Refactoring
Following is summary of some of the refactoring approaches that I frequently use, and that I keep in mind while doing code reviews. Some of the following guidelines may seem like common sense but it is important to revisit, nonetheless. Moreover, more often than not, you will come across code which faced design decay due to number of reasons and can use some basic refactoring approaches:

Extract Functions:
  • Functions should be atomic. Ideally, one function should be doing one task and doing it well. Split functions into smaller functions if it is getting complex to understand
  • Code should look like endless calls of delegation
  • Write small functions with meaningful names such that every function shows its intent. Do not underestimate importance of good names. I am not suggesting not to have comments at all, but before adding comments consider if splitting functions or if giving meaningful names can avoid need of comments. A good name will allow you to understand what function does without looking at its body. If that’s not the case, keep thinking.
Encapsulate Data
  • Importance of encapsulating data is directly proportional to scope of data. The more widely data fields are being used, the more important encapsulation becomes.
  • Encapsulation gives limited entry and exit points. Easier to add validation (or mutability etc) checks when inevitable enhancements/change requests come along.
  • Consider a simple scenario where we need to change data type of widely accessed variable due to unknown reasons. If data field was encapsulated, we can get away by just changing accessor method and type casting. (This is not recommended approach but may serve as good example of benefits of encapsulation)
Parameter Object
  • Consider creating parameter object if group of functions using same parameters.
  • It will not only reduce the number of parameters for functions but may also reveal structures in code which otherwise were unnoticed.  For example, can group of functions (operating on same subset of parameters) be part of class?
Replace Primitive with Object
  • In the earlier phase of development some simple data items might be stored as primitive types. If there is significant functionality revolving around these types, consider wrapping these types into Object. For example, address or telephone number might be stored as string. However, you might need to extract country and area codes or apply different formatting for different use cases.  Such primitive data types may be good candidates for wrapping into objects.
Replace Temp with Function
  • Temp variables are often used for calculations. This may seem counter intuitive but moving these calculations (however small these are) into class function and then calling this function can create more clarity. Especially, if these calculations are being performed at several places. 
Hide Delegate
  • Related to Encapsulation, consider hiding delegates. Changes to data structures will happen, and practice of hiding delegate will help you to make those changes easier. If ‘Person’ object has an ‘Address’ object, client needs access to ‘street’, then Person class can have getter which return something like ‘this.address.street’ instead of returning ‘Address’ object. Another Example.
Simplify Conditional Logic
  • Consider moving complex conditional check logic into function. It will make existing function easier to read and will make conditions easier to modify.
  • Consider moving series of conditional checks into wrapper function. It will look like a single atomic condition check rather than series of statements. For example, apply discount if customer has loyalty card, order amount is greater than 100 $, and if customer has not availed any other discount. Then we can have 3 functions, each checking individual condition, and then a wrapper function ‘applyDiscount()’ calling individual functions in return.
  • Consider if series of switch statements can be replaced by classes exhibiting polymorphic behavior.

This post is heavily inspired from book Refactoring: Improving Design of Existing code.


Popular posts from this blog

Practice Questions - AWS Solutions Architect - Associate Certification

Continuous Integration using AWS CodePipeline (GitHub to Elastic BeanStalk)

AWS Cross-Account RDS Backups