Live data from Hacker News

Go Naming Conventions: A Practical Guide

alexedwards.net

41–50 of 77 posts

Re: Go Naming Conventions: A Practical Guide

#41
post #36
post #34

Earlier quoted context omitted.

And then you introduce extra two levels of nested loops and suddenly "i", "j", and "k" don't make any sense on their own, but "ProductIndex", "BatchIndex" and "SeriesIndex" do. ijk for indices in loops are actually clearer than random names in nested loops precisely because it is a *very common convention* and because they occur in a defined order. So you always know that "j" is the second nesting level, for instance…

I partly agree, and partly don't. When ijk really is unambiguous and the order is common (say you're implementing a well-known algorithm) I totally agree, the convention aids understanding. But nesting order often doesn't control critical semantics. Personally, it has much more often implied a heuristic about the lengths or types (map, array, linked list) of the collections (i.e. mild tuning for performance but not c…

I think I know what you mean. Let's assume a nesting structure like this:

Company -> Employee -> Device

That is, a company has a number of employees that have a number of devices, and you may want to traverse all cars. If you are not interested in where in the list/array/slice a given employee is, or a given device is, the index is essentually a throwaway variable. You just need it to address an entity. You're really interested in the Person structure -- not its position in a slice. So you'd assign it to a locally scoped variable (pointer or otherwise).

In Go you'd probably say something like:

for _, company := range companies { for _, employee := range company.Employees { for _, device := range employee.Devices // ..do stuff } }

ignoring the indices completely and going for the thing you want (the entity, not its index).

Of course, there are places where you do care about the indices (since you might want to do arithmetic on them). For instance if you are doing image processing or work on dense tensors. Then using the convention borrowed from math tends to be not only convenient, but perhaps even expected.

Re: Go Naming Conventions: A Practical Guide

#42
post #27

Earlier quoted context omitted.

I think this may be related to how people read code. You have people who scan shapes, and then you have people who read code almost like prose. I scan shapes. For me, working with people who read code is painful because their code tends to to have less clear "shapes" (more noise) and reads like more like a verbal description. For instance, one thing I've noticed is the preference for "else if" rather than switch stru…

> I think this may be related to how people read code. You have people who scan shapes, and then you have people who read code almost like prose. I think this is an astute observation. I think there is another category of "reading" that happens, is what you're reading for "interaction" or "isolation". Sure c.method is a scalable shape but if your system deals with Cats, Camels, Cars, and Crabs that same c.method when…

dealing with an abstract api call divorced from the underlying representation

I don't understand what you mean. Could you give me an example?

I would be curious if you frequently use a debugger?

I practically never use a debugger.

Re: Go Naming Conventions: A Practical Guide

#43
People have been arguing this stuff since the dawn of (computer) time. I don't get it. I've been at it so long now, IDGAF what or how you name something. Short names in loops? Long? I don't care. I really don't. Just be consistent in what you decide and I can read it.

All this arguing... FFS, go DO something with your time!

EDIT: Oh, yeah, as for the article itself, it's a good article. But again, just be consistent in what you choose.

Re: Go Naming Conventions: A Practical Guide

#44

> we use the identifier p to represent a value in the people slice — the range block is so small and tight that using a single letter name is clear enough. No, it's not. When you see `p.Age`, you have to go back and find the body of the loop, see what it operates on and decipher what p stands for. When you see `person.Age`, you understand it. I've never understood what is gained by using `p` instead of spelling it ou…

>you have to go back and find the body of the loop

If the loop is long enough that you don't naturally remember how it was introduced, that's the problem. In the given example, the use of `p.Age` is literally on the next line of code after ` for _, p := range people`.

> I've never understood what is gained by using `p` instead of spelling it out as `person`.

Wisdom I received from, IIRC, the Perl documentation decades ago: tightly-scoped names should be shorter and less attention-grabbing than more broadly-scoped ones, because you should really notice when you're using a global, and you don't want to suffer attention fatigue. (I'm sure the exact wording was quite different.)

Also because it's better for information density. As I recall, Larry Wall also had the idea that more commonly used language keywords should be shorter than rare ones. Good code uses the locals much more often than globals, so you shouldn't need to expend the same amount of effort on them. (The limiting case of this is functional programming idioms where you can eliminate the variable name completely, in cases like (Python examples) `lambda x: int(x)` -> `int`, or `(foo(x) for x in xs)` -> `map(foo, xs)`.

Re: Go Naming Conventions: A Practical Guide

#45
post #27

Earlier quoted context omitted.

I think this may be related to how people read code. You have people who scan shapes, and then you have people who read code almost like prose. I scan shapes. For me, working with people who read code is painful because their code tends to to have less clear "shapes" (more noise) and reads like more like a verbal description. For instance, one thing I've noticed is the preference for "else if" rather than switch stru…

> I think this may be related to how people read code. You have people who scan shapes, and then you have people who read code almost like prose. I think this is an astute observation. I think there is another category of "reading" that happens, is what you're reading for "interaction" or "isolation". Sure c.method is a scalable shape but if your system deals with Cats, Camels, Cars, and Crabs that same c.method when…

The shape argument works well in small packages but it starts to fail once you have multiple domain models starting with the same letter

Re: Go Naming Conventions: A Practical Guide

#46
post #35
post #32

Earlier quoted context omitted.

> That would make “ProductIndex” superior to “i”, which doesn't add any clarity. Adds a ton of clarity, especially if you have a nested loop.

and god help you if those loops are pairing People and Products. though now that I write that out... it would be really nice if you could optionally type iteration vars so they couldn't be used on other collections / as plain integers. I haven't seen any languages that do that though, aside from it being difficult to do by accident in proof-oriented languages.

You usually don't need an index that can't be used elsewhere. If you don't then you can abstract it away entirely and use an iterator or foreach features.

Re: Go Naming Conventions: A Practical Guide

#47
post #34
post #22

Earlier quoted context omitted.

Something like "AnIteratorObjectWithPersonPointer" would be a long word, "person" is absolutely not. If a 6 letter identifier causes you that much trouble with code being too verbose, then it's likely a screen resolution/density/font issue, not a naming issue. > That would make “ProductIndex” superior to “i”, which doesn't add any clarity. And then you introduce extra two levels of nested loops and suddenly "i", "j",…

And then you introduce extra two levels of nested loops and suddenly "i", "j", and "k" don't make any sense on their own, but "ProductIndex", "BatchIndex" and "SeriesIndex" do. ijk for indices in loops are actually clearer than random names in nested loops precisely because it is a *very common convention* and because they occur in a defined order. So you always know that "j" is the second nesting level, for instance…

> ijk for indices in loops are actually clearer than random names in nested loops precisely because it is a very common convention and because they occur in a defined order. So you always know that "j" is the second nesting level, for instance. Which relates to the visual layout of the code.

In problem domains that emphasize multidimensional arrays, yes.

More often nowadays I would see `i` and think "an element of some sequence whose name starts with i". (I tend to use `k` and `v` to iterate keys and values of dictionaries, but spell `item` in full. I couldn't tell you why.)

Re: Go Naming Conventions: A Practical Guide

#49
post #46
post #35

Earlier quoted context omitted.

and god help you if those loops are pairing People and Products. though now that I write that out... it would be really nice if you could optionally type iteration vars so they couldn't be used on other collections / as plain integers. I haven't seen any languages that do that though, aside from it being difficult to do by accident in proof-oriented languages.

You usually don't need an index that can't be used elsewhere. If you don't then you can abstract it away entirely and use an iterator or foreach features.

Depends on the language. Doing that is a huge pain in Go (until fairly recently, and it's still quite abnormal or closure-heavy), so the vast majority of code there does manual index-pairing instead of e.g. a zip iterator when going through two paired arrays.

Re: Go Naming Conventions: A Practical Guide

#50
post #44

> we use the identifier p to represent a value in the people slice — the range block is so small and tight that using a single letter name is clear enough. No, it's not. When you see `p.Age`, you have to go back and find the body of the loop, see what it operates on and decipher what p stands for. When you see `person.Age`, you understand it. I've never understood what is gained by using `p` instead of spelling it ou…

>you have to go back and find the body of the loop If the loop is long enough that you don't naturally remember how it was introduced, that's the problem. In the given example, the use of `p.Age` is literally on the next line of code after ` for _, p := range people`. > I've never understood what is gained by using `p` instead of spelling it out as `person`. Wisdom I received from, IIRC, the Perl documentation decade…

> remember how it was introduced

The problem is that many times I have not read the definition to remember. Debugger puts me into a context where I have to figure out what `p` stands for. I go up the call stack and now there's `s` to be deciphered. Worse is the reuse of `p` for person, product, part, etc. in different contexts.

Debugging is not the only problem. Code is read rarely linearly. Many times I browse different uses of a function, or see how a data structure is modified in different contexts. Looking up single letter variables is just a waste of time.

Post reply on HN