level: A set of methods or behaviors that can be invoked by other objects or by itself ‣ Implementation level: A set of code and data and computation interactions between them
All items have a Sell-In value which denotes the number of days in which the item must be sold ▸ 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
Once the sell-in date has passed, Quality degrades twice as fast ▸ The Quality of an item is never negative ▸ Some items actually increase in Quality the older it gets, e.g. “Aged Brie” ▸ 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 concerts have a Quality value which denotes how valuable the item is
of conjured items. This requires an update to our system: ▸ “Conjured” items degrade in Quality twice as fast as normal items GILDED ROSE REFACTORING KATA: THE REQUIREMENTS
which denotes the number of days in which the item must be sold ▸ 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 GILDED ROSE REFACTORING KATA: THE REQUIREMENTS
Once the sell by date has passed, Quality degrades twice as fast ▸ The Quality of an item is never negative ▸ Some items actually increase in Quality the older it gets, e.g. “Aged Brie” ▸ 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 concerts have a Quality value which denotes how valuable the item is
Once the sell by date has passed, Quality degrades twice as fast ▸ The Quality of an item is never negative ▸ Some items actually increase in Quality the older it gets, e.g. “Aged Brie” ▸ 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 concerts have a Quality value which denotes how valuable the item is
Once the sell by date has passed, Quality degrades twice as fast ▸ The Quality of an item is never negative ▸ Some items actually increase in Quality the older it gets, e.g. “Aged Brie” ▸ 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 concerts have a Quality value which denotes how valuable the item is
i < len(items); i++ { if items[i].name == "Normal" { update_normal(&items[i]) return } // Deal with quality // Things whose quality decreases over time if items[i].name != "Aged Brie" && items[i].name != "Backstage passes to a TAFKAL80ETC concert" { // Catch lower limit if items[i].quality > 0 { if items[i].name != "Sulfuras, Hand of Ragnaros" { items[i].quality = items[i].quality - 1 } }
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) return case "Aged Brie": update_brie(&items[i]) return case "Sulfuras, Hand of Ragnaros": update_sulfuras(&items[i]) return } // ... existing mess
Once the sell by date has passed, Quality degrades twice as fast ▸ The Quality of an item is never negative ▸ Some items actually increase in Quality the older it gets, e.g. “Aged Brie” ▸ 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 concerts have a Quality value which denotes how valuable the item is
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) return case "Aged Brie": update_brie(&items[i]) return case "Sulfuras, Hand of Ragnaros": update_sulfuras(&items[i]) return case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) return } // ... existing mess
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) return case "Aged Brie": update_brie(&items[i]) return case "Sulfuras, Hand of Ragnaros": update_sulfuras(&items[i]) return case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) return } // ... existing mess Default?
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) return case "Aged Brie": update_brie(&items[i]) return case "Sulfuras, Hand of Ragnaros": update_sulfuras(&items[i]) return case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) return default: update_default(&items[i]) return } // ... existing mess
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) return case "Aged Brie": update_brie(&items[i]) return case "Sulfuras, Hand of Ragnaros": update_sulfuras(&items[i]) return case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) return default: update_default(&items[i]) return } // ... existing mess
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) case "Aged Brie": update_brie(&items[i]) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) default: update_default(&items[i]) } return } }
of conjured items. This requires an update to our system: ▸ “Conjured” items degrade in Quality twice as fast as normal items GILDED ROSE REFACTORING KATA: THE NEW FEATURE
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) case "Aged Brie": update_brie(&items[i]) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) default: update_default(&items[i]) } return } }
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) case "Aged Brie": update_brie(&items[i]) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) case “Conjured Mana Cake": update_conjured(&items[i]) default: update_default(&items[i]) } return } }
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) case "Aged Brie": update_brie(&items[i]) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) case “Conjured Mana Cake": update_conjured(&items[i]) default: update_default(&items[i]) } return } }
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) case "Aged Brie": update_brie(&items[i]) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) case “Conjured Mana Cake": update_conjured(&items[i]) case “Chunky Bacon": update_bacon(&items[i]) default: update_default(&items[i]) } return } }
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) case "Aged Brie": update_brie(&items[i]) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) case “Conjured Mana Cake": update_conjured(&items[i]) case “Chunky Bacon": update_bacon(&items[i]) case “+5 Dexterity Vest": update_vest(&items[i]) default: update_default(&items[i]) } return } }
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) case "Aged Brie": update_brie(&items[i]) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) case “Conjured Mana Cake": update_conjured(&items[i]) case “Chunky Bacon": update_bacon(&items[i]) case “+5 Dexterity Vest": update_vest(&items[i]) case “Gorbypuff Thunderhorse": update_cat(&items[i]) default: update_default(&items[i]) } return } } ❌
level: A set of methods or behaviors that can be invoked by other objects or by itself ‣ Implementation level: A set of code and data and computation interactions between them
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) case "Aged Brie": update_brie(&items[i]) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) default: update_default(&items[i]) } return } }
i < len(items); i++ { switch items[i].name { case "Normal": update_normal(&items[i]) case "Aged Brie": update_brie(&items[i]) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(&items[i]) default: update_default(&items[i]) } return } }
i < len(items); i++ { switch items[i].name { p := &items[i] case "Normal": update_normal(p) case "Aged Brie": update_brie(p) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(p) default: update_default(p) } return } } Objects are created here
i < len(items); i++ { switch items[i].name { p := &items[i] case "Normal": update_normal(p) case "Aged Brie": update_brie(p) case "Backstage passes to a TAFKAL80ETC concert": update_backstage(p) default: update_default(p) } return } }
10, 20), ItemFactory("Aged Brie", 2, 0), ItemFactory(“Chunky Bacon”, 5, 7), ItemFactory("Sulfuras, Hand of Ragnaros", 0, 80), ItemFactory("Backstage passes to a TAFKAL80ETC concert", 15, 20), ItemFactory("Conjured Mana Cake", 3, 6), } func GildedRose() { for i := 0; i < len(items); i++ { //... } } ACTUAL COLLECTION OF ITEMS
int Quality() int Update() } type Params struct { name string sellIn, quality int } var items = []Item{ ItemFactory("+5 Dexterity Vest", 10, 20), ItemFactory("Aged Brie", 2, 0), ItemFactory(“Chunky Bacon”, 5, 7), ItemFactory("Sulfuras, Hand of Ragnaros", 0, 80), ItemFactory("Backstage passes to a TAFKAL80ETC concert", 15, 20), ItemFactory("Conjured Mana Cake", 3, 6), }
:quality def initialize name, sellIn, quality @name, @sellIn, @quality = name, sellIn, quality end def update end end class Brie < Default def update ... end end class Normal < Default def update ... end end class BackstagePass < Default def update ... end end
string SellIn() int Quality() int Update() } type Params struct { name string sellIn, quality int } type Factory func(Params) Item var Factories = map[string]Factory{ "Normal": NewNormal, "Aged Brie": NewBrie, "Backstage passes to a TAFKAL80ETC concert": NewBackstagePass, } ...
string SellIn() int Quality() int Update() } type Factory func(Params) Item var Factories = map[string]Factory{ "Normal": NewNormal, "Aged Brie": NewBrie, "Backstage passes to a TAFKAL80ETC concert": NewBackstagePass, } ...
be conceptualized as a set of responsibilities ▸ Inheritance is possible through the use of interfaces and embedding ▸ Interfaces represent the specification of the object ▸ Embedding represents a portable encapsulation of a set of data/ behavior ▸ Namespacing can be achieved via packages
Software, by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides. ▸ Design Patterns Explained: A New Perspective on Object-Oriented Design, by Alan Shalloway and James R. Trott ▸ All the Little Things, Sandi Metz: https://confreaks.tv/videos/ railsconf2014-all-the-little-things ▸ https://xkcd.com/1428/