Skip directly to content

Gilded Rose Kata

on Tue, 03/22/2011 - 17:03

Purpose:

This kata fictionalizes the experience of working with someone else's code. You'll probably groan when you first see the code provided to you. The amount of code isn't overwhelming, its the prefect balance to evoke the feeling, "I can't wait to re-write this cruft." It's suggested that you use Test Driven Development with this kata. Once done, read the **spoiler** section below to see if you had a similar experience or not.

 

Original posting: http://iamnotmyself.com/2011/02/13/refactor-this-the-gilded-rose-kata/  http://www.iamnotmyself.com/2011/02/13/RefactorThisTheGildedRoseKata.aspx

C#: https://github.com/NotMyself/GildedRose

Java : https://github.com/wouterla/GildedRose

Ruby : https://github.com/professor/GildedRose

I believe that the Gilded Rose Kata was developed by Terry Hughes and Bobby Johnson and presented to the SC community on 2/13/2011. 

Kata Text

 

Hi and welcome to team Gilded Rose. As you know, we are a small inn with a prime location in a prominent city ran by a friendly innkeeper named Allison. We also buy and sell only the finest goods. Unfortunately, our goods are constantly degrading in quality as they approach their sell by date. We have a system in place that updates our inventory for us. It was developed by a no-nonsense type named Leeroy, who has moved on to new adventures. Your task is to add the new feature to our system so that we can begin selling a new category of items. First an introduction to our system:

  • All items have a SellIn value which denotes the number of days we have to sell the item
  • All items have a Quality value which denotes how valuable the item is
  • At the end of each day our system lowers both values for every item

Pretty simple, right? Well this is where it gets interesting:

  • Once the sell by date has passed, Quality degrades twice as fast
  • The Quality of an item is never negative
  • “Aged Brie” actually increases in Quality the older it gets
  • The Quality of an item is never more than 50
  • “Sulfuras”, being a legendary item, never has to be sold or decreases in Quality
  • “Backstage passes”, like aged brie, increases in Quality as it’s SellIn value approaches; Quality increases by 2 when there are 10 days or less and by 3 when there are 5 days or less but Quality drops to 0 after the concert

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

Feel free to make any changes to the UpdateQuality method and add any new code as long as everything still works correctly. However, do not alter the Item class or Items property as those belong to the goblin in the corner who will insta-rage and one-shot you as he doesn’t believe in shared code ownership (you can make the UpdateQuality method and Items property static if you like, we’ll cover for you).

 

Carnegie Mellon University - Silicon Valley campus reflections

**Spoilers** Note: you probably want to read this section after doing the kata. 

1. Most of the students thought this was a great kata for practicing TDD.

We had a great conversation about  what is the best way to test this? A few started with a given initial state and looped through update quality man times. They found that their test cases were as complicated as the code they were testing. Often this code was hard to follow or read. Many tested the individual requirements to verify that when we go from state N to state N+1, a certain invariant still holds true. 

2. What is the purpose of the Goblin rule?

(I need to find my notes on the class response to this one.) Most agreed that it was ok to subclass item provided that you didn't touch the code in the item class. Just to be sure, I asked Terry this question and here is his answer: "basically if the goblin sees anything different inside the Item class, everyone dies"

3. Of the 11 students who did it, only one refactored the code by creating subclasses of Item. (One student broke the Goblin rule and thus everyone died.)  I believe the rest did inline modifications of the original code. (Which in my opinion wasn't that hard to do, once you had the test cases written.)
 
4. We make assumptions when we write software. Some of us thought that the original code worked fine and our job was to replicate the behavior. If there was a difference between the requirement and what the code did, we assumed the code was correct. Others of us thought the opposite.
 
We had a great conversation about when is it appropriate for the programmer to override input given by the user? For example, Sulfuras, Hand of Ragnaros has an initial quality of 80 which violates that "The Quality of an item is never more than 50" -- some people decided to enforce this rule and drop the quality from 80 to 50 (which is ironic given that “Sulfuras never decreases in Quality" while others decided to keep the behavior of the original code. We discussed what would a considerate system do and what are circumstances where you tell the user that they are wrong.
 
5. What did you like about this kata?
-the kata was realistic and mimic a real-life scenario
-I was confident about TDD this time
-I broke the rules and modified the Item Class
-it's a good exercise for design patterns
-need to go through all the test cases
-the kata was a great way to get familiar with the syntax of a programming language
-it was also a great avenue for applying TDD and writing strong tests
-it had the perfect level of hardness to practice TDD
-code required more thought than Prime Factors. Also made me want to refactor and think in that way before starting the code.
-I liked how it demonstrated how poor readability code and make it hard to make changes
-the kata was fun because of the little story behind it. Made it more interesting than just another problem.
-I liked how the code/spec was co convoluted that it took me a while to feel confident that I had ported the code to my language correctly. It was like a brain teaser
-handling the numerous conditions and putting them efficiently in code

 

 

Tags: 

Comments

ccjensen's picture

1. Would you recommend this activity to a peer? (and why)

It was more an exercise of keeping my head straight on what brackets went where. Code should probably have been refactored.

 

2. How many starts would you give it?

3 stars
 
3. How much time did you spend on the activity?
2 hours. Ended up going above and beyond with my tests, and their complexity were approaching that of the original code (not good).
 
4. What worked well?
I had learned from my past experience, and embraced the fact that this was objective-c. Also, moving the item specifics into a constant file allowed me to re-use those numbers in the tests without having to hard code them both places.
 
5. What didn't work well? (Suggestions for improvement)
Being too clever with the tests.
 
6. What programming language did you use?
Objective-C, Cocoa and OCUnit
 
7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)
No
 
Question:
None
ajauhri's picture

1. Would you recommend this activity to a peer? (and why)

With so many if conditions, the code can get a clumsy. One should keep this in mind while implementing such a task.

 

2. How many starts would you give it?

3 stars

 

3. How much time did you spend on the activity?

One and a half hour

 

5. What didn't work well? (Suggestions for improvement)

-

 

6. What programming language did you use?

Python

 

7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)

No

asem.radhwi's picture

 


1. Would you recommend this activity to a peer? (and why)

I liked it, I felt it was a real life scenario, I refactored the code and at most, I got 2 inner if conditions.

 

2. How many starts would you give it?

4 Stars

 

3. How much time did you spend on the activity?
2 Hours
 
4. What worked well?
I felt confident now using JUnit, Refactoring the if conditions, used static variables, wanted to use switch for strings but isn't available in Java :( hopefully in Java 7 :D
 
5. What didn't work well? (Suggestions for improvement)
None
 
6. What programming language did you use?
Java, JUnit
 
7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)
Nope
 
kurifu's picture

1. Would you recommend this activity to a peer? (and why)

Yes, because the skeleton makes you want to refactor and restructure existing code before you begin coding, helps you organize your thoughts before you start

 

2. How many starts would you give it?

3 stars? Not sure what the scale is

 

3. How much time did you spend on the activity?

2 hours

 

5. What didn't work well? (Suggestions for improvement)

The skeleton for Java didn't look very good, it made me refactor a couple things and made me very suspicious that the existing code would work at all. I spent about half an hour getting a bunch of test cases up and running to make sure what I was given was legit. Also the fact that we couldn't modify the Item class was a little random. If this was a random artificial constraint, it wasn't a very good one. The solution to this problem is neither elegant nor satisfying.

 

6. What programming language did you use?

Java, JUnit

 

7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)

Nope.

shehriih's picture

 

1. Would you recommend this activity to a peer? (and why)

Yes, it shows how important is Code Readability and how it affacts the maintainability !. After a quick look @ the code, i thought there are some bugs. So i wrote couple of tests before changing the code to make sure it is working ! which were useful  laster as it helped me to ensure that the refactoring or changes i made did not break the code.

 

I had some generic rule (quality not be negative and not to be more than 50 , etc ..) to applied at the end of the for loop which saved me some extra inner if blocks

 

Those generica rules  could've been in the set methods of the Item class.

 

 

2. How many starts would you give it?

4 stars

 

3. How much time did you spend on the activity?

2 hours

 

5. What didn't work well? (Suggestions for improvement)

None

 

6. What programming language did you use?

Java, JUnit

 

7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)

i think the original goal is to experince the difficulty of refactoring  code with poor readibilty. I would add to it the importance of writing thorough test cases before making any changes.

toddsedano's picture

 

1. Would you recommend this activity to a peer? (and why)

Growing up with games, I enjoyed the motif and the items. 

 

2. How many starts would you give it?

4 stars
 
3. How much time did you spend on the activity?
I spent too long porting the java to ruby and then realizing that the C# has a closer syntax. My first attempt took me about 45 minutes.
 
4. What worked well?
 
5. What didn't work well? (Suggestions for improvement)
 
6. What programming language did you use?
Ruby
 
7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)
After writing my tests, I actually understood the requirements. My approach completely changed. When I first saw the code, I told myself, "don't bother with it." My initial thought was to re-write all of the code. After understanding the tests, I realized that I only needed to modify the code in a few places. The test suite that I wrote game me the confidence to follow this path. I spent about 30 minutes writing my tests and 5 minutes writing the code. 
 
If I were to spend more time on this project, I would extend the Item class and move behavior to child classes.
 
Question:
None
rob.engel@sv.cmu.edu's picture

 

1. Would you recommend this activity to a peer? (and why)

I think this is a very good activity to get comfortable with a programming language, so I would for that purpose. In addition, it was a very good activity to practice writing tests.

 

2. How many stars would you give it?

3 stars

 

3. How much time did you spend on the activity?
6 hours
 
4. What worked well?
I was able to get more accustomed to C++ and the testing framework, in addition to writing powerful tests. I want to extend this kata into an OO example, with special items having their own classes and methods - this is for the weekend.
 
5. What didn't work well? (Suggestions for improvement)
-
 
6. What programming language did you use?
C++
 
7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)
-
vprasad's picture

 

1. Would you recommend this activity to a peer? (and why)

I found it (at times) frustrating to follow TDD and other learning objecitves that I have set to myself but I ended up sticking to my "newly learned" principles, for the most part. I would recomend this to my peers (if their learning objectives are same as mine) because IMO it had that balance between being excessively frustrating and overly easy. 

 

2. How many starts would you give it?

4 stars

 

3. How much time did you spend on the activity?
5 hours, I didn't just write the method but I created the entire project. 
 
4. What worked well?
First I thought of using enumerators for having the "special items" but then I came to the conclusion that if I have a seperate class with a list of special items it would be better. 
 
5. What didn't work well? (Suggestions for improvement)
I think I have not followed DRY (Don't Repeat Yourself) compeletely. I didn't know where I could have changed my code to improve on that aspect. 
 
6. What programming language did you use?
Java.
 
7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)
When I decided to use a separate "SpecialItems" class instead of using enumerators. 
 
Question:
None
ianzhang's picture

 

1. Would you recommend this activity to a peer? (and why)

Yes, this is a good exercise to learn TDD. After this exercise, I understood that writing test examples can be part of the design process. I felt more confident to implement the code when I finished the test examples

 

2. How many starts would you give it?

3 stars
 
3. How much time did you spend on the activity?
2 hours. 1 hour for going through the suitable design pattern and tried to understand the bussiness rules. 1 hour for TDD and implementation.
 
4. What worked well?
I learn how to implement some design patterns using Ruby and I feel more comfortable with TDD now. It's just awesome~
 
5. What didn't work well? (Suggestions for improvement)
None.
 
6. What programming language did you use?
Ruby Rspec
 
7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)
No
 
hahuang65's picture

1. Would you recommend this activity to a peer? (and why)

Absolutely. This was a fun kata that slightly resembled a real life situation. It tested many things, like following TDD, problems with code you can't change, reading others' code, etc. It was a fun experience.

 

2. How many starts would you give it?

5 stars

 

3. How much time did you spend on the activity?

2 hours

 

5. What didn't work well? (Suggestions for improvement)

I could not get Rspec to work with Ruby only code (without a Rails skeleton), so I wasn't quite able to follow TDD, and had to go back to a printing debug method to test my code.

 

6. What programming language did you use?

Ruby

 

7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)

Yes, 2 days after the kata, I realized, Rspec was not working because in the 2.0 version, the command for Rspec in the terminal was "rspec" and no longer "spec". And since I had aliased "rspec" to also run "spec", I was getting trouble running Rspec at all. In my Rails projects Rspec has always worked because I ran autotest. Quite stupid of me, but now I have Rspec running, so I'm very excited to do the next kata with TDD! :)

isuru.warn's picture

1. Would you recommend this activity to a peer? (and why)

Yes. It was a good exercise that made me think about design decisions such as do I want to keep the Items List static, do I want to make the Update method static, etc.

 

2. How many starts would you give it?

3 stars
 
3. How much time did you spend on the activity?
4 hours.
 
4. What worked well?
I was able to follow TDD every step of the way, based on the problem scenario provided. I learned about statics (class methods and variables) in Ruby.
 
5. What didn't work well? (Suggestions for improvement)
I didn't test for edge cases when writing the tests, and realized this during the review session in class. The fact that some of the existing code was buggy meant that I had to do some bug fixing before starting on the actual task.
 
6. What programming language did you use?
Ruby
 
7. Where there any "ah-hah!" moments or unintendend consequences? (In other words, would you add something to the original goal list?)
No

Post new comment