From f35d2e9c848df9650376979e3495fbc3976962fc Mon Sep 17 00:00:00 2001 From: Arno Chauveau Date: Thu, 24 Jul 2025 11:49:26 +0200 Subject: [PATCH] Introduce improved file structure, move update logic to legacyBehavior class MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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 --- TypeScript/app/gilded-rose.ts | 75 +++---------------- TypeScript/app/item.ts | 18 +++++ TypeScript/app/update-behaviors/index.ts | 2 + .../app/update-behaviors/legacy-behavior.ts | 56 ++++++++++++++ .../update-behavior.interface.ts | 5 ++ TypeScript/test/jest/approvals.spec.ts | 3 +- TypeScript/test/jest/gilded-rose.spec.ts | 3 +- TypeScript/tsconfig.json | 2 +- 8 files changed, 96 insertions(+), 68 deletions(-) create mode 100644 TypeScript/app/item.ts create mode 100644 TypeScript/app/update-behaviors/index.ts create mode 100644 TypeScript/app/update-behaviors/legacy-behavior.ts create mode 100644 TypeScript/app/update-behaviors/update-behavior.interface.ts diff --git a/TypeScript/app/gilded-rose.ts b/TypeScript/app/gilded-rose.ts index fe63cc89..2d894720 100644 --- a/TypeScript/app/gilded-rose.ts +++ b/TypeScript/app/gilded-rose.ts @@ -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); + } + } } diff --git a/TypeScript/app/item.ts b/TypeScript/app/item.ts new file mode 100644 index 00000000..5bad4d89 --- /dev/null +++ b/TypeScript/app/item.ts @@ -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; + } +} diff --git a/TypeScript/app/update-behaviors/index.ts b/TypeScript/app/update-behaviors/index.ts new file mode 100644 index 00000000..ec2e4546 --- /dev/null +++ b/TypeScript/app/update-behaviors/index.ts @@ -0,0 +1,2 @@ +export * from "./update-behavior.interface"; +export * from "./legacy-behavior"; diff --git a/TypeScript/app/update-behaviors/legacy-behavior.ts b/TypeScript/app/update-behaviors/legacy-behavior.ts new file mode 100644 index 00000000..e9fa304a --- /dev/null +++ b/TypeScript/app/update-behaviors/legacy-behavior.ts @@ -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; + } +} diff --git a/TypeScript/app/update-behaviors/update-behavior.interface.ts b/TypeScript/app/update-behaviors/update-behavior.interface.ts new file mode 100644 index 00000000..351156c1 --- /dev/null +++ b/TypeScript/app/update-behaviors/update-behavior.interface.ts @@ -0,0 +1,5 @@ +import { Item } from "@app/item"; + +export interface IUpdateBehavior { + update: () => Item; +} diff --git a/TypeScript/test/jest/approvals.spec.ts b/TypeScript/test/jest/approvals.spec.ts index ca6ba5d1..b33f47c0 100644 --- a/TypeScript/test/jest/approvals.spec.ts +++ b/TypeScript/test/jest/approvals.spec.ts @@ -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", () => { diff --git a/TypeScript/test/jest/gilded-rose.spec.ts b/TypeScript/test/jest/gilded-rose.spec.ts index 391ee0c0..f28e1623 100644 --- a/TypeScript/test/jest/gilded-rose.spec.ts +++ b/TypeScript/test/jest/gilded-rose.spec.ts @@ -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", () => { diff --git a/TypeScript/tsconfig.json b/TypeScript/tsconfig.json index 1623eedf..eff4f0f1 100644 --- a/TypeScript/tsconfig.json +++ b/TypeScript/tsconfig.json @@ -9,7 +9,7 @@ "resolveJsonModule": true, "esModuleInterop": true, "paths": { - "@/*": ["app/*"] + "@app/*": ["app/*"] } }, "exclude": ["node_modules"]