Skip to content

E-Commerce DDD Layered Architecture

E-commerce domain: 5 Aggregates (Customer, Product, Order, Inventory, Tag) + Domain Service + Application Layer CQRS.

public class Order
{
public string CustomerId { get; set; }
public string Status { get; set; }
public decimal TotalAmount { get; set; }
public List<OrderLineDto> Lines { get; set; }
}
public class OrderLineDto
{
public string ProductId { get; set; }
public int Quantity { get; set; }
public decimal UnitPrice { get; set; }
}

This implementation compiles and runs. However, it permits the following invalid states:

  • Any string can be assigned to Status — invalid order states are possible
  • Negative amounts, zero or negative quantities — no value range validation
  • Empty order lines — orders without any items can be created
  • Manual total calculation — TotalAmount and the sum of line totals can be inconsistent
  • No credit limit verification — orders exceeding customer credit are confirmed

4 guarantees:

  1. Type safety — Value objects are fully validated at creation time
  2. Invariant enforcement — State machines and structural constraints prevent invalid states at the source
  3. CQRS separation — Command/Query independent optimization
  4. Pipeline automation — Validation/error handling automation via Apply pattern + FinT monad

DDD tactical patterns define rule boundaries, and Functorium’s functional types enforce them at the compiler level.

This example divides the Domain layer and Application layer into two tracks, going from naive code to a complete DDD model through 4 stages each.

StageDomain LayerApplication Layer
0. RequirementsDomain business requirementsApplication business requirements
1. DesignDomain type design decisionsApplication type design decisions
2. CodeDomain code designApplication code design
3. ResultsDomain implementation resultsApplication implementation results
DDD ConceptFunctorium TypeApplication
Value ObjectSimpleValueObject<T>, ComparableSimpleValueObject<T>CustomerName, Email, Money, Quantity, ProductName, etc.
Smart EnumSimpleValueObject<string> + HashMapOrderStatus (5 states, transition rules)
EntityEntity<TId>OrderLine (child entity)
Aggregate RootAggregateRoot<TId>Customer, Product, Order, Inventory, Tag
Domain EventDomainEvent19 types (Created, Updated, Confirmed, etc.)
Domain ErrorDomainErrorType.CustomEmptyOrderLines, InvalidOrderStatusTransition, etc.
SpecificationExpressionSpecification<T>ProductNameSpec, CustomerEmailSpec, etc. (6 types)
Domain ServiceIDomainServiceOrderCreditCheckService
RepositoryIRepository<T, TId>5 Repository interfaces
PatternImplementationApplication
CQRSICommandUsecase / IQueryUsecase10 Commands, 9 Queries
Apply Patterntuple.Apply()Parallel VO validation composition
FinT LINQfrom...in chainingAsynchronous error propagation
Port/AdapterIQueryPort, IRepositoryRead/write separation
FluentValidationMustSatisfyValidationSyntactic + semantic dual validation
Nested ClassRequest, Response, Validator, UsecaseUse Case encapsulation
samples/ecommerce-ddd/
├── Directory.Build.props
├── Directory.Build.targets
├── ecommerce-ddd.slnx
├── domain/ # Domain layer documentation
│ ├── 00-business-requirements.md
│ ├── 01-type-design-decisions.md
│ ├── 02-code-design.md
│ └── 03-implementation-results.md
├── application/ # Application layer documentation
│ ├── 00-business-requirements.md
│ ├── 01-type-design-decisions.md
│ ├── 02-code-design.md
│ └── 03-implementation-results.md
├── Src/
│ ├── ECommerce.Domain/
│ │ ├── SharedModels/
│ │ │ ├── ValueObjects/ (Money, Quantity)
│ │ │ └── Services/ (OrderCreditCheckService)
│ │ └── AggregateRoots/
│ │ ├── Customers/ (Customer, VOs, Specs)
│ │ ├── Products/ (Product, VOs, Specs)
│ │ ├── Orders/ (Order, OrderLine, VOs)
│ │ ├── Inventories/ (Inventory, Specs)
│ │ └── Tags/ (Tag, VOs)
│ └── ECommerce.Application/
│ ├── Ports/ (IExternalPricingService)
│ └── Usecases/
│ ├── Products/ (Commands, Queries, Ports)
│ ├── Customers/ (Commands, Queries, Ports)
│ ├── Orders/ (Commands, Queries, Ports)
│ └── Inventories/ (Queries, Ports)
└── Tests/
└── ECommerce.Tests.Unit/ (301 tests)
├── Architecture/ # Architecture rule verification (26 tests)
├── Domain/
└── Application/
Terminal window
# Build
dotnet build Docs.Site/src/content/docs/samples/ecommerce-ddd/ecommerce-ddd.slnx
# Test
dotnet test --solution Docs.Site/src/content/docs/samples/ecommerce-ddd/ecommerce-ddd.slnx