Live data from Hacker News

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

dave.cheney.net

91–100 of 237 posts

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

#91
post #35

> Naming the Config parameter config is redundant. We know its a Config, it says so right there. > In this case consider conf or maybe c will do if the lifetime of the variable is short enough. This seems petty. Is it really that problematic to type out a few extra characters?

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.

In short Go functions I tend to like single letter variable names. Maybe because it makes me closely consider the behavior of the program instead of trying to assume by the variable names.

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

#92
post #81
post #76

Earlier quoted context omitted.

I agree with you. I like the way packages are isolated from each other, meaning that to understand a package it is usually by definition a good start to simply read what is there. Smaller packages mean more bite-sized chunks of the program. And I think the discipline of slicing up your program this way is very, very good for the design, and often makes the tests easier to write to by significantly shrinking the surfa…

If packages are too small it can get hard to understand the code if your not familiar with the structure yet. Working from bottom to top level can work but might also be different because you are missing context for the low level packages to make sense. In general I found larger packages tend to produce more direct / pragmatic code with less indirection which is usually easier to understand, even though it also feels…

"If packages are too small it can get hard to understand the code if your not familiar with the structure yet."

I solve that with describing the context of the package in the opening prose section. I think this section is underused in every language community I've seen, even though all the automated doc systems support a top-level summary/contextualization/etc.

I think that an advantage of small packages is precisely that it is easier to understand if you're not familiar with the structure yet, by isolating how much structure you have to understand. Large packages, or languages with loose barriers, force you to eat huge swathes of the project at once to understand the code. Small packages are both bite-sized on their own, and also the packages that use the small packages often allow you to gloss over the used package while you're learning that package.

I don't end up with much indirection caused by the package boundaries. (Where there are interfaces I would usually have them anyhow for testing purposes.)

This tends for me to be one of those places where I wonder if I'm just doing something really different than most people. Another example is all the many people over the years who have tried to convince me, with varying level of politeness, that testing code should only use the external interfaces, or dire consequences like having to rewrite all the testing code if I tweak the package will happen. All my testing code uses private interfaces unless there's a really good reason not to, and maybe once in ten years have I had a serious rewrite of the test code come up. The threatened problems don't seem to happen to me. (And I am pretty sure I'd notice them if they did, although I guess I can't completely discount the possibility that I'm just too oblivious somehow.)

Certainly, if they cause you trouble, either because your style is different, or your problem domain is different, or whatever reason, don't use small packages.

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

#94
My advice would be this: If you have a specific reusable component.. Make a package to contain it.

Use init() to compile any regular expressions and store them as variables within that package, so that you don't

Split out related code in a folder, remembering that the included code is done in alphabetical order - so shared functions within the same package you should alphabetically make it the first to be included.

You can register components of a larger system by using the init() function to call a function in the base package, and within the calling package (usually main) import the "plugin" using the underscore space prefix (sql database drivers use this method)

Use the new go modules system; its great. But sometimes it doesn't include the latest packages, just modify the go.mod file and anything after the package name remove it and just put master instead.

One last thing with error handling. Everybody does if err!=nil. I tend to go the opposite way, if err==nil and nest these, if err isn't nil i drop out and deal with the error. If it is ok, it will return ok.

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

#96
post #71

About half-way through and I think this is a great article, in particular the quotes and I also agree that the first 4 sections are generally applicable. One thing I disagree with is the remark about having fewer, big packages. Though conceptually I agree that avoiding having too many public APIs that aren't widely used makes sense, in practice --at least on the types of projects I tend to work on--I find that direct…

Yes, and I think the quoted paragraph has so much more to do with coding around interfaces (behaviour) than with abstraction using non-exported package symbols.

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

#97
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.

Totally agree. If you have to scroll up to be reminded what some variable means, a longer name is good. But if its usage is a few lines away from its declaration then there's no reason to add visual noise to your code.

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

#98
post #35

> Naming the Config parameter config is redundant. We know its a Config, it says so right there. > In this case consider conf or maybe c will do if the lifetime of the variable is short enough. This seems petty. Is it really that problematic to type out a few extra characters?

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.

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

#99
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.

For me Config just isn't one of those cases, HackerNewsOnYCombinatorMessageBoard on the other hand becomes an opaque mess to eyes when it is mixed with other variables of similar length and complexity.

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

#100
post #35

> Naming the Config parameter config is redundant. We know its a Config, it says so right there. > In this case consider conf or maybe c will do if the lifetime of the variable is short enough. This seems petty. Is it really that problematic to type out a few extra characters?

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.
Post reply on HN