Enumerations¶
Info
At ConnectSoft, Enumerations are not simple technical enums —
they are rich domain concepts that evolve, carry behaviors, and express business meaning cleanly.
Introduction¶
In Domain-Driven Design (DDD), Enumerations are used to model domain-specific choices and states
that must be explicit, meaningful, and sometimes behavior-rich — going beyond simple technical enums.
Simple Enums (like integers) are often insufficient because:
- They are not extensible without modifying source code.
- They cannot carry domain behaviors.
- They are tightly coupled to static primitives.
At ConnectSoft, we use Enumeration Classes (sometimes called Smart Enums) to:
- Model complex business concepts (e.g., OrderStatus, PaymentMethod, SubscriptionPlan).
- Add behaviors and business rules directly into the Enumeration.
- Support future extensibility without major rewrites.
Concept Definition¶
An Enumeration in the DDD sense:
| Aspect | Description |
|---|---|
| Purpose | Represents a fixed set of meaningful domain choices. |
| Type | Modeled as a full class, not just primitive enums. |
| Behavior | Can carry domain behaviors and validations. |
| Extensibility | New values can be added without breaking old code. |
| Identity | Identified by stable IDs or Codes, not implicit ordering. |
| Examples | OrderStatus, PaymentMethod, AppointmentType. |
📚 Why Rich Enumerations Matter at ConnectSoft¶
✅ Model Business Language Precisely
- Enumerations express domain concepts clearly (e.g., "Paid", "Pending", "Cancelled").
✅ Extend Behavior Safely
- New options can add new behaviors (e.g., different pricing logic for a new SubscriptionPlan).
✅ Preserve Backward Compatibility
- Systems consuming Enumerations via APIs or Events remain stable as new options are introduced.
✅ Encourage Open/Closed Principle
- Behavior can change based on the Enumeration without changing consumers.
✅ Improve Domain Expressiveness
- Code reads naturally for developers and business stakeholders alike.
Simple Enum vs Rich Enumeration Class¶
| Aspect | Simple Enum | Rich Enumeration |
|---|---|---|
| Type | Language primitive (enum) |
Class-based model |
| Behavior | Cannot hold methods or logic | Can contain domain behaviors |
| Extensibility | Requires recompilation | Extendable without touching existing code |
| Serialization Control | Limited (names/ints) | Full control (Id, Name, extra metadata) |
| Example | enum OrderStatus { Pending, Paid, Cancelled } |
OrderStatus.Pending, OrderStatus.Paid instances with behavior |
🧩 Visual: Enumeration and Domain Entity Relationship¶
flowchart TD
OrderEntity["Order Entity"]
OrderStatusEnum["OrderStatus Enumeration"]
PaymentEntity["Payment Entity"]
PaymentMethodEnum["PaymentMethod Enumeration"]
OrderEntity -->|Has Status| OrderStatusEnum
PaymentEntity -->|Has Method| PaymentMethodEnum
✅ Entities reference Enumerations to model their domain states clearly.
✅ Enumerations may evolve independently from core Entity structure.
Strategic Design Principles for Enumerations¶
At ConnectSoft, Enumerations are modeled intentionally —
only when a domain concept needs clear expression, stable identity, possible behavior, and safe evolution.
📚 Core Principles for Good Enumeration Design¶
✅ Model Real Domain Concepts
- Only introduce Enumerations for business-relevant states, types, or modes — not for technical flags.
✅ Prefer Class-Based Enumerations Over Language Primitives
- Primitive enums are not flexible enough to evolve with complex business needs.
✅ Expose Stable Identifiers
- Each Enumeration instance must expose a stable Id (integer or string) and a business-meaningful Name.
✅ Allow Behavior When Needed
- If needed, Enumeration classes can include methods or strategies related to the specific type.
✅ Respect Open/Closed Principle
- Adding a new Enumeration value should not require changing existing consumers.
✅ Support Serialization Explicitly
- Enumerations must serialize to known IDs or names — never rely on implicit enum integer values.
✅ Avoid Mixing Enumeration and Infrastructure Concerns
- Enumerations belong in the Domain Layer, not infrastructure or DTOs.
🎯 Clear Criteria: When to Use Rich Enumerations¶
| ✅ Use Rich Enumeration | 🚫 Don't Use Rich Enumeration |
|---|---|
| Fixed set of domain states/types needed | Ad-hoc, volatile flags |
| Possibility of behaviors per option | No behavior variation |
| Business needs clear naming, IDs, metadata | Internal-only technical flags |
| States evolve but require backward compatibility | Constantly changing tech toggles |
| Need for future extension without breaking changes | Static, unchanging two-state flags |
🛑 Common Anti-Patterns to Avoid¶
| Anti-Pattern | Symptom | Why It's Dangerous |
|---|---|---|
| Primitive Enums Everywhere | Use enums for all states, no extensibility. | Breaks flexibility, requires redeployment on changes. |
| Leaking Persistence Concerns | Enumeration depends on database structure (e.g., foreign key to enum table). | Tight coupling, breaks evolution safety. |
| Mixed Domain and Infrastructure Concepts | Enumeration carries persistence IDs, DTO properties. | Violates clean architecture separation. |
| Unstable Identifiers | Enumeration values change ID or Name after creation. | Breaks historical data, event consumers, APIs. |
| Overloading Enums | Put unrelated concepts into a single Enumeration. | Poor domain clarity, violates SRP (Single Responsibility Principle). |
📚 Good vs Bad Enumeration Examples¶
| ✅ Good Enumeration Example | 🚫 Bad Enumeration Example |
|---|---|
OrderStatus: Pending, Paid, Cancelled |
Flags: A, B, C, D (no meaning) |
PaymentMethod: CreditCard, PayPal, WireTransfer |
ProcessFlags: 0, 1, 2, 3 |
SubscriptionPlan: Free, Premium, Enterprise |
DbEnum: 1, 2, 3 with no meaning outside DB |
| Values stable across system lifetime | Values tied to database row IDs |
🧩 Visual: Enumeration Open/Closed Evolution¶
flowchart LR
v1["Initial Enumeration"]
v2["Enumeration + New Option Added (Backward Compatible)"]
Consumer1["Old Consumer"]
Consumer2["New Consumer"]
v1 --> Consumer1
v2 --> Consumer1
v2 --> Consumer2
✅ Existing consumers remain stable even when new Enumeration options are added.
ConnectSoft.Extensions.EntityModel.Enumeration Base Class¶
At ConnectSoft, we use the ConnectSoft.Extensions.EntityModel.Enumeration base class
to provide a consistent, powerful foundation for all enumeration implementations.
The base class provides:
Value(int) — Stable numeric identifier for persistence and serializationShortName(string) — Concise identifier for APIs and code referencesLongName(string) — Human-readable description for UI and documentationGetAll<T>()— Static method to retrieve all enumeration values via reflectionFromValue<T>(int value)— Factory method to create enumeration from numeric valueFromShortName<T>(string shortName)— Factory method to create enumeration from short nameEquals(),GetHashCode(),ToString()— Proper value semanticsIComparable— Support for sorting and comparison operations
C# Examples: Domain-Driven Enumerations at ConnectSoft¶
At ConnectSoft, Enumerations are full domain models —
not just primitive flags — and often carry business rules, validations, and metadata.
All examples below are based on real implementations from the ConnectSoft.Saas.ProductsCatalog microservice.
🛠️ Example 1: SaaS Product Catalog — ProductStatusEnumeration¶
Real Implementation from ConnectSoft.Saas.ProductsCatalog.EntityModel:
// Ignore Spelling: Saas
namespace ConnectSoft.Saas.ProductsCatalog.EntityModel
{
using System;
using ConnectSoft.Extensions.EntityModel;
/// <summary>
/// Product status enumeration.
/// </summary>
public class ProductStatusEnumeration : Enumeration
{
/// <summary>
/// Active - product status.
/// </summary>
public static readonly ProductStatusEnumeration Active = new ActiveProductStatusEnumeration();
/// <summary>
/// Inactive - product status.
/// </summary>
public static readonly ProductStatusEnumeration Inactive = new InactiveProductStatusEnumeration();
/// <summary>
/// Deprecated - product status.
/// </summary>
public static readonly ProductStatusEnumeration Deprecated = new DeprecatedProductStatusEnumeration();
/// <summary>
/// Initializes a new instance of the <see cref="ProductStatusEnumeration"/> class.
/// </summary>
protected ProductStatusEnumeration()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ProductStatusEnumeration"/> class.
/// </summary>
/// <param name="value">the value.</param>
/// <param name="shortName">the sort name.</param>
/// <param name="longName">the long name.</param>
protected ProductStatusEnumeration(int value, string shortName, string longName)
: base(value, shortName, longName)
{
}
/// <summary>
/// Active - product status enumeration class.
/// </summary>
[Serializable]
private sealed class ActiveProductStatusEnumeration : ProductStatusEnumeration
{
public ActiveProductStatusEnumeration()
: base(1, "Active", "Active")
{
}
}
/// <summary>
/// Inactive - product status enumeration class.
/// </summary>
[Serializable]
private sealed class InactiveProductStatusEnumeration : ProductStatusEnumeration
{
public InactiveProductStatusEnumeration()
: base(2, "Inactive", "Inactive")
{
}
}
/// <summary>
/// Deprecated - product status enumeration class.
/// </summary>
[Serializable]
private sealed class DeprecatedProductStatusEnumeration : ProductStatusEnumeration
{
public DeprecatedProductStatusEnumeration()
: base(3, "Deprecated", "Deprecated")
{
}
}
}
}
Key Pattern Elements:
✅ Inherits from ConnectSoft.Extensions.EntityModel.Enumeration
✅ Protected constructors prevent external instantiation
✅ Private sealed nested classes for each enumeration value
✅ [Serializable] attribute for persistence and serialization support
✅ Three-part identity: Value (int), ShortName (string), LongName (string)
Usage in Entity:
public partial class ProductEntity : EntityWithTypedId<Guid>, IProduct
{
// ... other properties ...
/// <inheritdoc/>
required public virtual ProductStatusEnumeration Status { get; set; }
// ... other properties ...
}
Usage in Domain Logic:
var newProduct = new ProductEntity
{
ProductId = productId,
Name = "Salesforce CRM Cloud",
DisplayName = "Salesforce CRM Cloud",
Key = "Salesforce-CRM-Cloud",
Description = "Unified CRM platform for sales, marketing, and customer support.",
ProductCategory = "CRM",
Status = ProductStatusEnumeration.Active, // ✅ Using static readonly field
LatestVersion = "v1.0.0",
ReleaseNotes = "Initial release.",
};
🛠️ Example 2: SaaS Product Catalog — PricingTypeEnumeration with Rich Metadata¶
Real Implementation showing enumerations with descriptive metadata:
// Ignore Spelling: Saas Freemium
namespace ConnectSoft.Saas.ProductsCatalog.EntityModel
{
using System;
using ConnectSoft.Extensions.EntityModel;
/// <summary>
/// Pricing type enumeration.
/// </summary>
public class PricingTypeEnumeration : Enumeration
{
/// <summary>
/// Fixed price - pricing type.
/// </summary>
public static readonly PricingTypeEnumeration FixedPrice = new FixedPricePricingTypeEnumeration();
/// <summary>
/// Tiered pricing - pricing type.
/// </summary>
public static readonly PricingTypeEnumeration TieredPricing = new TieredPricingPricingTypeEnumeration();
/// <summary>
/// Usage-based pricing - pricing type.
/// </summary>
public static readonly PricingTypeEnumeration UsageBasedPricing = new UsageBasedPricingPricingTypeEnumeration();
/// <summary>
/// Freemium - pricing type.
/// </summary>
public static readonly PricingTypeEnumeration Freemium = new FreemiumPricingTypeEnumeration();
/// <summary>
/// Subscription-based pricing - pricing type.
/// </summary>
public static readonly PricingTypeEnumeration SubscriptionBased = new SubscriptionBasedPricingTypeEnumeration();
// ... more pricing types ...
/// <summary>
/// Initializes a new instance of the <see cref="PricingTypeEnumeration"/> class.
/// </summary>
protected PricingTypeEnumeration()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PricingTypeEnumeration"/> class.
/// </summary>
/// <param name="value">the value.</param>
/// <param name="shortName">the sort name.</param>
/// <param name="longName">the long name.</param>
protected PricingTypeEnumeration(int value, string shortName, string longName)
: base(value, shortName, longName)
{
}
/// <summary>
/// Fixed Price - pricing type enumeration class.
/// </summary>
[Serializable]
private sealed class FixedPricePricingTypeEnumeration : PricingTypeEnumeration
{
public FixedPricePricingTypeEnumeration()
: base(1, "Fixed Price", "Fixed Price - A set price for the product or service regardless of usage or other factors.")
{
}
}
/// <summary>
/// Tiered Pricing - pricing type enumeration class.
/// </summary>
[Serializable]
private sealed class TieredPricingPricingTypeEnumeration : PricingTypeEnumeration
{
public TieredPricingPricingTypeEnumeration()
: base(2, "Tiered Pricing", "Pricing that changes based on usage or quantities. Different tiers offer different pricing levels.")
{
}
}
/// <summary>
/// Usage-Based Pricing - pricing type enumeration class.
/// </summary>
[Serializable]
private sealed class UsageBasedPricingPricingTypeEnumeration : PricingTypeEnumeration
{
public UsageBasedPricingPricingTypeEnumeration()
: base(4, "Usage-Based Pricing", "Pricing based on the amount of resources consumed or features used.")
{
}
}
/// <summary>
/// Freemium - pricing type enumeration class.
/// </summary>
[Serializable]
private sealed class FreemiumPricingTypeEnumeration : PricingTypeEnumeration
{
public FreemiumPricingTypeEnumeration()
: base(7, "Freemium", "Offering basic features for free, with additional charges for premium features or higher usage.")
{
}
}
/// <summary>
/// Subscription-Based - pricing type enumeration class.
/// </summary>
[Serializable]
private sealed class SubscriptionBasedPricingTypeEnumeration : PricingTypeEnumeration
{
public SubscriptionBasedPricingTypeEnumeration()
: base(8, "Subscription-Based", "Recurring charges on a periodic basis (e.g., monthly, annually).")
{
}
}
}
}
✅ Rich LongName descriptions provide business context in the enumeration itself.
✅ Extensible pattern — new pricing types can be added without modifying existing code.
🛠️ Example 3: SaaS Product Catalog — BillingCycleEnumeration with Business Context¶
Real Implementation showing enumerations with domain-specific descriptions:
// Ignore Spelling: Saas
namespace ConnectSoft.Saas.ProductsCatalog.EntityModel
{
using System;
using ConnectSoft.Extensions.EntityModel;
/// <summary>
/// The BillingCycle enumeration represents different billing frequencies or cycles at which charges are applied.
/// Depending on your SaaS product's pricing structure, you might need to support various billing cycles.
/// </summary>
public class BillingCycleEnumeration : Enumeration
{
/// <summary>
/// Monthly billing cycle.
/// </summary>
public static readonly BillingCycleEnumeration Monthly = new MonthlyBillingCycleEnumeration();
/// <summary>
/// Quarterly billing cycle.
/// </summary>
public static readonly BillingCycleEnumeration Quarterly = new QuarterlyBillingCycleEnumeration();
/// <summary>
/// Annually billing cycle.
/// </summary>
public static readonly BillingCycleEnumeration Annually = new AnnuallyBillingCycleEnumeration();
/// <summary>
/// One-Time billing cycle.
/// </summary>
public static readonly BillingCycleEnumeration OneTime = new OneTimeBillingCycleEnumeration();
// ... more billing cycles ...
/// <summary>
/// Initializes a new instance of the <see cref="BillingCycleEnumeration"/> class.
/// </summary>
protected BillingCycleEnumeration()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="BillingCycleEnumeration"/> class.
/// </summary>
/// <param name="value">the value.</param>
/// <param name="shortName">the sort name.</param>
/// <param name="longName">the long name.</param>
protected BillingCycleEnumeration(int value, string shortName, string longName)
: base(value, shortName, longName)
{
}
/// <summary>
/// Monthly - billing cycle enumeration class.
/// </summary>
[Serializable]
private sealed class MonthlyBillingCycleEnumeration : BillingCycleEnumeration
{
public MonthlyBillingCycleEnumeration()
: base(1, "Monthly", "Billing occurs on a monthly basis. Charges are applied every 30 days.")
{
}
}
/// <summary>
/// Quarterly - billing cycle enumeration class.
/// </summary>
[Serializable]
private sealed class QuarterlyBillingCycleEnumeration : BillingCycleEnumeration
{
public QuarterlyBillingCycleEnumeration()
: base(2, "Quarterly", "Billing occurs every three months. Charges are applied every 90 days.")
{
}
}
/// <summary>
/// Annually - billing cycle enumeration class.
/// </summary>
[Serializable]
private sealed class AnnuallyBillingCycleEnumeration : BillingCycleEnumeration
{
public AnnuallyBillingCycleEnumeration()
: base(4, "Annually", "Billing occurs once a year. Charges are applied every 365 days.")
{
}
}
/// <summary>
/// One-Time - billing cycle enumeration class.
/// </summary>
[Serializable]
private sealed class OneTimeBillingCycleEnumeration : BillingCycleEnumeration
{
public OneTimeBillingCycleEnumeration()
: base(5, "One-Time", "A single charge is applied once, with no recurring billing. A one-time purchase or setup fee.")
{
}
}
}
}
Usage in Entity with Multiple Enumerations:
public class PricingModelEntity : EntityWithTypedId<Guid>, IPricingModel
{
// ... other properties ...
/// <inheritdoc/>
required public virtual PricingTypeEnumeration PricingType { get; set; }
/// <inheritdoc/>
required public virtual BillingCycleEnumeration BillingCycle { get; set; }
// ... other properties ...
}
Usage Example:
var pricingModel = new PricingModelEntity
{
PricingModelId = Guid.NewGuid(),
Name = "Premium Subscription",
Key = "premium-subscription",
DisplayName = "Premium Subscription Plan",
Description = "Full feature access with monthly billing",
CreationDate = DateTime.UtcNow,
PricingType = PricingTypeEnumeration.SubscriptionBased, // ✅ Using enumeration
Currency = "USD",
BasePrice = 99.99m,
BillingCycle = BillingCycleEnumeration.Monthly, // ✅ Using enumeration
MinimumPrice = 99.99m,
MaximumPrice = 99.99m,
EditionPricingModels = new List<IEditionPricingModel>(),
};
🛠️ Working with Enumerations: Common Operations¶
The ConnectSoft.Extensions.EntityModel.Enumeration base class provides powerful static methods:
Getting All Enumeration Values¶
// Get all ProductStatusEnumeration values
IEnumerable<ProductStatusEnumeration> allStatuses =
Enumeration.GetAll<ProductStatusEnumeration>();
// Use in LINQ queries, validation, UI dropdowns, etc.
foreach (var status in allStatuses)
{
Console.WriteLine($"{status.Value}: {status.ShortName} - {status.LongName}");
}
Creating Enumerations from Values¶
// Parse from numeric value (e.g., from database)
ProductStatusEnumeration status =
Enumeration.FromValue<ProductStatusEnumeration>(1); // Returns Active
// Parse from short name (e.g., from API request)
ProductStatusEnumeration statusFromName =
Enumeration.FromShortName<ProductStatusEnumeration>("Active");
// Throws InvalidEnumerationException if value/name not found
Comparing Enumerations¶
// Value equality
if (product.Status == ProductStatusEnumeration.Active)
{
// Product is active
}
// Comparison for sorting
var sortedStatuses = Enumeration.GetAll<ProductStatusEnumeration>()
.OrderBy(s => s); // Uses IComparable implementation
// Absolute difference calculation
int difference = Enumeration.AbsoluteDifference(
ProductStatusEnumeration.Active,
ProductStatusEnumeration.Deprecated
);
Using in Entity Queries¶
// Find all active products
var activeProducts = repository.Query<ProductEntity>()
.Where(p => p.Status == ProductStatusEnumeration.Active)
.ToList();
// Find products by pricing type
var freemiumProducts = repository.Query<ProductEntity>()
.Where(p => p.PricingModel.PricingType == PricingTypeEnumeration.Freemium)
.ToList();
📋 Complete Implementation Template¶
Here's a complete template you can use to create new enumerations following ConnectSoft patterns:
// Ignore Spelling: [Add any domain-specific terms here]
namespace YourNamespace.EntityModel
{
using System;
using ConnectSoft.Extensions.EntityModel;
/// <summary>
/// [Your enumeration] enumeration.
/// </summary>
public class YourEnumeration : Enumeration
{
/// <summary>
/// [First value] - [description].
/// </summary>
public static readonly YourEnumeration FirstValue = new FirstValueEnumeration();
/// <summary>
/// [Second value] - [description].
/// </summary>
public static readonly YourEnumeration SecondValue = new SecondValueEnumeration();
/// <summary>
/// Initializes a new instance of the <see cref="YourEnumeration"/> class.
/// </summary>
protected YourEnumeration()
{
}
/// <summary>
/// Initializes a new instance of the <see cref="YourEnumeration"/> class.
/// </summary>
/// <param name="value">the value.</param>
/// <param name="shortName">the sort name.</param>
/// <param name="longName">the long name.</param>
protected YourEnumeration(int value, string shortName, string longName)
: base(value, shortName, longName)
{
}
/// <summary>
/// [First value] - [description] enumeration class.
/// </summary>
[Serializable]
private sealed class FirstValueEnumeration : YourEnumeration
{
public FirstValueEnumeration()
: base(1, "FirstValue", "Descriptive long name for FirstValue")
{
}
}
/// <summary>
/// [Second value] - [description] enumeration class.
/// </summary>
[Serializable]
private sealed class SecondValueEnumeration : YourEnumeration
{
public SecondValueEnumeration()
: base(2, "SecondValue", "Descriptive long name for SecondValue")
{
}
}
}
}
✅ Follow this pattern for all new enumerations to ensure consistency across ConnectSoft projects.
📚 Key Lessons from ConnectSoft Enumeration Modeling¶
| Good Practice | Why It Matters | ConnectSoft Implementation |
|---|---|---|
Inherit from ConnectSoft.Extensions.EntityModel.Enumeration |
Provides consistent base functionality across all enumerations | All enumeration classes inherit from the base Enumeration class |
| Use Value, ShortName, and LongName | Three-part identity enables clear APIs, persistence, and UI display | Value (int) for persistence, ShortName (string) for code/APIs, LongName (string) for UI |
| Private sealed nested classes for values | Encapsulation and type safety — prevents external instantiation | Each enumeration value is a private sealed nested class (e.g., ActiveProductStatusEnumeration) |
| Protected constructors | Prevents external instantiation while allowing inheritance | Base class and derived enumerations use protected constructors |
[Serializable] attribute |
Enables proper serialization for persistence and messaging | All nested enumeration value classes are marked [Serializable] |
Use Enumeration.GetAll<T>() |
Reflection-based discovery of all enumeration values | Base class provides GetAll<T>() method for retrieving all values |
Use Enumeration.FromValue<T>() and FromShortName<T>() |
Safe parsing from persisted values or API inputs | Factory methods handle parsing with proper exception handling |
| Rich LongName descriptions | Business context embedded in enumeration itself | LongName provides detailed descriptions for UI and documentation |
| Stable Value identifiers | Never change numeric IDs after creation — ensures backward compatibility | Value IDs are assigned once and never modified |
🧩 Visual: Enumeration Usage Inside Application Service Workflow¶
sequenceDiagram
participant API
participant ApplicationService
participant OrderAggregate
participant Enumeration as OrderStatus Enumeration
API->>ApplicationService: Place Order Request
ApplicationService->>OrderAggregate: Create Order
OrderAggregate->>Enumeration: Set Initial Status (Pending)
OrderAggregate-->>ApplicationService: Order Created
ApplicationService-->>API: Success Response
✅ Enumerations participate naturally in orchestrated domain workflows.
Best Practices for Enumerations¶
At ConnectSoft, Enumerations are modeled as living domain concepts,
empowering the system to evolve naturally, scale behaviors, and communicate business meaning clearly.
📚 Best Practices Checklist¶
✅ Use Enumeration Classes, Not Primitive Enums
- Prefer class-based smart enums that can evolve and carry behavior.
✅ Expose Stable Identifiers and Names
- Provide explicit
IdandNamefields for safe persistence, messaging, and APIs.
✅ Model Business Behavior and Metadata
- Add domain-relevant behaviors (e.g., validation rules, strategy differences).
✅ Apply Open/Closed Principle
- Add new Enumeration options without modifying consumer code.
✅ Avoid Leaking Infrastructure Concerns
- Keep Enumerations pure — no database IDs, no DTO dependencies.
✅ Support Validation and Lookups
- Provide explicit methods for listing, looking up, and validating Enumeration instances.
✅ Version Carefully if Necessary
- If Enumerations are exposed in public APIs or events, design versioning strategies safely.
✅ Use Enumerations Only for Meaningful Domain Concepts
- Avoid overloading Enumerations for technical flags or volatile toggles.
Conclusion¶
At ConnectSoft, Enumerations are not afterthoughts —
they are strategic tools to:
- Express real-world business states, types, and choices.
- Safely extend system capabilities without risking fragile code rewrites.
- Capture behaviors and metadata inside clear, maintainable models.
- Enable APIs, Events, and UI layers to speak the true language of the domain.
Without rich Enumerations:
- Systems drift into fragile procedural checks (
if-else,switch-casechaos). - Adding a new type or status requires breaking core logic everywhere.
- Business meaning is hidden behind technical plumbing.
With strong Enumeration modeling:
- Evolution becomes safe.
- Communication becomes clear.
- Architecture remains aligned to business agility.
At ConnectSoft, Enumerations safeguard the flexibility, expressiveness, and integrity of our domain-driven software systems —
from E-Commerce to Finance to Healthcare to SaaS and AI ecosystems.
"Enumerations capture choices;
Smart Enumerations empower evolutions.
Build for change, model with meaning."
References¶
-
Books and Literature
- Eric Evans — Domain-Driven Design: Tackling Complexity in the Heart of Software
- Vaughn Vernon — Implementing Domain-Driven Design
- Jimmy Nilsson — Applying Domain-Driven Design and Patterns
-
Online Resources
-
ConnectSoft Packages and Code
ConnectSoft.Extensions.EntityModel.Enumeration— Base enumeration class providing:- Value, ShortName, and LongName properties
GetAll<T>()method for reflection-based discoveryFromValue<T>()andFromShortName<T>()factory methods- Proper equality, hashing, and comparison semantics
- Serialization support
- Real-World Examples — See
ConnectSoft.Saas.ProductsCatalog.EntityModelfor production implementations:ProductStatusEnumerationPricingTypeEnumerationBillingCycleEnumerationAccessTypeEnumeration- And more...
-
ConnectSoft Internal Standards
- ConnectSoft Smart Enumeration Patterns Playbook
- ConnectSoft API and Event Modeling Guidelines
- ConnectSoft Domain Layer Evolution Strategies