DDD Refactoring: Enums++ with Enumeration Classes
DDD Refactoring: Enums++ with Enumeration Classes
Let's refactor ENUMS by moving from traditional ENUM types to enumeration classes
Understanding Problems with Enums
Using C# Enum types has limitations:
- They are value types and cannot have behavior (methods).
- They cannot hold additional data.
- They are not easily extensible without modifying the original enum.
- They don’t support polymorphism.
Example Code
public enum OrderStatus
{
Pending,
Shipped,
Delivered
}Issues with above code
- If you need to associate extra info (like display name or code), you need separate mappings.
- Adding logic (IsFinalStatus ) is impossible inside the Enum.
Fix: Use Enumeration Classes
Enumeration Classes
Enumeration classes are implemented using sealed classes with static instances. They allow: Adding properties
a. Adding methods
b. Strong typing
c. Extensibility
Code Example
public sealed class OrderStatus
{
public string Name { get; }
public int Code { get; }
private OrderStatus(string name, int code)
{
Name = name;
Code = code;
}
// Predefined instances
public static readonly OrderStatus Pending = new OrderStatus("Pending", 1);
public static readonly OrderStatus Shipped = new OrderStatus("Shipped", 2);
public static readonly OrderStatus Delivered = new OrderStatus("Delivered", 3);
// Behavior
public bool IsFinalStatus() => this == Delivered;
// Optional: Get all values
public static IEnumerable<OrderStatus> List() => new[] { Pending, Shipped, Delivered };
// Optional: Parse by code
public static OrderStatus FromCode(int code)
{
return List().FirstOrDefault(s => s.Code == code)
?? throw new ArgumentException($"Invalid code: {code}");
}Execution
var status = OrderStatus.Shipped;
Console.WriteLine($"Status: {status.Name}, Code: {status.Code}");
Console.WriteLine($"Is Final? {status.IsFinalStatus()}");
// Parse from code
var parsed = OrderStatus.FromCode(3);
Console.WriteLine($"Parsed: {parsed.Name}");
``Benefits
Easier to extend without breaking existing code.
a. Adding new statuses or roles doesn’t require changing external logic.
b. You can even extend behavior without modifying existing code (Open/Closed Principle).
Strong Typing & Safety
- No accidental casting to integers (common with enums).
2. Prevents invalid states like OrderStatus status = (OrderStatus)999;
3. This enforces invariants, which is a key DDD principle.
Works Well with DDD
a. This pattern Eliminates Primitive Obsession: DDD warns against Primitive Obsession (using strings, ints for domain concepts).
b. Enumeration classes replace magic numbers or strings with rich domain types.
Comments
Post a Comment