6 ms·
Type systems, like any other tool in the toolbox, have an 80/20 rule associated with them. It is quite easy to overdo types and make working with a library ext
by recursivedoubts 1y ago
Type systems, like any other tool in the toolbox, have an 80/20 rule associated with them. It is quite easy to overdo types and make working with a library extremely burdensome for little to no to negative benefit.
I know what a UUID (or a String) is. I don't know what an AccountID, UserID, etc. is. Now I need to know what those are (and how to make them, etc. as well) to use your software.
Maybe an elaborate type system worth it, but maybe not (especially if there are good tests.)
https://grugbrain.dev/#grug-on-type-systems https://grugbrain.dev/#grug-on-type-systems
- 3836293648 1y agoTo be fair, you probably needed to know that anyway? Or else you would've just passed invalid data into functions.
- recursivedoubts 1y agoI cannot recall ever passing an invalid UUID (or long id) into a function due to statically-knowable circumstances.
- happytoexplain 1y agoThe point is that you might pass a semantically invalid user ID. Not that you might pass an invalid UUID. I generally agree that it's easy to over-do, but can be great if you have a terse, dense, clear language/framework/docs, so you can instantly learn about UserID.
- ThunderSizzle 1y agoMore specifically, if all entities have a GUID, it's not impossible to accidentally map entity A ID to entity B ID accidentally, especially when working with relationships. Moving the issue to the compiler is nicer than the query returning 0 results and the developer staring endlessly for the subtle issue.
- petesergeant 1y ago> I know what a UUID (or a String) is. I don't know what an AccountID, UserID, etc. is. Now I need to know what those are (and how to make them, etc. as well) to use your software. Yes, that’s exactly the point. If you don’t know how to acquire an AccountID you shouldn’t just be passing a random string or UUID into a function that accepts an AccountID hoping it’ll work, you should have acquired it from a source that gives out AccountIDs!
- recursivedoubts 1y agoAnd that's my point: I'm usually getting AccountIDs from strings (passed in via HTTP requests) so the whole thing becomes a pointless exercise.
- petesergeant 1y agoDo you validate them? I assume you do. Feels like a great time to cast them too
- Kranar 1y agoYou just accept raw strings without doing any kind of validation? The step that performs validation should encode that step in the form of a type.
- dgb23 1y agoI think the example is just not very useful, because it illustrates a domain separation instead of a computational one, which is almost always the wrong approach. It is however useful to return a UUID type, instead of a [16]byte, or a HTMLNode instead of a string etc. These discriminate real, computational differences. For example the method that gives you a string representation of an UUID doesn't care about the surrounding domain it is used in. Distinguishing a UUID from an AccountID, or UserID is contextual, so I rather communicate that in the aggregate. Same for Celsius and Fahrenheit. We also wouldn't use a specialized type for date times in every time zone.
- ElectricalUnion 1y ago> I know what a UUID (or a String) is. I now know I never know whenever "a UUID" is stored or represented as a GUIDv1 or a UUIDv4/UUIDv7. I know it's supposed to be "just 128 bits", but somehow, I had a bunch of issues running old Java servlets+old Java persistence+old MS SQL stack that insisted, when "converting" between java.util.UUID to MS SQL Transact-SQL uniqueidentifier, every now and then, that it would be "smart" if it flipped the endianess of said UUID/GUID to "help me". It got to a point where the endpoints had to manually "fix" the endianess and insert/select/update/delete for both the "original" and the "fixed" versions of the identifiers to get the expected results back. (My educated guess it's somewhat similar to those problems that happens when your persistence stack is "too smart" and tries to "fix timezones" of timestamps you're storing in a database for you, but does that wrong, some of the time.)
- paulddraper 1y agoUUIDs all have the same storage+representation. They are generated with different algorithms, if you find these distinctions to be semantically useful to operations, carry that distinction into the type. Seems like 98% of the time it wouldn’t matter.
- tshaddox 1y ago> I don't know what an AccountID, UserID, etc. is. Now I need to know what those are (and how to make them, etc. as well) to use your software. Presumably you need to know what an Account and a User are to use that software in the first place. I can't imagine a reasonable person easily understanding a getAccountById function which takes one argument of type UUID, but having trouble understanding a getAccountById function which takes one argument of type AccountId.
- kjksf 1y agoUserID and AccountID could just as well be integers. What he means is that by introducing a layer of indirection via a new type you hide the physical reality of the implementation (int vs. string). The physical type matters if you want to log it, save to a file etc. So now for every such type you add a burden of having to undo that indirection. At which point "is it worth it?" is a valid question. You made some (but not all) mistakes impossible but you've also introduced that indirection that hides things and needs to be undone by the programmer.
- yawaramin 1y agoWell...yeah. That's the point. We want there to be a layer of indirection to prevent mistakes. Otherwise you get things like this: https://www.columbia.edu/~ng2573/zuggybuggy_is_2scale4ios.pdf https://www.columbia.edu/~ng2573/zuggybuggy_is_2scale4ios.pd... > There is a UI for memorialising users, but I assured her that the pros simply ran a bit of code in the PHP debugger. There’s a function that takes two parameters: one the ID of the person being memorialised, the other the ID of the person doing the memorialising. I gave her a demo to show her how easy it was....And that’s when I entered Clowntown....I first realised something was wrong when I went back to farting around on Facebook and got prompted to login....So in case you haven’t guessed what I got wrong yet, I managed to get the arguments the wrong way round. Instead of me memorialising my test user, my test user memorialised me.
- paulddraper 1y agoI recommend adding a serialization method to your types, namely to text, but optionally to JSON as well.
- buerkle 1y agofoo(UUID, UUID); foo(AccountId, UserId); I'd much rather deal with the 2nd version than the first. It's self-documenting and prevents errors like calling "foo(userId, accountId)" letting the compiler test for those cases. It also helps with more complex data structures without needing to create another type. Map<UUID, List<UUID>> Map<AccountId, List<UserId>>
- deleted 1y ago[deleted]
- Mawr 1y ago> I know what a UUID (or a String) is. I don't know what an AccountID, UserID, etc. is. It's literally the opposite. A string is just a bag of bytes you know nothing about. An AccountID is probably... wait for it... an ID of an Account. If you have the need to actually know the underlying representation you are free to check the definition of the type, but you shouldn't need to know that in 99% of contexts you'll want to use an AccountID in. > Now I need to know what those are (and how to make them, etc. as well) to use your software. You need to know what all the types are no matter what. It's just easier when they're named something specific instead of "a bag of bytes". > https://grugbrain.dev/#grug-on-type-systems https://grugbrain.dev/#grug-on-type-systems Linking to that masterpiece is borderline insulting. Such a basic and easy to understand usage of the type system is precisely what the grug brain would advocate for.
- spion 1y agoThe OP is the author of grugbrain.dev
- spion 1y agoThere are a few languages where this is not too tedious (although other things tend to be a bit more tedious than needed in those) The main problem with these is how do you actually get the verification needed when data comes in from outside the system. Check with the database every time you want to turn a string/uuid into an ID type? It can get prohibitively expensive.