Now that you've refactored and simplified the legacy code, it's trivial to add a new feature. Use the red-green-refactor three-step dance of test-driven development (TDD) to add the new feature.
- [Voiceover] I've gone ahead and simplified the remaining code and I've included a copy of my code so you can begin at the same point as me. Let's take a look at updateQuality now. This is super simple, easy to read, easy to understand. I have a feeling it's going to be easy for us to add the new behavior. Here's what we've done so far. We started with a large chunk of legacy code that was ridden with technical debt. We added pin-down tests to stabilize the code.
Then we refactored to simplify the code. Now the code is much, much simpler than when we started. And we're on the third and final step of adding a new feature to legacy code. Let's review the requirements document so we remember the feature request. Let's look at GildedRoseRequirements.text. At line 29, the new requirement is: "Conjured" items degrade in Quality twice as fast as normal items. To implement this, we'll return to the Red-Green refactor three-step dance of TDD.
We'll start by writing a new test that goes red. We'll write the minimum code until that test passes, until all the tests go green. And we'll improve the code, we'll refactor as needed. So let's return to GildedRoseTest.java and we'll add a new test for conjured items. At line 121, we'll type "@Test", "public void" we'll call it conjuredDegradeTwiceAsFast.
We'll follow the pattern for previous tests. "Item item = createAndUpdate". The item name is GildedRose.CONJURED which is red, it won't compile, because CONJURED doesn't exist yet. We'll take care of that in a moment. We'll give it a sellin value of 15 and a quality of 25. And then we'll assert that the quality decreases by two, it goes from 25 to 23, and that's for the item's quality.
Alright, let's take care of this compile problem. We'll put the mouse pointer there, press Option + Enter and select "Create Constant Field". Then we type "String" and it will be the string "Conjured". Alright, looks like we've written enough code that it will compile and run, so let's run the new test. That test goes red, which is exactly what we expect. We've written a new test that goes red on purpose, we haven't implemented this new behavior yet.
And looking at the actual result, it looks like the item's quality decreased by one instead of by two. So it treated it like it was a normal item. Let's write the least amount of code to make this go green. So let's go back to updateQuality. And let's continue following this pattern. So at line 25 and a half, let's write this method "handleConjured(item)". Of course it's red because that method doesn't exist yet.
So we'll press Option + Enter, create that method. It has type void, it'll take an item with the name "item". What we'll type here is, if it is a conjured item. We're following the pattern that we've used before. If the item is a conjured item, then sellIn decreases by one and quality decreases by two.
At line 31, isConjured is red, we haven't implemented that yet. So we'll press Option + Enter, create method isConjured. Its type is boolean, takes an item called "item". We'll return true if the item's name equals CONJURED. Alright, looks like we have enough that it will compile and run, so let's run the tests. And it's still red.
Let's see if we can figure this out. Looks like it decreased by three. So it looks like we're not quite there. I think I know what happened. We have this method called isNormalItem and isNormalItem doesn't know about this new Conjured type yet. So let's add this to the list. It's a normal item if it's not a backstage pass, it's not Sulfuras and it's not Aged Brie, and it's not Conjured.
Let's re-run the tests now. And we are all green, we have successfully implemented the new feature. Let's take a look back up in updateQuality. And again, updateQuality is really easy to read now, we could add or change behavior as we wish and the pin-down tasks are going to help us keep everything safe.
- Defining refactoring
- Setting up a test-driven development environment
- Renaming variables
- Using the extract method
- Pinning down legacy code
- Testing code and branch coverage
- Refactoring legacy code
- Simplifying math and Booleans
- Adding new behaviors to refactored code