public record Order( // 0 · a record: shape, nothing more
Guid Id, Guid CustomerId,
IReadOnlyList<Line> Lines,
OrderStatus Status, int Version, decimal Total, string Label);// 1 · rules between rows, written next to the types
public static readonly Constraint<Shop> LinesPointAtAnOrder =
Constraints<Shop>.References(
s => s.Lines, l => [l.OrderId], s => s.Orders.Select(o => o.Id));
public static readonly Constraint<Shop> OrderIdsAreUnique =
Constraints<Shop>.Unique(s => s.Orders, o => o.Id);// 2 · rules about values, with a name and a sentence
public static readonly Constraint<Order> TotalNeverNegative =
Constraints<Order>.Always(
o => o.Total, t => t >= 0, "An order total is never negative.");
public static readonly Constraint<Order> MoneyIsConserved =
Constraints<Order>.Always(
o => o.Lines.Sum(l => l.Qty * l.Price) == o.Total,
"The total is the sum of the lines.");// 3 · what may follow what
public static readonly StateMachine<OrderStatus, string> Lifecycle =
StateMachine.Define<OrderStatus, string>(OrderStatus.Draft)
.Permit("place", OrderStatus.Draft, OrderStatus.Placed)
.Permit("pay", OrderStatus.Placed, OrderStatus.Paid)
.Permit("ship", OrderStatus.Paid, OrderStatus.Shipped)
.Permit("cancel", [OrderStatus.Placed, OrderStatus.Paid],
OrderStatus.Cancelled)
.Build();// 4 · time: never backwards, and when a rule bites
public static readonly Constraint<Order> VersionNeverGoesBack =
Constraints<Order>
.Monotonic(o => o.Version, MonotonicDirection.NonDecreasing)
.WithSeverityUntil(Severity.Warning,
new DateTimeOffset(2027, 1, 1, 0, 0, 0, TimeSpan.Zero), Severity.Error);// 5 · the same rules on a mutable, async service
public static readonly ConstraintSet<Wallet> WalletRules =
ConstraintSet
.From(("money-is-conserved",
Constraints<WalletState>.Conserves(s => s.Checking + s.Savings)))
.Map<Wallet>(w => w.State);
await AutoTest.For(WalletRules, () => new Wallet())
.MutateAsync<int>("Move", (w, n) => w.MoveAsync(n), _ => Gen.Int[1, 12])
.RunAsync();// 6 · one line: CsCheck generates, shrinks, replays
await AutoTest.For(OrderConstraints.Instance).RunAsync();// 7 · nothing more to write.
// every rule was reached.