The parts of your program that don’t have interesting names are the least interesting parts of your program.
It’s best to make your program as boring as possible, that way it’s more likely to be correct.
Can you see how that does not contradict what I wrote?
Looks like it just follows on: the parts of your program that don’t have interesting names are the least interesting parts of your program, so make your program as boring as possible…
Technically correct statements that carry misleading implications are not a very productive contribution to the discussion.
What is the misleading implication?
That the parts of your program that don’t have interesting names are irrelevant to your program’s quality.
(I mean you evidently seemed to think you’d mislead me, given your condescending first reply)
Being “least interesting” does not imply irrelevant to quality. I don’t see how one implies the other.
My first reply was a genuine question. I’m sorry you sensed condescension.
Okay so this is a bit of a rant but hear me out.
I’ve been writing primarily Clojure for several years now. In the Clojure universe there are some de-facto conventions for the significance of very brief variable names. For instance m denotes a map, and col or seq a list type or other sequence source. This works out pretty well for all the reasons that John outlines here - my programs in Clojure are written against an interface which is conventionally named by a truncated name, not a concrete type like clojure.lang.AFunction or java.util.Map. The single letter variable names wind up being binding for existential types… that is m is the sign by which I reference <T instanceof Associative, Iterable>.
<T instanceof Associative, Iterable>
At my day job, I work on an almost all Python team and have now repeatedly gotten into code review scuffles with my coworkers over my choice of variable names. Because I approach programming from this interface oriented perspective, the most meaningful names are short ones much in the same sense that John is after here which convey only the interfaces or other features which I need, rather than the longer names preferred by my team which seek to convey the entire context of the original use of the code I write.
The starkest contrast is, I think, in the use of classes and named class fields as opposed to functions. Functions are composable, single purpose things which you can reason about in isolation because all the relevant context is in the call stack and application. Class members especially in a context without strong static types are forced to use naming to fully distinguish the context and meaning of the value(s) they contain, which leads to long and task specific names in order to convey all the relevant context.
So yes I absolutely agree that long variable names are primarily used as a crutch in lieu of types, or due to high cyclomaitc complexity and consequent low reusability.
“code smell”, at this point is maybe an article smell. a better courtyard considered article about variable naming: https://blogs.janestreet.com/whats-in-a-name/
I wonder if we overloaded their blog server. It no longer responds :(
I found this a hard read.
At first glance I thought the author was presenting a case for using descriptive variable names, but as you read on, you see that the article is really about constraining type signatures.
I’m all for types, and for good variable names, but I think I missed the relationship between those two aspects in this article.
I don’t think the author makes the case that it is always a code smell. I think he has made the case that in a typed, functional language, it’s a code smell.
I don’t think the logic here is very sound.
Monomorphic code is much more likely to be incorrect than polymorphic code, because for every type signature, there are many more possible implementations.
If your code is designed to have exactly one specific use case (“monomorphic”) then it’s far less likely to have flaws for its designed use compared to more abstract code which has to satisfy a set of perhaps unknown use cases (“polymorphic”). Code with one use case can be thoroughly tested for that use case. Polymorphic code with multiple potential uses is inherently harder to get right.
Fortunately not much code needs to be polymorphic/generic in general. The vast majority of code has a pretty specific purpose it was designed for and the maintainability of that code benefits greatly from having meaningful identifiers. Saying that all variables should be generically named because just a few might have to be named that way flies in the face of logic.
[Comment removed by author]
The argument could be phrased much better, though. There is nothing wrong with monomorphic code. But, in languages whose expressive power is primarily derived from parametric polymorphism (like Haskell), the easiest way to constrain the behavior of a function happens to be using free theorems. A function whose type is Int -> Int probably has an interesting specification, but this specification isn’t captured by the type.
Int -> Int