3 ms·
> The belief that if your code type-checks correctly, it will do exactly what you intended. With a little care and a sufficiently strong type system it’s surpr
by aranchelk 6y ago
> The belief that if your code type-checks correctly, it will do exactly what you intended.
With a little care and a sufficiently strong type system it’s surprising how often this is actually true.
- pmontra 6y agoThis is the last bug I had to fix. Scenario: a credit transfer marketplace. When we auction an invoice, we snapshot the data about all the involved parties and show those data in all the screens about the invoice. However some of those screens didn't show the stored data, they showed the current ones, which is useless and very wrong. I know which tests can catch that bug but I wonder what type system could catch it at compile time. To make it worthwhile it must be easier than writing the test. We can stop at the JSON generation. No need to look into the React frontend.
- KMag 6y agoDepending on how your code is structured, phantom types might work for your use case. They're useful for tracking metadata about the values being passed around, even though the methods and fields don't differ between your use cases.
- pmontra 6y agoI googled phantom types Haskell: https://wiki.haskell.org/Phantom_type https://wiki.haskell.org/Phantom_type Python: https://phantom-types.readthedocs.io/en/stable/ https://phantom-types.readthedocs.io/en/stable/ Elm: https://dmalashock.com/elm-phantom-types/ https://dmalashock.com/elm-phantom-types/ Purescript: https://qiita.com/kimagure/items/b576b5bfe370180599f8 https://qiita.com/kimagure/items/b576b5bfe370180599f8 I'll give them a read. Thanks
- aranchelk 6y agoThat sounds like a pretty frustrating bug to try to find and fix. No type-level feature that I'm aware of could prevent this issue directly. What you're describing is pretty high-level business logic. While I've seen some pretty impressive demos with dependent types, nothing that I know of could handle this. I don't know much at all about the structure of your application, and it's hard to speculate, but what strikes me is your live and snapshotted data have the same shape/type and seem to be interchangeable for the compiler/interpreter, but are very different to you and your customers. The engineer creating that screen may have had the forethought at the outset to say "this should never deal with live data, only snapshots", so that warning probably gets put in a comment, but there's very little to stop someone from later passing in the live data that you definitely don't want. There's a feature in Haskell (and similar languages e.g. PureScript) called newtype declarations. They're a lightweight way you can tag and optionally limit access to your data. You essentially tell the compiler "this is a new and distinct type that can wrap the original one". The original and newtype are not interchangeable, and an attempt to do so won't compile. Having that feature I'm in the habit whenever I recognize overloaded meanings encoded with the same type (e.g. live/snapshot) of wrapping one of them in a newtype, and before I even implement application logic, I write out the signatures and specify which type I actually want. They add a bit of tediousness, but they have saved me many times, and I've never regretted using them.
- pmontra 6y agoThanks, maybe we can build something along those lines even if we're using a totally different language (Elixir backend, JSON to a React frontend). That is an administrator console. Sometimes we do have the foresight to understand what our users actually want but in a large system inevitably happen things like "it was obvious to us" or "after months of use we realized that it's better to do this way", etc.
- samhh 6y agoYou can do the same in TypeScript with newtype-ts. I'd recommend it for the same reasons you'd use them in Haskell et al.