mirror of
https://github.com/emilybache/GildedRose-Refactoring-Kata.git
synced 2026-02-08 03:01:24 +00:00
4.8 KiB
4.8 KiB
GildedRose Refactoring Kata - C# Solution
This solution demonstrates a refactoring of the GildedRose kata using clean code principles and design patterns.
Design Patterns Used
Class Diagram
classDiagram
class Item {
+string Name
+int SellIn
+int Quality
}
class GildedRose {
-IList~Item~ Items
+UpdateQuality()
}
class IUpdateStrategy {
<<interface>>
+UpdateQuality(Item)
}
class BaseUpdateStrategy {
<<abstract>>
#DecreaseQuality(Item)
#IncreaseQuality(Item)
#DecreaseSellIn(Item)
+UpdateQuality(Item)*
}
class UpdateStrategyFactory {
+CreateStrategy(string) IUpdateStrategy$
}
StandardItemStrategy --|> BaseUpdateStrategy
AgedBrieStrategy --|> BaseUpdateStrategy
BackstagePassStrategy --|> BaseUpdateStrategy
SulfurasStrategy --|> BaseUpdateStrategy
ConjuredItemStrategy --|> BaseUpdateStrategy
BaseUpdateStrategy ..|> IUpdateStrategy
GildedRose --> IUpdateStrategy
GildedRose --> UpdateStrategyFactory
UpdateStrategyFactory ..> BaseUpdateStrategy
1. Strategy Pattern
The main design pattern used in this refactoring is the Strategy Pattern, which enables:
- Encapsulation of different item update algorithms
- Easy addition of new item types
- Elimination of complex conditional logic
The pattern is implemented through:
IUpdateStrategy: Interface defining the contract for all strategiesBaseUpdateStrategy: Abstract base class with common functionality- Concrete strategies for each item type:
StandardItemStrategyAgedBrieStrategyBackstagePassStrategySulfurasStrategyConjuredItemStrategy
2. Factory Pattern
The Factory Pattern is used to create appropriate strategies:
UpdateStrategyFactory: Creates the correct strategy based on item name- Centralizes strategy instantiation
- Makes it easy to add new item types
Code Structure
GildedRose/
├── ItemCategory.cs # Constants and configuration
├── IUpdateStrategy.cs # Strategy interface
├── BaseUpdateStrategy.cs # Common strategy functionality
├── Strategies/
│ ├── StandardItemStrategy.cs
│ ├── AgedBrieStrategy.cs
│ ├── BackstagePassStrategy.cs
│ ├── SulfurasStrategy.cs
│ └── ConjuredItemStrategy.cs
└── UpdateStrategyFactory.cs # Factory for creating strategies
Key Improvements
-
Separation of Concerns
- Each item type has its own strategy class
- Common functionality extracted to base class
- Clear responsibility boundaries
-
Maintainability
- Eliminated nested if statements
- Removed code duplication
- Centralized constants
- Easy to modify individual item behaviors
-
Extensibility
- Adding new item types only requires:
- Creating a new strategy class
- Adding item name to ItemCategory
- Adding strategy to factory
- No modification of existing code needed (Open/Closed Principle)
- Adding new item types only requires:
-
Testability
- Each strategy can be tested independently
- Clear test cases for each item type
- Easy to add tests for new items
How to Use
-
Adding a New Item Type
// 1. Add item name to ItemCategory public static class ItemCategory { public const string NewItem = "New Item Name"; } // 2. Create new strategy public class NewItemStrategy : BaseUpdateStrategy { public override void UpdateQuality(Item item) { // Implement update logic } } // 3. Add to factory public static class UpdateStrategyFactory { public static IUpdateStrategy CreateStrategy(string itemName) { return itemName switch { ItemCategory.NewItem => new NewItemStrategy(), // ... existing cases }; } } -
Modifying Item Behavior
- Locate the appropriate strategy class
- Modify the UpdateQuality method
- Add/update tests as needed
Testing
The solution includes comprehensive tests:
- Unit tests for each item type
- Edge case testing
- Approval tests for system behavior
- Quality boundary tests
- SellIn date tests
Future Enhancements
The code is structured to easily accommodate future changes:
- Double degradation for Conjured items
- New item types
- Modified quality rules
- Additional item properties
Design Principles Applied
- Single Responsibility Principle: Each class has one reason to change
- Open/Closed Principle: Open for extension, closed for modification
- Dependency Inversion: High-level modules depend on abstractions
- DRY (Don't Repeat Yourself): Common logic in base class
- KISS (Keep It Simple, Stupid): Clear, straightforward implementations