Live data from Hacker News

Practical Go: Real-world advice for writing maintainable Go programs

dave.cheney.net

111–120 of 237 posts

Re: Practical Go: Real-world advice for writing maintainable Go programs

#111

Earlier quoted context omitted.

And this is worse advice: > Functions should do one thing only. ... In addition to be easier to comprehend, smaller functions are easier to test in isolation, and now you’ve isolated the orthogonal code into its own function, its name may be all the documentation required. Using single-caller functions as a substitute for comments makes the workings of a specific operation much harder to follow, as you have to jump a…

I believe you've misunderstood this. A function can be very long and do only one thing or very short and do many things. The function: func ManyThing(i int) int { fmt.Println(i) return i+1 } does two things, and it's two lines long. The function tcp_send_message_locked ( https://github.com/torvalds/linux/blob/master/net/ipv4/tcp.c... ) does one thing at it's 261 lines long. Shorter code is _indicative of_ orthogonali…

My critique is of single-caller functions as a documentation device, not shorter functions.

Re: Practical Go: Real-world advice for writing maintainable Go programs

#112
post #100

Earlier quoted context omitted.

And this is worse advice: > Functions should do one thing only. ... In addition to be easier to comprehend, smaller functions are easier to test in isolation, and now you’ve isolated the orthogonal code into its own function, its name may be all the documentation required. Using single-caller functions as a substitute for comments makes the workings of a specific operation much harder to follow, as you have to jump a…

Longer functions are much more prone to causing errors, and errors that are harder to find. It is honestly much better to have functions that do one thing and one thing only. Might not always be possible, but it is always the best way to code.

I don't necessarily agree with "one thing only". At least, for things that start simple and grow as needed, I split things into functions either to not have to copy and paste the same code, or for readability/structure purpose. But not out of principle and always, until I can't divide any further. I can still split things out into functions later, should I need it, but doing it "just in case" and then not even having a use for it doesn't save me time and just adds overhead.

Though it also depends on whether I'm doing something familiar or something new, if I'm doing something new I might split things up more to help me conceptualize the problem. But when I'm just making a quick CLI tool, I might put it all in main first and only split it up as needed.

Re: Practical Go: Real-world advice for writing maintainable Go programs

#113

Slightly offtopic: Does anyone know which template was used to generate this document? I'm assuming the source in markdown and I really like that the generated html has table of contents, support for footnotes and is responsive!

I can't offer a solution to what it was made with, but the italicization on this paragraph makes me almost sure it was a markdown source.

  The go tool also supports a special package declaration, ending in test, ie., package http_test. This allows your test files to live alongside your code in the same package, however when those tests are compiled they are not part of your package’s code, they live in their own package. This allows you to write your tests as if you were another package calling into your code. This is known as an _external test.

Re: Practical Go: Real-world advice for writing maintainable Go programs

#114

Earlier quoted context omitted.

This is one reason I like nested functions. They’re not available to the surrounding scope so they don’t succumb to these weaknesses, while also allowing you to organize your very long function internally by task. I use ‘em in Python all the time. It’s a bummer that more languages don’t support them, though you can get there with lambdas too, sometimes at the cost of more syntax.

Go has closure functions; great feature. One of the (few) things I like about Javascript is the ability to define a closure anywhere in the containing function, so it appears in the order of operations: function f() { setTimeout(fDing, 2000); g(); function fDing() { ... } }

Go has anonymous functions too.

The Go Programming Language book (Kernighan and Donovan) has some examples of them.

Re: Practical Go: Real-world advice for writing maintainable Go programs

#115

Earlier quoted context omitted.

Yeah, I used to go by this advice, and I found the maintainability of my code dramatically increased when I typed out full names. I don't even use "i" for loop variables anymore. If the length is a problem, invest in an editor with autocomplete. Well-known abbreviations are fine, like "iter" and "prev", but single-letter variable names notoriously impede readability for me.

I generally find if you need multi letter variable names it means your function or scope is to long, or manipulating to many things. It's a nice little red flag for me. Up to four or five single letter variables is pretty trivial to remember. Especially when three of those are i, j, and k. More than 6 or 7 rapidly becomes painful. But if you are manipulating 6 or 7 variables _in the same scope_ you are doing to much.…

I could not disagree more. When I'm skimming code, I want to immediately know what a variable means. I don't want to go cross-reference elsewhere.

Re: Practical Go: Real-world advice for writing maintainable Go programs

#116
post #59

Earlier quoted context omitted.

It's really more of a language community issue, but communities of a language are commonly referred to by the name of the language itself.

I'm sure there are many actual professionals using Go. Not just script kiddies. I happen to be learning Go coming from a C background. I find "The Go Programming Language" by Donovan and Kernighan exemplary and the decades of experience that went into the language really show.

No need for insinuations, that's not a point of contention.

If you look past the book, and directly at the STL, you'll find a common example: the "fmt" library, shortened to save three letters. Or compare the verbosity of these two examples from language docs, and the length and descriptiveness of variable names in them: https://docs.oracle.com/javase/tutorial/essential/io/cl.html to https://golang.org/pkg/bufio/#example_Scanner_emptyFinalToke...

I agree, it's a great language. These naming conventions are part of its developers and community.

Re: Practical Go: Real-world advice for writing maintainable Go programs

#117

Earlier quoted context omitted.

I took issue with this because it's a conventional wisdom, and does a fair bit of damage. Single-caller functions attract other callers over time, gain backwards-incompatible features, and result in regressions.

This is one reason I like nested functions. They’re not available to the surrounding scope so they don’t succumb to these weaknesses, while also allowing you to organize your very long function internally by task. I use ‘em in Python all the time. It’s a bummer that more languages don’t support them, though you can get there with lambdas too, sometimes at the cost of more syntax.

A bit of our “heritage” in programming destroyed by the C family of programming languages

Pascal, like Algol, had nested subroutines for decomposing longer operations without leaking the details.

Nested functions is one of the things I like about JavaScript as well.

Re: Practical Go: Real-world advice for writing maintainable Go programs

#118

Earlier quoted context omitted.

Go has closure functions; great feature. One of the (few) things I like about Javascript is the ability to define a closure anywhere in the containing function, so it appears in the order of operations: function f() { setTimeout(fDing, 2000); g(); function fDing() { ... } }

Now write a unit test for function fDing() { ... } Honestly with modern JS I am not sure this feature is that great. Looks more like a code smell these days imo. Edit: Formatting

Now write a unit test for the inline block of code within the longer function which would have become the nested function???

You write the test (where any is needed) for the outer function.

Edit: the start of the discussion was about using nested functions to decompose what otherwise would have been “unpartitioned” long functions. Such blocks of code nested within a long function would not be possible to unit test, either.

Unit tests, rather than integration tests, are usually bogus, anyway, though.

Re: Practical Go: Real-world advice for writing maintainable Go programs

#119
post #62

Earlier quoted context omitted.

Yeah, I used to go by this advice, and I found the maintainability of my code dramatically increased when I typed out full names. I don't even use "i" for loop variables anymore. If the length is a problem, invest in an editor with autocomplete. Well-known abbreviations are fine, like "iter" and "prev", but single-letter variable names notoriously impede readability for me.

I feel like I have the opposite problem. If the name is more than a few characters long, it starts to become non-instantaneous to recognize it. Things get much easier to follow with visually-instantly-recognizable symbols. So in conditions where a variable is used over a short area in the code (or where it's used _constantly_ over a wide area), I prefer short variables.

Dense code that benefits from dense variables(which describes a lot of "pure algorithms" work) I often approach by aliasing the variables to shorter ones. It's all in the same body so the context is not especially hard to lose.

Re: Practical Go: Real-world advice for writing maintainable Go programs

#120

Earlier quoted context omitted.

Yeah, I used to go by this advice, and I found the maintainability of my code dramatically increased when I typed out full names. I don't even use "i" for loop variables anymore. If the length is a problem, invest in an editor with autocomplete. Well-known abbreviations are fine, like "iter" and "prev", but single-letter variable names notoriously impede readability for me.

> I don't even use "i" for loop variables anymore. Yeah, I noticed that for myself, too. so instead of i I might use frame_index, or whatever it "actually is". Up to a certain length it seems faster to just read what is there, without an additional mental translation step. But to be honest, I just do it because I like it.

I do that off and on, mostly because with the editor I use, it's harder to highlight single letter variables.
Post reply on HN