Introduce improved file structure, move update logic to legacyBehavior class

- move item to it’s own file.
- Change tsconfig to use ‘@app’ prefix for imports
- move the logic to the legacy-behavior file, allowing to refactor out 
item type by item type
This commit is contained in:
Arno Chauveau 2025-07-24 11:49:26 +02:00
parent 737704e19e
commit f35d2e9c84
8 changed files with 96 additions and 68 deletions

View File

@ -1,21 +1,5 @@
export class Item {
name: string;
sellIn: number;
quality: number;
// can't edit this constructor because of the kata rules.
// but I would change the constructor to take a javaScript object.
// It makes the consumer code more readable.
// e.g. new Item({ name: "standard item", sellIn: 0, quality: 2 })
// instead of new Item("standard item", 0, 2)
// I would also type the parameters, because now they are implicitly any.
constructor(name, sellIn, quality) {
this.name = name;
this.sellIn = sellIn;
this.quality = quality;
}
}
import { Item } from "@app/item";
import { IUpdateBehavior, LegacyBehavior } from "@app/update-behaviors";
export class GildedRose {
// also can't edit this because of the kata rules.
@ -28,53 +12,14 @@ export class GildedRose {
updateQuality() {
return this.items.map((item) => {
if (
item.name !== "Aged Brie" &&
item.name !== "Backstage passes to a TAFKAL80ETC concert"
) {
if (item.quality > 0) {
if (item.name !== "Sulfuras, Hand of Ragnaros") {
item.quality = item.quality - 1;
}
}
} else {
if (item.quality < 50) {
item.quality = item.quality + 1;
if (item.name === "Backstage passes to a TAFKAL80ETC concert") {
if (item.sellIn < 11) {
if (item.quality < 50) {
item.quality = item.quality + 1;
}
}
if (item.sellIn < 6) {
if (item.quality < 50) {
item.quality = item.quality + 1;
}
}
}
}
}
if (item.name !== "Sulfuras, Hand of Ragnaros") {
item.sellIn = item.sellIn - 1;
}
if (item.sellIn < 0) {
if (item.name !== "Aged Brie") {
if (item.name !== "Backstage passes to a TAFKAL80ETC concert") {
if (item.quality > 0) {
if (item.name !== "Sulfuras, Hand of Ragnaros") {
item.quality = item.quality - 1;
}
}
} else {
item.quality = item.quality - item.quality;
}
} else {
if (item.quality < 50) {
item.quality = item.quality + 1;
}
}
}
return item;
return this.#getUpdateBehaviorFor(item).update();
});
}
#getUpdateBehaviorFor(item: Item): IUpdateBehavior {
switch (item.name) {
default:
return new LegacyBehavior(item);
}
}
}

18
TypeScript/app/item.ts Normal file
View File

@ -0,0 +1,18 @@
export class Item {
name: string;
sellIn: number;
quality: number;
// can't edit this constructor because of the kata rules.
// but I would change the constructor to take a javaScript object.
// It makes the consumer code more readable.
// e.g. new Item({ name: "standard item", sellIn: 0, quality: 2 })
// instead of new Item("standard item", 0, 2)
// I would also type the parameters, because now they are implicitly any.
constructor(name, sellIn, quality) {
this.name = name;
this.sellIn = sellIn;
this.quality = quality;
}
}

View File

@ -0,0 +1,2 @@
export * from "./update-behavior.interface";
export * from "./legacy-behavior";

View File

@ -0,0 +1,56 @@
import { Item } from "@app/item";
import { IUpdateBehavior } from "./update-behavior.interface";
export class LegacyBehavior implements IUpdateBehavior {
constructor(private item: Item) {}
update(): Item {
if (
this.item.name !== "Aged Brie" &&
this.item.name !== "Backstage passes to a TAFKAL80ETC concert"
) {
if (this.item.quality > 0) {
if (this.item.name !== "Sulfuras, Hand of Ragnaros") {
this.item.quality = this.item.quality - 1;
}
}
} else {
if (this.item.quality < 50) {
this.item.quality = this.item.quality + 1;
if (this.item.name === "Backstage passes to a TAFKAL80ETC concert") {
if (this.item.sellIn < 11) {
if (this.item.quality < 50) {
this.item.quality = this.item.quality + 1;
}
}
if (this.item.sellIn < 6) {
if (this.item.quality < 50) {
this.item.quality = this.item.quality + 1;
}
}
}
}
}
if (this.item.name !== "Sulfuras, Hand of Ragnaros") {
this.item.sellIn = this.item.sellIn - 1;
}
if (this.item.sellIn < 0) {
if (this.item.name !== "Aged Brie") {
if (this.item.name !== "Backstage passes to a TAFKAL80ETC concert") {
if (this.item.quality > 0) {
if (this.item.name !== "Sulfuras, Hand of Ragnaros") {
this.item.quality = this.item.quality - 1;
}
}
} else {
this.item.quality = this.item.quality - this.item.quality;
}
} else {
if (this.item.quality < 50) {
this.item.quality = this.item.quality + 1;
}
}
}
return this.item;
}
}

View File

@ -0,0 +1,5 @@
import { Item } from "@app/item";
export interface IUpdateBehavior {
update: () => Item;
}

View File

@ -1,4 +1,5 @@
import { Item, GildedRose } from "@/gilded-rose";
import { GildedRose } from "@app/gilded-rose";
import { Item } from "@app/item";
describe("Gilded Rose Approval", () => {
it("should match the snapshot for thirty Days", () => {

View File

@ -1,4 +1,5 @@
import { Item, GildedRose } from "@/gilded-rose";
import { GildedRose } from "@app/gilded-rose";
import { Item } from "@app/item";
describe("Gilded Rose", () => {
it("should have an empty array as items when no constructor parameter is provided", () => {

View File

@ -9,7 +9,7 @@
"resolveJsonModule": true,
"esModuleInterop": true,
"paths": {
"@/*": ["app/*"]
"@app/*": ["app/*"]
}
},
"exclude": ["node_modules"]