Applying “make invalid states unrepresentable”
121–130 of 193 posts
Re: Applying “make invalid states unrepresentable”
#122While this is great if you know exactly what you want to achieve, it does “lock you in” those constraints on a more fundamental level. More times than I can count I’ve seen business requirements change to require those “unrepresentable” states, and since you’ve now designed you whole data model around it you need to add awful hacks to make it work. The timeline example is actually very telling. A lot of times you’d a…
You could always split your types into frontend and backend types where the backend ones are more open and the frontend ones are more restricted. I don't necessarily mean FE/BE as on the web. A lot of code is only interested in shuffling around data anyway, the shape is fairly uninteresting.
Re: Applying “make invalid states unrepresentable”
#123In general I agree that it's nice to make invalid states unrepresentable, but I'm not sure if I agree that this counts as a fundamental "invalid state". There is nothing about contracts which require that you can only have one active at the same time, or that that current one must be open ended. From a practical point of view it might be advantageous if you maintain only a single contract with a customer at all times…
> Multiple times I've designed systems where I've reduced the representable states to the minimum, and when some requirements change I realize I have to re-design the full system. Yes, if requirements change, you change the design and code to support the new requirements. Compromising the consistency and maintainability of the current design to accommodate a hypothetical future requirement change is a bad trade-off I…
Re: Applying “make invalid states unrepresentable”
#124Earlier quoted context omitted.
> Multiple times I've designed systems where I've reduced the representable states to the minimum, and when some requirements change I realize I have to re-design the full system. Yes, if requirements change, you change the design and code to support the new requirements. Compromising the consistency and maintainability of the current design to accommodate a hypothetical future requirement change is a bad trade-off I…
> since you can't predict the future That's one of those statements that makes sense, but is often not true. Very rarely does a client comes to me with a feature request that does require a pretty significant design change, but most of the time they're changes that were foreseen. Using this current article as an example, I love the way that they're storing the intervals to guarantee that they can't overlap. That's aw…
The article addresses that concept:
> It is sometimes still useful to represent the periods as a sequence of start and end dates. It is trivial to project the set of dates in to this form. As long as the canonical representation is the set, the constraints will still hold.
Re: Applying “make invalid states unrepresentable”
#125Earlier quoted context omitted.
Sum types are one of the main things I miss when working in Python. Is anyone aware of any good ways of adding sum types to Python?
I'm not sure you would consider this a good way, but one can implement (unchecked) sum and product types in any language with lexical closures via Scott encoding[1]: # data Pair a b = Pair a b def pair(x, y): return lambda f: f(x, y) # data Either a b = Left a | Right b def left(x): return lambda l, r: l(x) def right(y): return lambda l, r: r(y) v0 = pair(2, 3) v1 = left(7) v2 = right(9) # case v0 of { Pair x y -> x…
I'll need to read more about it, thanks for the pointer!
Re: Applying “make invalid states unrepresentable”
#126So Google's protocol buffers have this feature called "required" fields, which enforce schema in the type system. You should never use it. Never. It's one of those things that sound good until you're a few years into the project. Similar to how you should never be using meaningful IDs as primary keys for objects, always use meaningless fingerprint-like integers. Or how all integers should be signed unless you're dead…
Making invalid states unrepresentable is basically the process of taking human-checked invariants and turning them into type-checked invariants. This reduces the likelihood of bugs and guides humans to use the system correctly.
Re: Applying “make invalid states unrepresentable”
#127While this is great if you know exactly what you want to achieve, it does “lock you in” those constraints on a more fundamental level. More times than I can count I’ve seen business requirements change to require those “unrepresentable” states, and since you’ve now designed you whole data model around it you need to add awful hacks to make it work. The timeline example is actually very telling. A lot of times you’d a…
Re: Applying “make invalid states unrepresentable”
#128Not certain I get the needless attack on OOP in this text. The error could just as well have happened in any alternative to OO. What is needed is the realization that there is that there is a schedule that needs to have full control over the times to not create coordination issues. That is a realization that is utterly independent of the OOP-ness of the eventual solution.
Re: Applying “make invalid states unrepresentable”
#129Earlier quoted context omitted.
The YAGNI (you aint gonna need it) principle overrides the DRY principle imo.
This is partly why I've found it helpful to wait until there are at least 3 identical (not nearly identical) implementations of something before trying to make a more generic/abstracted version of it.
DRY is too often treated as purely (or principally) syntactic, when that's actually much less useful.
Re: Applying “make invalid states unrepresentable”
#130Earlier quoted context omitted.
I agree that this is an issue, but I think the answer is simply using a very flexible basic data representation (which admits invalid state) and then using predicates to refine it. e.g. starting with a list of (start,end) intervals and then adding predicates for valid intervals (start If any of the requirements change, it's easy to either add more predicates or relax/even outright remove them.
If you play your cards right, you can even get your type system to alert you to every place in your code that needs to change when you change the constraints. I don't deny there's a certain art to that, and I can't explain it all myself. But I don't even necessarily mean amazing clever type tricks like you might see in Haskell or something, I mean that something as simple as "I've changed the definition of what a 'Cu…