> A Data Dictionary is usually a better place for such details.
Self-documenting code/schemas are an even better place.
...sometimes I feel like I'm the only one in the world who uses DB-level metadata (e.g. `sp_addextendedproperty` in SQL Server) to attach explanatory notes and other metadata to database objects, including columns and constraints - and it gets better because I modified my Entity Framework scaffolding templates to then include those comments in the generated C# code as XML-doc (or JS Doc comments in TypeScript) - and the entire DB schema is also kept in source-control (using SSDT).
Additionally, because CHECK constraints in SQL are declarative it means I don't need to write-up a human-readable explanation of (for example) the format restrictions based on a column in the CHECK constraint, because it's immediately visible and obvious (and yes, my scaffolding templates also include the CHECK's expression in C# code-comments too for-reference).
----
Another technique I'm a huge fan of now is using predicate-types (similar to dependent-types) by taking advantage of class-invariants: so I have my own zero-overhead (i.e. elided structs) like `NonEmptyImmutableList<T>` which immediately lets everyone know that if that's passed as a parameter then it won't ever be empty - whereas if the code used the stock `List<T>` or `IReadOnlyList<T>` types you'd have to write-up how that list should be used - which no-one should have to do.
I just lament that my daily-driver languages (namely C#) make it kinda tedious to define types like that.
I've used it for years - usually auto-populated from the model that builds the relational schema (like you had done). Same for constraints. By coincidence, I just convinced my team to start using sp_addextendedproperty.
That's the advantage of using a higher-level notation, such as UML or code-first EF, for your ORM.
Self-documenting code/schemas are an even better place.
...sometimes I feel like I'm the only one in the world who uses DB-level metadata (e.g. `sp_addextendedproperty` in SQL Server) to attach explanatory notes and other metadata to database objects, including columns and constraints - and it gets better because I modified my Entity Framework scaffolding templates to then include those comments in the generated C# code as XML-doc (or JS Doc comments in TypeScript) - and the entire DB schema is also kept in source-control (using SSDT).
Additionally, because CHECK constraints in SQL are declarative it means I don't need to write-up a human-readable explanation of (for example) the format restrictions based on a column in the CHECK constraint, because it's immediately visible and obvious (and yes, my scaffolding templates also include the CHECK's expression in C# code-comments too for-reference).
----
Another technique I'm a huge fan of now is using predicate-types (similar to dependent-types) by taking advantage of class-invariants: so I have my own zero-overhead (i.e. elided structs) like `NonEmptyImmutableList<T>` which immediately lets everyone know that if that's passed as a parameter then it won't ever be empty - whereas if the code used the stock `List<T>` or `IReadOnlyList<T>` types you'd have to write-up how that list should be used - which no-one should have to do.
I just lament that my daily-driver languages (namely C#) make it kinda tedious to define types like that.