Move DailyUpdate of each type to DailyUpdaterHierarchy and add a simple factory method to get the appropriate updater to use.

This commit is contained in:
Sarah Ashri 2024-03-14 14:27:42 +10:00
parent 0e52fc7c4b
commit a585b181da
3 changed files with 113 additions and 52 deletions

View File

@ -0,0 +1,94 @@
using System.Data;
namespace GildedRoseKata;
public abstract class DailyUpdater
{
protected const int MinQuality = 0;
protected const int MaxQuality = 50;
public void DailyUpdate(Item item)
{
UpdateSellIn(item);
UpdateQuality(item);
}
public abstract void UpdateQuality(Item item);
public virtual void UpdateSellIn(Item item) => item.SellIn -= 1;
protected static bool IsExpired(Item item) => item.SellIn < 0;
protected static void IncreaseQuality(Item item, int byValue)
{
item.Quality = int.Min(item.Quality + byValue, MaxQuality);
}
protected static void DecreaseQuality(Item item, int byValue)
{
item.Quality = int.Max(item.Quality - byValue, MinQuality);
}
}
public class DailyUpdaterForRegularItems : DailyUpdater
{
public override void UpdateQuality(Item item)
{
DecreaseQuality(item, 1);
if (IsExpired(item))
{
DecreaseQuality(item, 1);
}
}
}
public class DailyUpdaterForBetterWithAgeItems : DailyUpdater
{
public override void UpdateQuality(Item item)
{
IncreaseQuality(item, 1);
if (IsExpired(item))
{
IncreaseQuality(item, 1);
}
}
}
public class DailyUpdaterForBackstagePassesItems : DailyUpdater
{
public override void UpdateQuality(Item item)
{
if (item.SellIn > 9)
{
IncreaseQuality(item, 1);
}
else if (item.SellIn > 4)
{
IncreaseQuality(item, 2);
}
else if (!IsExpired(item))
{
IncreaseQuality(item, 3);
}
else //Expired
{
DecreaseQuality(item, item.Quality);
}
}
}
public class DailyUpdaterForLegendaryItems : DailyUpdater
{
public override void UpdateSellIn(Item item)
{
// Legendary Items don't change over time
}
public override void UpdateQuality(Item item)
{
// Legendary Items don't change over time
}
}

View File

@ -17,7 +17,8 @@ public class GildedRose
{ {
foreach (var item in _items) foreach (var item in _items)
{ {
DailyItemUpdate(item); DailyUpdater dailyUpdater = getDailyUpdater(item);
dailyUpdater.DailyUpdate(item);
} }
} }
@ -27,66 +28,23 @@ public class GildedRose
private static bool IsBetterWithAgeItem(Item item) => item.Name.ToLower().Equals("aged brie"); private static bool IsBetterWithAgeItem(Item item) => item.Name.ToLower().Equals("aged brie");
private static bool IsRegularItem(Item item) => (!IsLegendaryItem(item) && private DailyUpdater getDailyUpdater(Item item)
!IsBackstagePassesItem(item) &&
!IsBetterWithAgeItem(item));
private static bool IsExpired(Item item) => item.SellIn < 0;
private static void IncreaseQuality(Item item, int byValue)
{ {
item.Quality = int.Min(item.Quality + byValue, MaxQuality); if (IsLegendaryItem(item))
}
private static void DecreaseQuality(Item item, int byValue)
{ {
item.Quality = int.Max(item.Quality - byValue, MinQuality); return new DailyUpdaterForLegendaryItems();
}
private void DailyItemUpdate(Item item)
{
if (IsLegendaryItem(item)) return;
item.SellIn -= 1;
if (IsRegularItem(item))
{
DecreaseQuality(item, 1);
if (IsExpired(item))
{
DecreaseQuality(item, 1);
}
} }
if (IsBetterWithAgeItem(item)) if (IsBetterWithAgeItem(item))
{ {
IncreaseQuality(item, 1); return new DailyUpdaterForBetterWithAgeItems();
if (IsExpired(item))
{
IncreaseQuality(item, 1);
}
} }
if (IsBackstagePassesItem(item)) if (IsBackstagePassesItem(item))
{ {
if (item.SellIn > 9) return new DailyUpdaterForBackstagePassesItems();
{
IncreaseQuality(item, 1);
}
else if (item.SellIn > 4)
{
IncreaseQuality(item, 2);
}
else if (!IsExpired(item))
{
IncreaseQuality(item, 3);
}
else //Expired
{
DecreaseQuality(item, item.Quality);
}
} }
return new DailyUpdaterForRegularItems();
} }
} }

View File

@ -12,11 +12,20 @@ Some of the tests failed due to bugs I discovered in the code/existing tests (e.
I decorated these tests with `[Ignore]` until I get to a stage in the refactoring where I can easily fix the issues and re-introduce the tests. I decorated these tests with `[Ignore]` until I get to a stage in the refactoring where I can easily fix the issues and re-introduce the tests.
2. small refactorings of the UpdateQuality() method to make it more readable and separate the different (unrelated) handling of the different types.<br> 2. small refactorings of the UpdateQuality() method to make it more readable and separate the different (unrelated) handling of the different types.<br>
3. Extract Increasing/Decreasing Quality into a method.<br> 3. Extract Increasing/Decreasing Quality into a method.<br>
It feels like Quality should have been a TinyType that manages its own limits. However, since we're not allowed to change Item, I'm just extracting a method.
4. Separated the processing of the different types from each other.<br> 4. Separated the processing of the different types from each other.<br>
5. Used the `Template` design pattern to create DailyUpdater abstract class and derived classes to handle the DailyUpdate's steps for the different types of items.<br>
The different derived classes will be moved to their own files in the next PR. Left them together for now to show the steps.
6. Created a `Simple Factory` method to return the appropriate DailyUpdater object for the item type.<br>
For this PR, I left this method in the GildedRose.cp to show the steps. But in the next PR I'll move it into its own class.
This is the state of the code now This is the state of the code now
### Considered but dropped
This is all the design ideas/patterns I've considered but decided against
- It feels like Quality should have been a `TinyType` that manages its own limits. However, since we're not allowed to change Item I'm not implementing this.
-