View on GitHub

Srinivas Kommu Tech Blog

Passionate About Infomation

Software maintenance with Good Design

In software engineer life involvement in implementing the software applications and maintaining over the time is obvious thing. The people who involves in maintaining the application can be a new team member who joined recently who doesn’t have any idea about the application, some times same set of engineers who involved in developing the application or it could be different group of engineers. But how a team member or entire team enjoys maintaining the application depends on the software engineering principles that team followed while design, implementation and also current phase of maintaining the application.

The term software maintenance refers to changes for defect correction, performance improvements, or adaptations to changed business requirements. Change or enhancement to software could introduce a new bug in existing working software. With the poor design/code implementation in existing application could demand almost redesigning/rewriting the whole software that will be more costly. That could lead the same kind of process in the future also whenever we required a code change. Most software maintenance requirements could have been anticipated and avoided during the design process. In other words, maintenance is a form of waste. Adhere to best software engineering principles like SOLID principles while designing or implementing the code can save our lives while maintaining the software over the course of time.

I was given a task of maintaining poorly written application called gilded Rose. The problem description can be found at - gilded-rose-refactoring-kata. As part of the maintenance of current code and also there was new requirement (below description) from business, which made me to refactor the existing code.

“We have recently signed a supplier of conjured items. This requires an update to our system: "Conjured" items degrade in Quality twice as fast as normal items”

While thinking about changing the existing code, I was thinking how to make this application code easy to maintain over time and defect-free, performs well, and to contain user-controlled parameters to adjust processing rules in response to changing requirements. While refactoring the code, I was afraid to touch even single line of code; my fear was it might break the existing functionality. I lost figuring out where to change the code; I also attempted to rewrite the entire code few times. This drove me to write all test cases for the existing functionality before touching any application code. I written test case that covers existing functionality and those tests gave me confidence to change code.

Main thing came to my mind is the ‘Sprout’ class for new item ‘Conjured’ with ‘ Test Driven Development ’. So started writing test case for ‘Conjured’ item and also ‘ConJureItem’. I successfully updated the main program ‘Gilded Rose’ with if condition and my earlier tests with new ConjuredItem test passing.

ConjuredItem

public class ConjuredItem extends ItemWrapper { public ConjuredItem(String name, int sellIn, int quality) { super(name, sellIn, quality);

}

@Override public void updateQuality() { if (super.getQuality() - 1 >= 0) { if (super.getSellIn() > 0) { super.setQuality(super.getQuality() - 2); } else { super.setQuality(super.getQuality() - 4); }

}

} }

Change to main program

public void updateQuality() { for (int i = 0; i < items.length; i++) { if (items[i].name.equals("Conjured"){ items[i].quality = new ConjuredItem(items[i].name, items[i].sellIn, items[i].quality).updateQuality();

        }

With the above change all my test cases were passing along with new Conjure Item test as well. After I finished the new requirement I started observing for ‘code smells’ with the lines of good design including the Object-Oriented paradigm and SOLID (S: Single Responsibility Principle (SRP), O: Open-Closed Principle (OCP), L: Liskov Substitution Principle (LSP), I: Interface Segregation Principle (ISP), D: Dependency Inversion Principle (DIP)) principles for simple design.

Code smells and effects in current code:

• Large Class and long method are difficult to read, understand, and troubleshoot. • Conditional Complexity
• Code repetition and Combinatorial Explosion. (DRY: Don't Repeat Yourself) lots of code that does almost the same thing.

Code refactoring:

• Pre written test cases for all possible scenarios gave me quick feedback on my code refactoring.
• I went on refactoring piece by piece until I felt like code looks modular, easy to change, understandable and follows SOLID principles. • I figured SRP and OCP were violated o SRP: Class should have one and only one reason to change o OCP: Open for extension and closed for modification • I created ‘ItemControl’ abstraction and subclasses for each Item Type implementing ‘Item Control’ based SRP and OCP principle. • Even if we add new category of item in the future, we will add one more sub type by extending the ‘Item Control’ abstraction instead of modifying it. • There is special Item ‘Sulfar’, which doesn’t fall under updating ‘quality’ and ‘sellIn’, So I observed that If I extend ‘ItemControl’, there is possibility for violation of Interface Segregation Principle (ISP). o ISP states that clients should not be forced to implement interfaces they don't use.

My refactored code is available for review code. So with good design we will achieve the highly readable, testable, defect free code and easy to adjust processing rules in response to changing requirements. This will lead to easy maintenance of the delivered product over time.