The biggest difficulty I'm having reading other people's code is the sheer
fact that, sometimes, they take the "Short variable name" guideline
<https://github.com/golang/go/wiki/CodeReviewComments#Variable_Names> to
heart. It's true that variables should be short enough to convey it's
meaning, no more and no less, but when it does it become "too much" or "too
less"? It could be a "I know it when I see it" type of thing, but I don't
think that's the case, as people have different preferences; maybe one to
two letter variables are easier to read for some, maybe 3 - 5 for others,
maybe Hungarian notation (Looking at you Win32), etc.
The biggest issue is the fact in other languages, you mostly have the type
name specified next to the declaration, hence you can infer the meaning...
unfortunately in Go, a lot of people use ':=' over the '=' operator, even
for extremely ambiguous variable names. If I gave you the code (from
runtime/hashmap.go)
alg := t.key.alg
hash := alg.hash(key, uintptr(h.hash0))
m := uintptr(1)<<h.B - 1
b := (*bmap)(unsafe.Pointer(uintptr(h.buckets) +
(hash&m)*uintptr(t.bucketsize)))
if c := h.oldbuckets; c != nil {
oldb := (*bmap)(unsafe.Pointer(uintptr(c) +
(hash&(m>>1))*uintptr(t.bucketsize)))
if !evacuated(oldb) {
b = oldb
}
}
Okay, lessee... alg means algorithm, used to hash the key, thats not so
bad. What's t? maptype (not to be confused with mapType and MapType
btw...), which contains the meta-data needed. What's h? Why, the hash-map's
header; hash0 being the seed (why not call it that?) Phew, well that wasn't
so bad...
So, what's m? What's that? The modulus? What's B? The logarithmic base-2
used to find the number of buckets, thank goodness for it's documentation.
However, why subtract by one? Because then you can turn 1000 0000 => 0111
1111; How does the letter 'm' represent this? Dunno, maybe it stands for
modulus? I would have figured 'm' in the context of the hashmap would be
reserved for, say, the actual map.
Now what is 'm' used for? Note the (hash & m), which will retrieve the
places where the first B bits are set, hence not all of the hash is
actually used. Why? Because the first bits set can be used to obtain the
index. If the hash is 1101 0101, and m is 0111 1111, then (1101 0101) &
(0111 1111) = 0101 0101. This would give you an index less than the number
of buckets, 1000 0000. What does this remind you of? A modulus you say?
Correct, you could have easily done (hash % m) and gotten the same result
and have it more readable.
I won't go on too long with this example, but bmap pretty much only has one
concrete member, the rest are actually allocated outside of the region of
bmap, and is accessed by using ugly-looking unsafe.Pointer's.
Then there's the next variable name used, 'c', which has no description
beyond the fact that it comes after the letter 'b'. Would it have killed
the developers to add some documentation on what is going on, add some more
descriptive variable names, etc.? This isn't even the worst of the code
I've had to sift through.
Hence, clearly this code is not okay, but if the language was written, by
the developers themselves, who defined the actual guidelines, violate their
own written guidelines? The real horror to me, is not the fact that I have
to spend the next 6 weeks reading this stuff and deciphering it, but I find
myself writing like this now as I got so used to it.
To clarify I'm not arguing that one-letter variable names are inherently
bad, as clearly in loops and limited scopes it is fine, such as the index
in a loop, but I feel as it should be avoided, not encouraged like in the
code above.
[This is more of a rant than anything though]
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.