4 ms·
> is seeing already guaranteed properties being checked again somewhere else Because at some point those "already guaranteed properties" might "disappear", to
by paganel 2y ago
> is seeing already guaranteed properties being checked again somewhere else
Because at some point those "already guaranteed properties" might "disappear", to be more exact, the process/procedure that implements and runs them might not do its thing anymore for one reason or another.
When that happens, because statistically speaking it will happen, then all the other processes/scripts/pieces of code depending on that "original" validating process would be in a very rough place.
- TeMPOraL 2y agoYes, and that's what the approach from the article is trying to help with. If you're coding in a statically typed language, the "already guaranteed properties" are propagated by types, so they can't just "disappear" - there's no way to get from e.g. String to Username without going through a String->Username function that does the checks, so functions accepting Username can rely on it having the relevant properties. Of course, this stops being true when you start hacking around the checks, side-stepping the parsers entirely (say, type-casting String to Username without any check). There's nothing a language can do to stop you when you really want to do this[0] - but then, you're an adult; if you see restrictions and safety interlocks, and put effort to hack around them, then any problem is really on you. This gets more difficult in dynamically typed languages, as you have to rely more on naming conventions and programmers not being idiots, but even without a typechecker, it will be rather obvious when you're doing something that could break the chain of guarantees. -- [0] - Some can try; I've seen a Haskell paper about this idea that does very complex type magic to try and truly ensure that only the parsing function can actually construct the result type. I tried reproducing that in C++ once, but C++ just can't give such guarantees.
- ChrisSD 2y ago> Some can try Rust does this with standard types even. "Parse, don't validate" is the answer to the question: why does Rust have so many string types? Of course you can hack around this using `unsafe` but, as you say, in that case you have to put visible effort into deliberately subverting the type system.
- kitd 2y agoAny language that allows private constructors makes this pretty easy, no?
- dgb23 2y agoThe constructor doesn't have to be private, it just has to be a constructor. For example take this library: https://github.com/google/uuid https://github.com/google/uuid It represents UUIDs as `type UUID [16]byte`. It would be trivial to circumvent a constructor: `var uuid UUID`. Go values are zero initialized. (Aside: You might actually have a reason to do this, but often you would rather use https://pkg.go.dev/github.com/google/uuid#NullUUID https://pkg.go.dev/github.com/google/uuid#NullUUID). But it's obvious that you would use one of the constructors in the library to get an actual valid UUID.
- TeMPOraL 2y agoIn C++ it's less obvious, so while a private constructor does most of the job, it's still tricky to come up with a way of designing those types so they feel natural, are easy to construct in the right way (via appropriate parsers), impossible to construct the wrong way by accident, and fulfill all the roles people expect, and don't devolve into impenetrable mess of template metaprogramming that can only be debugged by the author of the type definition framework.
- dgb23 2y agoI understand where it comes from, but I can't ignore the feeling that this is anxiety driven development. Sure, the farther away from your control and trust circle, the more you're inclined to check assumptions that are already guaranteed. It's a valid reason to do this as you explained, but I think the tradeoff has to be considered: Generally speaking, checking assumptions that are already guaranteed is a _bug_. It violates the DRY principle[0], and will break your program, when those guarantees relax or the assumptions become tighter at one place or another, because they diverge. And again, it can be confusing for maintainers and makes it harder to reason about a program and make sensible changes. The anxiety that drives the checks will leak right into the reader who might be wary of breaking Chesterton's Fence. Now you have someone testing everything in order to figure out if there are code paths that only hit one or the other of the checking code and stuff like that. Needless to say it can also make performance worse, because you're doing more work than needed, especially if the checks require fetching data from disk or the network etc. This type of performance degradation is quite common. [0] The real/actual one, not the one where people factor out superficially repetitive code.