
Gilded Rose Kata in Python
This is a refactoring exercise based on the famous GildedRose-Refactoring-Kata repository maintained by Emily Bache. This kata contains simple code in many different programming languages that need to be refactored and improve code quality.
The source program has two classes GildedRose and Item. The Item class describes the properties of an item and contains the attributes – name, sell_in, and quality. The GildedRose class has a method update_quality() that updates the sell_in date and quality of the items on a regular basis.
Requirements
The existing codebase provides support for three products, however, the addition of a new product Conjured breaks the existing business logic and hence needs remodeling. There are a few business rules and constraints that need to be taken care of while refactoring the code.
Business Rules
- All items will have the three attributes as follows:
name– Name of the item.sell_in– The number of days within which the item should be sold off.quality– The quality of the item; denoted by an integer.
- Every day, the method
update_quality()is executed, which lowers the values forsell_inandqualityeach. - Once the
sell_indate has passed, the value forqualitydegrades twice faster. - There are also rules for each of the items that are currently present which are as follows.
- AgedBrie increases its
qualitywith a decrease insell_invalue. - BackstagePasses has the following two rules:
- When
sell_invalue is more than 10,qualityincreases by 1. - When
sell_invalue is less than 10,qualityincreases by 2. - When
sell_invalue is less than 5,qualityincreases by 3. - When
sell_invalue is less than 0,qualityis set to 0.
- When
- Sulfuras is legendary, so
qualityis always 80 andsell_invalue never decreases. - A new item – Conjured is to be added with the following rule:
- Conjured items degrade
qualitytwice as fast as normal items.
- Conjured items degrade
- AgedBrie increases its
Constraints
There are a few constraints that we need to consider before refactoring.
- We are not allowed to alter the
Itemclass or the attributes of theItemclass. - The minimum and maximum values for
qualitycan only be 0 and 50 respectively.
For more detailed requirements, you can refer to the original text.
Reason to Refactor
If you browse through the existing code, you can see that all the business rules are implemented in a single class and inside a complex nested if-else statement. Following are a few reasons why I think the code should be refactored and developed in a modular way.
- Readability – The current logic is very difficult to read as everything is contained in a single class with multiple nested if-else statements.
- Duplicate logic – There are a few logics that are duplicated. This can be written in a better way by using a parent-child class relationship.
- Implementation of the new item Conjured will need to modify the current if-else statements and that might cause harm to the existing logic.
Implementation
My approach to implement and refactor the program would be as follows.
- Writing extensive unit test cases to preserve and validate the existing business logic.
- For the codebases to be modular, I would break down the project structure into multiple files as follows under the
appdirectory.gilded_rose.py– This is the refactored base file that contains theGildedRoseclass and theupdate_quality()method. I have removed the complex if-else statements from this class and implemented them separately.product_list.py– This file contains theProductListclass which is an enumerated list of all the available items. New items can be added to the list without affecting the business logic for other products.item.py– This is the definition of the classItem. It is the parent class of any item and contains methods to update the values forsell_inandquality. Any regular product which satisfies the normal business rules can be inherited from this class and if there are some specific rules, then the inherited child classes can modify the logic for theupdate_quality()method accordingly.products.py– This file contains aProductclass that will basically route the call to the respective product classes when the instances are created. In addition to that, I have added a separate class for each of the existing items that do not follow the normal business rules. All these child classes inherit from the parentItemclass.
UML Class Diagram
The UML class diagram of the refactored code is provided below.

Test Cases
In order to validate the existing logic and new business rules, several unit test cases have been written which are found under the tests directory. It contains several test files as follows.
| Test cases for regular products | test_gilded_rose_regular.py |
|---|---|
| Test cases for specific products | test_gilded_rose_brie.py |
| Test cases for specific products | test_gilded_rose_backstage.py |
| Test cases for specific products | test_gilded_rose_sulfuras.py |
| Test cases for specific products | test_gilded_rose_conjured.py |
| Test for other products | test_gilded_rose_other.py |
Executing the test cases
First, you need to create a python virtual environment for the program.
python -m venv .venv
source .venv/bin/activate
pip install --upgrade pip
This will start the virtual environment and update the pip. Once the virtual environment is up and running, the test cases can be executed from the terminal as follows.
python -m unittest discover tests

If the tests are configured within the IDE (VSCode or PyCharm), then the tests can be executed from within the IDE itself.



