5 ms·
> Oh we never considered the intersection of these 3 different business use cases Take a look at the history of any repository near you, for a project that use
by Peaker 13y ago
> Oh we never considered the intersection of these 3 different business use cases
Take a look at the history of any repository near you, for a project that uses C, Python or Java.
Review bug fix commits. See how many of them relate to "business use cases" and how many relate to implementation bugs. I believe you'll find the latter is far more common.
Even in the "business use cases", enforced invariants will be a tramendous help. In the infinite possibilities of all the use cases, none will be able to break any invariant forced by the type system.
When you set out to prove a property of your program, you will end up finding bugs, almost regardless of what properties you are trying to prove.
Writing unit tests is also useful. But if I can have 10 lines in my Red Black Tree that mean I don't have to write any test whatsoever for the tree's invariants -- I saved myself from a whole lot of work writing and later maintaining tests with every change.
Generally, to get similar confidence levels from unit tests as you get from types, you'll need to write many more tests. If I had to choose whether to trust a well-typed system written in Agda (which is similar to Haskell but has an even more powerful type system) with only the most trivial testing done, or trust a highly tested system written in dynamic or a much weaker type system, I'd definitely trust Agda more.
Or if I were to trust my 10 lines of type code or hundreds of lines of tests for the invariants of the tree, of course the 10 lines of code are far more reliable and easier to maintain.
- jbooth 13y agoHonestly, in my case, for my day job, it's way, way more "business use case" or more frequently "misunderstanding between 2 services" than it is an implementation error. We catch 90% of implementation problems with unit testing and/or just plain sanity checking it before release. Maybe Haskell could help us by making unit testing easier/unnecessary but of course there's no switching at this point. We're probably a bit of an edge case being a very service oriented architecture. (1,000 servers, 6-7 major classes of server, handling 10B (yes B) requests a day). Most of our bugs consist of a flawed assumption that crosses 3-4 service boundaries on it's way off the rails. I'll admit I'm ignorant of Haskell but I just don't see a type system fixing that for us.
- Peaker 13y agoDid you actually look at commits to reach this conclusion? Also, do you commit only/amend after doing extensive testing? Or do you also commit the results of debug sessions as separate commits? People have various biases that make them tend to remember some things and forget others. It is easy to have 100 boring implementation bugs, 1 interesting bug, and then end up remembering that you have more interesting bugs. Also, can you give me a couple of examples of "flawed assumptions" across services?
- jbooth 13y agoWell, for example, yesterday I was doing some UI work on a project I'm totally unfamiliar with. My bugs were caused by bad SQL, a null pointer exception, and some JS silliness. Most of my time was sucked up in figuring out a requirement. The NPE took about 10 minutes out of my day, and the fix for it never made it into a commit message because it was, write some code, run it, oh shit forgot to initialize that, fixed. Flawed assumptions across services tend to have to do with rate limiting, configuration mismatches, what happens when one class of service falls behind and queues fill up, stuff like that.
- Peaker 13y agoWhat kind of bad SQL? Most forms of bad SQL can be ruled out by a well typed DSL. JS silliness is also a type safety issue. You can use Fay, Elm, GHCJs or Roy to generate Javascript from a type-safe language. Some NPE's take just 10 minutes (not negligible) but there are also some that are expensive. Figuring out the reason is sometimes hard, when the code and its assumptions are badly documented. Fixing NPE's is sometimes hard because of silly reasons such as touching third party or "frozen" code. Also, NPE's can become extremely difficult when the code is bad in the first place. Things like rate limiting and queue lengths can be encoded in types. You can use type tagging on connection sources/destinations to make sure you only hook up things that match rates/etc.
- jbooth 13y agoMan, just when I thought we might agree on something. A DSL? SQL IS a freakin DSL. Why would I put another layer of abstraction between me and it? Just more places for things to go wrong. http://en.wikipedia.org/wiki/Inner-platform_effect http://en.wikipedia.org/wiki/Inner-platform_effect Anyways that particular problem yesterday wasn't a compilation problem, it was due to my own misunderstanding of some pre-existing data. You're proposing a more-complicated way of doing things with the idea that eventually we'll get to the promised land and things get simple again. I've just never seen it happen. Seen the opposite plenty of times.