7 ms·
Then when he designed Go he made the act of data modelling akin to having one hand tied behind your back, because it supports only product types and not sum typ
by frou_dh 3y ago
Then when he designed Go he made the act of data modelling akin to having one hand tied behind your back, because it supports only product types and not sum types too.
- MarkMarine 3y ago[flagged]
- ikari_pl 3y agoThey also made sure you can't easily tell what the code is doing due to the noise of edge case handling in 75% of the lines
- cratermoon 3y agoBuggy "edge case handling" is the source of many critical failures[1]. Go makes explicit where a called function can return and also provide information for any anomalous conditions encountered. The alternative of just pretending like a return means success is wrong, and other ways to determine if the result of called function is acceptable (e.g. checking errno in C) are just as verbose and introduce other failure modes. Here's a thought experiment for you: pretend the return type is something other than 'error': result, statuscode, responseContext, anything that doesn't imply failure. Would you then suggest handling that is "noise"? ETA: "there are countless other [than if err != nil] things one can do with an error value, and application of some of those other things can make your program better, eliminating much of the boilerplate that arises if every error is checked with a rote if statement."[2] 1 https://www.eecg.utoronto.ca/~yuan/papers/failure_analysis_osdi14.pdf https://www.eecg.utoronto.ca/~yuan/papers/failure_analysis_o... 2 https://go.dev/blog/errors-are-values https://go.dev/blog/errors-are-values
- golergka 3y agoAlternative is using result or either monad and have first-class support for nomadic operations in the language so you don't have to waste three lines on every function call just to propagate the error up
- TeMPOraL 3y agoThat's just a hard-core technique for sweeping noise under the rug. It helps with this and similar cross-cutting concerts, but at a huge cost elsewhere. We are unlikely to improve on this until we finally abandon the idea of working directly on a single, plaintext codebase.
- golergka 3y agoCan you please explain, how exactly is this sweeping noise under the rug? Type system still forces you to explicitly handle the error case, one way or another.
- TeMPOraL 3y agoMonadic techniques let you hide most of the noise coming from passing around the Result type, especially in code that would only pass the error state through. You still need to handle the error case explicitly somewhere, but you avoid writing error checks and early returns everywhere else. I say it's sweeping under the rug, because you still can't exactly ignore the presence of error handling when not interested in it, and the extra complexity cost of monadic mechanisms themselves still pops up elsewhere to ruin your day.
- groestl 3y agoOr just, like, exceptions, still good enough. It's not rocket science, almost anything is better than Go's approach, and only C's is worse.
- frou_dh 3y agoSpecific functions where returning a tuple of error and something else makes sense are always free to do so. Why does their existence mean that the other 95% of functions that can error need be given the wrong return type and pretend to return a tuple when they never do? (i.e. some element of the tuple will be garbage, euphemistically called a Zero Value)
- rohansingh 3y ago> Why does their existence mean that the other 95% of functions that can error need be given the wrong return type and pretend to return a tuple when they never do? They don't, do they? One really nice thing about Go is writing and calling functions that _don't_ return any error. You can be confident that they will not throw any exceptions at all.
- groestl 3y ago> writing and calling functions that _don't_ return any error You are under an illusion if you think they can't fail.
- frou_dh 3y agoI said functions that error. If it has 'error' in its return type then it's such a function, e.g. (string, error)
- ikari_pl 3y agoYou can only be confident that they won't tell you what the exception was. More likely they will panic. If you're lucky, the documentation says when.
- LispSporks22 3y ago> Go makes explicit Is kind of an understatement. If the handling code for that is duplicated as 75% of your code base, there's something wrong with the language. There's got to be some other way than all that noise.
- fasterik 3y agoExplicit error handling is a design choice, not a language defect. If you don't like it, you don't have to use the language. Many people choose to use explicit error handling even in languages that support exceptions. Knowing that every function call returns a value that is handled locally makes it a lot easier to reason about your program and debug it. Also, this 75% number sounds made up out of thin air. If your program is doing something non-trivial, it should have far more code doing work than checking errors.
- AnimalMuppet 3y agoI recall reading back in the 1970s or 80s that error checking and handling took 80% of the lines of code of production-ready software. That would be pure procedural code, not exceptions, not FP style. (And that's all I've got - one hearsay-level report from decades ago.) I have not, ever, seen any numbers for exception style or FP style. My perception is that their numbers might be lower, but I have no evidence, and I am not dogmatic about my guess.
- fasterik 3y agoI can't really imagine 80% error handling for the whole codebase unless literally all of your functions look like this: int foo(Data *data) { int error = do_some_io_request(data); if (error) log_error(error, "Request failed"); return error; } For propagating errors up the stack, the ratio is only 50%: int error = foo(data); if (error) return error; For the rest of your code, I guess it's domain specific. But most projects should have a significant amount of the codebase doing things with data in memory that can't fail.
- 3y ago
- groestl 3y ago> Buggy "edge case handling" is the source of many critical failures[1] And to fix this, we introduce 10 places per function to improperly unwind the stack, have a chance at missing an error result, and completely ignoring that fact that anything can fail anyway, even a simple addition. Instead of just writing exception safe code in the first place.
- icholy 3y agoIt's not 75% of the code-base. During the error handling proposals, the Go team analyzed a large corpus of Go, and it turns out people drastically overstate how much error handling contributes to the line count.
- jahewson 3y agoIt does make me wonder if the fact that people feel this way says something about how much cognitive effort is consumed by error handling and that it might be disproportionate.
- t-3 3y agoError handling is something you always need to think about for serious code, but often feels like unnecessary work and boilerplate for exploratory programming or simple hacks.
- cowl 3y agonot 75% of all code but 75 of all code that is doing anything with meaningful practically. the classic example of a simple copyFile func. func CopyFile(src, dst string) error { r, err := os.Open(src) if err != nil { return err } defer r.Close() w, err := os.Create(dst) if err != nil { return err } defer w.Close() if _, err := io.Copy(w, r); err != nil { return err } if err := w.Close(); err != nil { return err } }
- no_wizard 3y agocould you in theory break this into other functions or no? You could have smaller discrete functions that abstract the handling of each action a little bit and be more reusable, or is that not possible in Go
- ikari_pl 3y agolike Open, Copy...? These shorter functions need to signal their failure somehow, so calling them looks exactly like the example.
- tptacek 3y agoSystems programming is edge case handling.
- ikari_pl 3y agoAnd that's exactly why it should be expressive, self explanatory, and come at a low cognitive cost.
- nkozyra 3y agoLike generics, it took a long time but Go does have them, unfortunately using the interface keyword in yet another way.
- assbuttbuttass 3y agosum types are awful for data modeling once you put them in an array. So much wasted padding around the tag bit, and wasted space to allow storing the largest variant
- saghm 3y agoSo therefore they shouldn't exist at all? I don't understand this logic
- mhh__ 3y agoHow else would you do it?
- assbuttbuttass 3y agoA common technique is to use a "struct of arrays" approach, rather than an "array of structs" This can save a lot on padding, and greatly increase the cache efficiency
- mhh__ 3y agoUnless you have a tag column that's not the same thing
- arp242 3y agoIt's not great in some cases, but "one hand tied behind your back" really is overstating things. In most cases you probably should limit things to simple types and collections (primitives, simple collections such as structs and arrays), using more complex modellings like sum types only when there's no other good solution.
- frou_dh 3y agoIf it's considered advanced, that's only because it's been left out of many languages and so people have unfamiliarity. It's the dual of product types, the other side of the same coin.
- arp242 3y agoI said "more advanced", not "advanced". If I see that a value can have two or more types then obviously this is "more advanced" (or perhaps better, "more complex") than if it's just one type. Sometimes this makes things better. Sometimes it doesn't.
- frou_dh 3y agoProgrammers are in the business of understanding well-defined concepts like this, so we will cope. > Sometimes this makes things better. Sometimes it doesn't. Exactly, and that's why you want to have both techniques available, and the data modelling is the judicious interplay of both. If you'll excuse me I'm going to go walk AND chew gum. Or should that be OR :)
- arp242 3y agoOf course it's possible and people can "cope". A lot of things are possible and people can "cope" with a lot of stuff, but that doesn't mean it's good, isn't overly complex in some cases, or is the best solution. This is just a dismissal instead of an argument, and one that can be applied to almost anything.
- dang 3y ago"Eschew flamebait. Avoid generic tangents." - https://news.ycombinator.com/newsguidelines.html https://news.ycombinator.com/newsguidelines.html We detached this subthread from https://news.ycombinator.com/item?id=38098729 https://news.ycombinator.com/item?id=38098729.
- frou_dh 3y agoFair enough but I'd say this thread can only be considered such where it veered into "Go error handling". My data comment if cheeky was relevant to the quote.
- dang 3y agoYour comment spawned a generic flamewar-style tangent that lowered the discussion quality enough that we got email complaints about it. Btw, the site guidelines also include "Don't be snarky." - I realize that takes some of the fun out of posting a particular kind of comment, but people tend to overrate the quality of what they post when they post that way, and tend to underrate the degrading effect it has on discussions, and that's a double whammy of badness. Having a don't-be-snarky rule, and sticking to it, is a way of globally optimizing for fun—specifically the fun of interesting, curious discussion. That's more important than the sugar rush of being "cheeky".