5 ms·
An overlapping technique (covering some but not all of the circumstances you'd use assert) is to take a parse-dont-validate approach, and essentially encode the
by foo42 1mo ago
An overlapping technique (covering some but not all of the circumstances you'd use assert) is to take a parse-dont-validate approach, and essentially encode the fact that an assertion has been applied to a value in its type.
How ergonomic this is will vary by language, but the general idea would be to apply the assertion logic in some sort of constructor, then prevent any operations which would break the invariant going forward. The simplest way to protect this being by making the value immutable where possible.
Users of the value who care about the invariant being true can then specify in their types that they want a non-empty-collection or a foo-id or whatever it may be, rather than asking for the wider type, then asserting.
- sshine 1mo agoIt is so nice to come here and want to say something, and someone already said it. For those who haven't read "Parse, Don't Validate": https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-validate/ https://lexi-lambda.github.io/blog/2019/11/05/parse-don-t-va... I'm not sure exactly what languages people think of when they consider asserting, but I presume it's Java, C# or C/C++. In Java asserts are disabled by default, so they're thought of as a debug/development utility. In another thinkpiece, "It takes two to Contract", it is demonstrated how types and assertions work together in TigerBeetle: https://tigerbeetle.com/blog/2023-12-27-it-takes-two-to-contract/ https://tigerbeetle.com/blog/2023-12-27-it-takes-two-to-cont... I think people might be worried of asserting in production because "what if you hit an edge case in production that you haven't accounted for, and the system crashes?" And I either think "You just don't test enough", or "Parse, Don't Validate (rather than assert), report a problem and continue." > Users of the value who care about the invariant being true can then specify in their types that they want Now that C# has value types and Java has record classes, this kind of data modelling has become available in mainstream systems languages. I'm not a C++ shark, but I think the closest equivalent is C++20 aggregate structs.
- Eldt 1mo agoSome of the newer Java features are really nice for this: sealed interfaces, records, sealed interfaces, and record pattern matching
- sshine 1mo agoDon't forget sealed interfaces! I would say the killer features are records and pattern matching. Sealed interfaces/classes seem to mostly compensate for hypermobility caused by inheritance (that you can modify a superclass'es behavior and break abstraction boundaries). Stop relying on inheritance, and you don't really need sealed interfaces. Using records and thus lowering mutable state makes the problem of breaking abstraction boundaries lesser as well. This is a hot take paid for by the functional programming lobby.