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}");
}

E

xecution


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

  1. 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

Popular posts from this blog

WordPress.com or WordPress.Org??

Northwind Database

How To Shrink And Fit To Pages When Printing In Outlook?