FunctionalDdd.DomainDrivenDesign 3.0.0-alpha.72

This is a prerelease version of FunctionalDdd.DomainDrivenDesign.
dotnet add package FunctionalDdd.DomainDrivenDesign --version 3.0.0-alpha.72
                    
NuGet\Install-Package FunctionalDdd.DomainDrivenDesign -Version 3.0.0-alpha.72
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FunctionalDdd.DomainDrivenDesign" Version="3.0.0-alpha.72" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="FunctionalDdd.DomainDrivenDesign" Version="3.0.0-alpha.72" />
                    
Directory.Packages.props
<PackageReference Include="FunctionalDdd.DomainDrivenDesign" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add FunctionalDdd.DomainDrivenDesign --version 3.0.0-alpha.72
                    
#r "nuget: FunctionalDdd.DomainDrivenDesign, 3.0.0-alpha.72"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package FunctionalDdd.DomainDrivenDesign@3.0.0-alpha.72
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=FunctionalDdd.DomainDrivenDesign&version=3.0.0-alpha.72&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=FunctionalDdd.DomainDrivenDesign&version=3.0.0-alpha.72&prerelease
                    
Install as a Cake Tool

Domain Driven Design

NuGet Package

Building blocks for implementing Domain-Driven Design tactical patterns in C# with functional programming principles.

Installation

dotnet add package FunctionalDdd.DomainDrivenDesign

Quick Start

Entity

Objects with unique identity. Equality based on ID.

public partial class CustomerId : RequiredGuid<CustomerId> { }

public class Customer : Entity<CustomerId>
{
    public string Name { get; private set; }
    
    private Customer(CustomerId id, string name) : base(id)
    {
        Name = name;
    }
    
    public static Result<Customer> TryCreate(string name) =>
        name.ToResult()
            .Ensure(n => !string.IsNullOrWhiteSpace(n), Error.Validation("Name required"))
            .Map(n => new Customer(CustomerId.NewUnique(), n));
}

Value Object

Immutable objects with no identity. Equality based on all properties.

public class Money : ValueObject
{
    public decimal Amount { get; }
    public string Currency { get; }
    
    private Money(decimal amount, string currency)
    {
        Amount = amount;
        Currency = currency;
    }
    
    public static Result<Money> TryCreate(decimal amount, string currency = "USD") =>
        (amount, currency).ToResult()
            .Ensure(x => x.amount >= 0, Error.Validation("Amount cannot be negative"))
            .Map(x => new Money(x.amount, x.currency));
    
    protected override IEnumerable<IComparable> GetEqualityComponents()
    {
        yield return Amount;
        yield return Currency;
    }
}

Aggregate

Cluster of entities and value objects treated as a unit. Manages domain events.

public record OrderCreated(OrderId Id, CustomerId CustomerId, DateTime OccurredAt) : IDomainEvent;

public class Order : Aggregate<OrderId>
{
    private readonly List<OrderLine> _lines = [];
    
    public CustomerId CustomerId { get; }
    public OrderStatus Status { get; private set; }
    
    private Order(OrderId id, CustomerId customerId) : base(id)
    {
        CustomerId = customerId;
        Status = OrderStatus.Draft;
        DomainEvents.Add(new OrderCreated(id, customerId, DateTime.UtcNow));
    }
    
    public static Result<Order> TryCreate(CustomerId customerId) =>
        new Order(OrderId.NewUnique(), customerId).ToResult();
    
    public Result<Order> AddLine(ProductId productId, string name, Money price, int qty) =>
        this.ToResult()
            .Ensure(_ => Status == OrderStatus.Draft, Error.Validation("Order not editable"))
            .Ensure(_ => qty > 0, Error.Validation("Quantity must be positive"))
            .Tap(_ => _lines.Add(new OrderLine(productId, name, price, qty)));
}

Domain Events

Publish events after persisting:

if (order.IsSuccess)
{
    await repository.SaveAsync(order.Value);
    
    foreach (var evt in order.Value.UncommittedEvents())
        await eventBus.PublishAsync(evt);
    
    order.Value.AcceptChanges();
}

Core Types

Type Purpose Equality
Entity<TId> Objects with identity By ID
ValueObject Immutable, no identity By all properties
ScalarValueObject<T> Wraps single primitive By value
Aggregate<TId> Consistency boundary + events By ID
IDomainEvent Marker for domain events

Best Practices

  1. Use entities when identity mattersCustomer : Entity<CustomerId>
  2. Keep aggregates small — Include only what's needed for invariants
  3. Reference other aggregates by IDpublic CustomerId CustomerId { get; } not public Customer Customer { get; }
  4. Use Maybe<T> for optional propertiesMaybe<Url> Website instead of Url?
  5. Enforce invariants in aggregate root — Use Result<T> for validation
  6. Use domain events for side effects — Not direct service calls
  7. Make value objects immutable — No setters

License

MIT — see LICENSE for details.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (3)

Showing the top 3 NuGet packages that depend on FunctionalDdd.DomainDrivenDesign:

Package Downloads
FunctionalDdd.CommonValueObjects

To avoid passing around strings, it is recommended to use RequiredString to obtain strongly typed properties. The source code generator will automate the implementation process.

FunctionalDdd.Testing

Testing utilities and assertions for FunctionalDDD - FluentAssertions extensions, test builders, and fake implementations for Railway-Oriented Programming

FunctionalDdd.PrimitiveValueObjects

Infrastructure and ready-to-use implementations for primitive value objects in Domain-Driven Design. Includes base classes (RequiredString, RequiredGuid) with source generation, plus EmailAddress with RFC 5322 validation. Eliminates primitive obsession with strongly-typed domain primitives.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0-alpha.72 55 2/8/2026
3.0.0-alpha.60 51 2/4/2026
3.0.0-alpha.59 53 2/1/2026
3.0.0-alpha.56 53 1/31/2026
3.0.0-alpha.55 52 1/31/2026
3.0.0-alpha.44 58 1/13/2026
3.0.0-alpha.20 62 1/6/2026
3.0.0-alpha.19 57 1/5/2026
3.0.0-alpha.13 58 1/5/2026
3.0.0-alpha.9 60 1/5/2026
3.0.0-alpha.3 162 12/20/2025
2.1.10 732 12/3/2025
2.1.9 305 11/21/2025
2.1.1 275 4/26/2025
2.1.0-preview.3 109 4/26/2025
2.0.1 266 1/23/2025
2.0.0-alpha.62 106 1/8/2025
2.0.0-alpha.61 109 1/7/2025
2.0.0-alpha.60 117 12/7/2024
2.0.0-alpha.55 110 11/22/2024
Loading failed