Repository navigation
Nullean.Entities 0.1.0
Nullean.Entities 0.1.0
Types say what a thing is. Nothing says what it must do.
Nullean.Entities makes business rules first-class: a rule is a named value, declared once next to the type, and that one declaration validates a value, is tested automatically on generated data, and can watch live events. This is the first release. Docs: https://entities.nullean.net/getting-started/
What you get
- Rules as named values.
Constraint<T>andConstraintSet<T>, withAlways,When/Requires,Transitions,Idempotent,Monotonic,Conserves,OrderIndependent,Unique,Referencesand deadline and liveness rules for event streams.[Constraints]gathers the rules on a type into one generated set, so a rule you add cannot be forgotten. - Tests you do not write.
AutoTest.For(rules, ...)runs one test per axis the rules declare, on nine axes: invariants, idempotency, monotonicity, conservation, absence, deadlines, liveness, order independence, and a check that the tests reached the rules at all (a test that never exercised a rule fails as vacuous). - Records, services and mutable classes. The same
AutoTestruns on immutable records and on services changed in place (Mutate/MutateAsync), awaits async operations, and never blocks on a task. - Failures that read like an incident report. The rule that broke, the operation, the state before and after, the law and what it costs, and a seed that replays the smallest case found.
- Relations declared once.
Relation.ReferenceandRelation.Uniquebuild the rule and tell the data generator which members it relates, so the two cannot drift apart. - Adopt gradually. A rule can start as a warning and become an error on a date you choose.
Packages
| Package | For |
|---|---|
Nullean.Entities |
The rules, Result<T>, state machines and the [Constraints] source generator (bundled). No dependency on a test library or on Rx. |
Nullean.Entities.Reactive |
Temporal and structural rules over IObservable<TEvent> streams |
Nullean.Entities.FileSystem |
File rules over System.IO.Abstractions |
Nullean.Entities.Extensions.DependencyInjection |
Constraint sets in Microsoft.Extensions.DependencyInjection |
Nullean.Entities.AspNetCore |
A 400 ValidationProblem keyed by member, from violations |
Nullean.Entities.Argh |
Validate the options a Nullean.Argh command receives |
Nullean.Entities.CsCheck |
The generated tests, on CsCheck. Tests only. |
Nullean.Entities.CsCheck.Reactive |
Rx scheduler terminals for the CsCheck package (opt-in) |
Nullean.Entities.CsCheck.FileSystem |
A mock file system in generated data |
Nullean.Entities.CsCheck.AutoBogus |
Bogus and AutoBogus generators that route their draws through CsCheck so seeds replay |
All target net10.0 and net11.0. The core, Reactive, FileSystem, DependencyInjection, AspNetCore and Argh packages are trim and native-AOT clean (CI publishes a native AOT smoke app on Linux, macOS and Windows); the CsCheck packages rely on reflection and are for tests only.
Start here
[Constraints]
public static partial class OrderConstraints
{
public static readonly Constraint<Order> TotalNeverNegative = Constraints<Order>.Always(o => o.Total >= 0, "An order total is never negative.");
public static readonly Constraint<Order> CancelIsRepeatable = Constraints<Order>.Idempotent(o => o.Cancel());
public static readonly Constraint<Order> VersionNeverGoesBack = Constraints<Order>.Monotonic(o => o.Version, MonotonicDirection.NonDecreasing);
}
await AutoTest.For(OrderConstraints.Instance, orders).RunAsync();Getting started · The nine axes · Services and mutable classes · Rolling out a rule
Good to know
- Versions are
0.x: the API can still change between minor versions. 0.1.0-preview.1was published without the source generator, so[Constraints]did nothing; use0.1.0-preview.2or later.- MIT licensed.