6 ms·
> But the expense of extra lines of co[d]e come at significant maintenance costs. All lines are not created equal. if err != nil { return err
by PuerkitoBio 11y ago
> But the expense of extra lines of co[d]e come at significant maintenance costs.
All lines are not created equal.
if err != nil {
return err
}
Those 3 lines have very, very little maintenance cost.
The obvious must also be mentioned: less lines of code usually mean building on abstractions - the lines of code are in there, somewhere, but not in your code. Better hope that abstraction is well-tested. Of course it's all a matter of balance, but I disagree with "more lines of code is inherently a bad thing", which stated another way, would mean "cram as much information as possible in a single line of code".
In the end, lines of code are a bad metric of software.
- saurik 11y agoLess than other lines, but I definitely would disagree with the doubled-up "very" on "little". In addition to simply being distracting and verbose, a core issue is that you have to make certain you always have the boilerplate and that you have to make certain it is always correct. Otherwise you just https://gotofail.com/ https://gotofail.com/ :(.
- jacques_chester 11y ago> Those 3 lines have very, very little maintenance cost. These three lines are everywhere, give me no clear indication of whether they are intentional behaviour or merely a boilerplate-by-convention, and worst of all, they obscure the actual business logic.
- PuerkitoBio 11y agoError handling does not obscure the business logic, it is very much part of the business logic.
- jacques_chester 11y agoIf your business is handling full disks and HTTP timeouts, sure, exceptions and business logic are the same.
- jerf 11y agoThe further away from a "network server" you get, the less appealing Go gets. It's a general purpose language, but it's not entirely wrong to think of it as a DSL for writing network servers that happens to be useful for other some things. Why doesn't lack of generics kill Go? Well, if you're working in Go's wheelhouse, []byte actually covers a lot of things and you're rarely that far away from it, because you're about to read or write a []byte real soon now. (I don't mean you always have one literally in hand, you probably marshaled in into a struct, just that you're often very close to either reading or writing it.) Why does it work to have this error handling in Go? Well, when writing network servers or other basic cloud infrastructure, actually a lot of the errors require different handling on a case-by-case basis. Big ol' exception blocks around the whole operation are often hiding bugs, or at the very least, suboptimal exception handling. By contrast, when you're not writing the code to do all the nitty-gritty network operations it's a level of detail you don't want or need. I think every single posted "success story" I've seen for Go has been a network server. I don't think I've ever seen one about how it really cleaned up my Android app, or how my game development was crashing and burning until I switched it to Go. I don't think this is a coincidence, nor do I expect to see one anytime soon, the recent Android support notwithstanding.
- moe 11y agoError handling does obscure the business logic when, as in Go, nearly every operation needs to be followed by a boilerplate guard clause. Other languages (e.g. Java) have solved this problem quite elegantly over a decade ago with the introduction of Checked Exceptions[1]. Since this is the pattern that every Go program ends up emulating anyway, Google could save everyone a lot of work by just baking it into the language. In the eternal words of Larry Wall: The computer should be doing the hard work. That's what it's paid to do, after all. [1] https://en.wikipedia.org/wiki/Exception_handling#Checked_exceptions https://en.wikipedia.org/wiki/Exception_handling#Checked_exc...
- fooster 11y agoSorry, but if you have every operation followed by a guard clause you are doing it wrong. For example, https://blog.golang.org/errors-are-values https://blog.golang.org/errors-are-values
- jacques_chester 11y agoThis just shows that, to avoid having do-and-check after every operation, the provider needs to invent several idioms because it's tedious to the consumer. But now the consumer needs to know multiple idioms and recognise when they are being used. And the reader of the consumer code needs to know that the normal `err != nil` idiom is not being followed. All of which requires everyone involved to do more reading of source code than a "throws" line. How is this simpler than having a single, universal concept of exception handling?
- ivank 11y ago> https://blog.golang.org/errors-are-values https://blog.golang.org/errors-are-values The "helper" function there introduces 10 lines of code (per function in which you want it), and doesn't even work if you call anything besides that one `write` in sequence.
- moe 11y agoYour link describes (and encourages) exactly the laborious emulation of Checked Exceptions that I was talking about in my above comment. It doesn't make the guard clauses disappear. It merely forces the programmer to manually aggregate them at a higher level with even more boilerplate code.
- pcwalton 11y ago> Error handling does not obscure the business logic, it is very much part of the business logic. That's why it's nice when the language provides tools to make it more likely to be correct.
- kasey_junk 11y agoI routinely find bugs in golang error handling code. In general I agree with your point but this is not the example I would use.
- bkeroack 11y agoAs opposed to the bugs you didn't find in some other language, because your program was spitting out unhandled exception errors from random places at runtime.
- masklinn 11y agoAn unhandled exception means the program stops rather than continue in an unexpected and possibly invalid state. The latter being what happens in C or Go. And it's not like these two are the only possible error handling strategies.
- fooster 11y agoThat isn't really what happens most often. What happens is that the exception is caught and thrown out, or caught and printed (especially with java if you are using eclipse_.
- eropple 11y agoWhy would I spit unhandled exception errors from a Try monad?
- fithisux 11y agoThese three lines have made my life easier.
- incepted 11y ago... and your code more fragile. You can't have your lunch and eat it too: if you want robust code, you -- the developer -- need to spend some time thinking about how you manage your errors. Go makes it all too easy to sweep those under the rug.
- cdelsolar 11y agoNo it doesn't. You need to handle every error or your program will panic and crash. You are forced to think of and handle every error by the if err != nil construct.
- Daishiman 11y agoThose are some truly bullshit lines there. Totally unnecessary, a solved problem eons ago through very manaeable, existing constructs that have a lot more semantic meaning.
- lmm 11y agoThe most common maintenance task is reading an entire region of code, which costs in direct proportion to the number of lines. Bugs are also proportional to number of lines of code independently of language, http://programmers.stackexchange.com/a/185684 http://programmers.stackexchange.com/a/185684 . So no, lines of code is a good metric. (Though I wouldn't characterize it as "cramming"; better languages save lines by not requiring programmers to specify irrelevant detail rather than by packing more information into the same space).
- ilurkedhere 11y agoSeems like there should be an abstraction for that.
- mahyarm 11y agoThe problem with verbose code, is missing the small difference in the boilerplate and creating new bugs. It's the same problem with copy/paste code. With copy/paste code, it often has small changes that you can miss easily. You have to read every line of code to not miss the small variations. If the person bothered to generalize the copy paste code a bit, you can cover all cases in one spot, and be less likely to miss problems.