
Long Names Are Long (2016) - tosh
http://journal.stuffwithstuff.com/2016/06/16/long-names-are-long//
======
joshuamorton
This touches on one of my least favorite things when reviewing code:
"stutter".

A common example is what happens when you have an object that should just be a
function (or static in javaland):

    
    
        from io import reader
        
        reader = reader.Reader()
        reader.read(file)
    

Oof. Just

    
    
        import io
        io.read(file)
    

Similarly when you have method names that share information with the class and
arguments.

    
    
        BufferedReader bufferedReader = new BufferedReader()
    
        bufferedReader.readBuffer(buffer)
    

Now languages support stuff to reduce this, like `val`, but still! When
designing apis/interfaces, consider what they'll look like to a user and don't
force your end users to stutter.

~~~
YeGoblynQueenne

        from io import reader
        
        reader = reader.Reader()
        reader.read(file)
    

Isn't this why you can say:

    
    
      from io import reader as r
    

And then:

    
    
      reader = r.Reader()
      reader.read(file)
    
    ?

~~~
joshuamorton
Sure but you still have `read` 4 times (down from 6), while I have it only
once. And that comes at the cost of forcing your users to alias a variable
which can be a maintenance burden long term.

~~~
YeGoblynQueenne
Fair enough. Though two of the "read" are "reader" and "Reader" and you can
tell them apart easily from the capitalisation. But I don't completely
disagree with your point.

------
crazygringo
Unfortunately I don't think this is particularly complete advice, because it
totally ignores the question of scope.

Yes, variable names serve to disambiguate. But at what level -- function?
File? Component? Business process? There's no clear rule here. And are they
disambiguating merely between other variables that have already been defined,
or from the wider scope of _potential_ variables that a programmer might
likely otherwise accidentally confuse them with?

If I have 20 different functions that all deal internally with only a single
"price" variable, it may be legitimately helpful in preventing bugs to
explicitly name these "priceWithTax" and "priceWithoutTax", or
"priceLocalCurrency" and "priceForeignCurrency", or "priceList" and
"priceSold". Or even use "priceWithTax" even if I never once use or define a
"priceWithoutTax", because I _know_ from experience that people are going to
make a mistake otherwise.

In the end we're all trying to balance brevity with descriptiveness that
prevents someone from accidentally misinterpreting and therefore misusing the
variable when calling or modifying later on.

Sometimes I agree that yes variable names seem too long... but then I realize
it may well be worth the peace of mind knowing that it's reducing chances of
mistakes and bugs.

~~~
TheRealPomax
The article is explicitly about object oriented code, which pretty much tells
you exactly how scoping will work, and in which contexts you drop parts of a
name because they're contextually obvious.

If you have 20 different functions that all internally deal with `price`, then
either you're not writing OO code, or each of those functions is in its own
object type, providing a clear context on what your code is talking about.

~~~
crazygringo
> _The article is explicitly about object oriented code_

You're wrong, it's absolutely not.

It never once mentions being about objects, and the first half of examples
don't involve objects at all.

I don't know where you're getting that from.

And even if it were, it has nothing to do with my point. Different objects
could use different standards for a price variable. You claim that objects
would provice a "clear context", but if it's not through variable names, then
how? Just through comments around the variable names?

~~~
mangamadaiyan
From TFA:

"Obviously it’s an object. Everything is an object. That’s kind of what
“object-oriented” means".

So ... TFA is perhaps not explicitly, but _implicitly_ about object oriented
code?

------
zck
While I certainly think that naming is important, I don't quite agree with all
the improvements suggested here:

> // Bad:

> List<DateTime> holidayDateList;

> Map<Employee, Role> employeeRoleHashMap;

> // Better:

> List<DateTime> holidays;

> Map<Employee, Role> employeeRoles;

I'm not sure this is better. Yes, it's obvious that both are _collections_ ,
but it's not obvious what you can do with them. Is `holidays` a map of date to
information about the holiday? Is `employeeRoles` a set of all possible roles?

And once you remember that `employeeRoles` is a map, you're still a little
lost about how to look into it. Is the key the employee id? Email?

Perhaps it could be called employeeToRoleMap? That distinguishes it from
employeeIdToRoleMap, or possibleEmployeeRoles.

Maybe this is me disagreeing with a later statement by the author:

> Some people tend to cram everything they know about something into its name.
> Remember, the name is an identifier: it points you to where it’s defined.
> It’s not an exhaustive catalog of everything the reader could want to know
> about the object. The definition does that. The name just gets them there.

I don't know if I want to know _everything_ , but I think I lean towards
_more_ than the author does. A variable name I changed today was originally
called `initial-points`. It designated the set of intermediate points directly
from a source to a destination, which would later be offset randomly (example:
[https://imgur.com/a/UxkGPfX](https://imgur.com/a/UxkGPfX)).

While refactoring related code, I realized that although it was descriptive,
it was descriptive _temporally_, rather than describing the identity of the
points. I ended up changing it to `points-in-direct-line`. It still feels
subpar to me, but at least it's clearer: the points exist not because they'll
be changed later (initial-points), but as a direct line between the source and
destination.

~~~
joshuamorton
In a strongly typed language, you shouldn't encode type information in the
name, it's statically derivable. Holidays isn't a map, it's a list. The name
doesn't need to tell you that, you already know and the language will prevent
you from misusing it.

With employees, you might be right. The comments on the original article give
two suggestions:

1\. `employeesById`. This may imply a mapping type, but you aren't stuttering
(saying map twice in the decl) at least.

2\. Create an employee ID type and make the type declaration Map<EmployeeId,
Employee>. (Where your id type might just bsubclass int) This way the semantic
information is encoded into the type, and the type system prevents your from
misusing things. For example you'd need to explicitly cast from int to
employee ID.

~~~
zck
> In a strongly typed language, you shouldn't encode type information in the
> name, it's statically derivable.

This is completely true!

> The name doesn't need to tell you that, you already know and the language
> will prevent you from misusing it.

I think this is where we differ! I prefer to know what I can do with something
without having to ask a compiler or IDE. This helps, for example, when looking
at a pull request -- you don't have the code easily accessible for the
compiler or IDE.

Possibly a difference is that I prefer to use languages that are more
dynamically typed -- Clojure, Emacs Lisp, etc. And so you don't _have_
`Map<EmployeeId, Employee> employeesById`; you only have the variable name.

But I do wonder -- even in the most explicitly typed, statically typed
languages, what is the eser experience for finding this out? It seems that
unless one is looking at the declaration, there must be at least one level of
indirection to find out what the type of something is.

Say you're looking at a use of the variable `employees`. Here's the ways I can
think of that would let you know what the type is:

1\. Scan upwards until you find the declaration, if it even is on screen. Then
look back to where the use was.

2\. Move the cursor to the variable, and use the "go to definition"
functionality built into the IDE. Then look at the declaration, and use the
"go back" IDE function.

3\. Move the cursor to the variable, and the IDE has somewhere that tells you
the type. This is relatively simple, but still requires you to move to the
variable, and to look somewhere else and back.

On the other hand, with a name like `employeesById`, all you need is in that
thirteen characters.

~~~
JadeNB
> I think this is where we differ! I prefer to know what I can do with
> something without having to ask a compiler or IDE. This helps, for example,
> when looking at a pull request -- you don't have the code easily accessible
> for the compiler or IDE.

I think, in accordance with "variables won't and constants aren't", I would
propose the less pithy: "any invariant that is not enforced is broken". The
compiler doesn't check that the capabilities or roles advertised by your
variable names are actually present, so eventually they won't be. That means
that you _can 't_ just check the variable name when reviewing code, must
_must_ check the declaration (as well as possibly elsewhere) in case the
variable names lies; and, once you're checking that, what have you gained in
reviewability?

~~~
zck
Nothing can prevent all errors. Having explicit typing does not prevent
`List<Users> bankAccount`, but almost all programmers prefer variable names
that encode things not in the data types.

So I disagree that you must check that `employeesById` or similar are still a
map type if a PR uses it. If it wasn't a map type, I would have expected that
to be flagged in the PR that introduced the variable.

------
rossdavidh
Personally, working in a variety of python and javascript shops, I have seen
problematically-short variable names way more often than problematically-long
variable names, probably on the order of 10:1.

------
Pxtl
I've been burned far too many times by ambiguous names. The edict on hashmaps
in here is a particular one that has gotten me more than once, so i always
name them "ValuesByKey" style. Alike "AccountsByID".

It's a risk/reward thing. Overlong names are annoying. Brief names are
destructive. So I always err on the side of length.

~~~
atoav
This is one of the pros of using a strictly typed language: there errors like
these can only go unnoticed if the other object has the same type. And in
languages like Rust with a concept of ownership even those might be cought in
compilation..

Naming things is hard. But it is a lot easier if you can rely on it not
breaking things all the time.

~~~
Pxtl
Hashtables full of record-like objects are the usual problem. I often find
myself throwing records into a hashtable and then keying it by one of its
properties, and that means it's a simple primitive and there may be many of
the same type.

If I've a record with a half-dozen int properties that are semantically IDs, I
have to clarify which is the key for this hashtable.

------
jrobn
This is a symptom of OO languages. You don’t nearly get as much word soup in
good functional languages.

People really diss Erlang for its syntax but I find it to be extremely
readable and understandable in most cases because pattern matching is a first
class citizen in the language. Humans are excellent at recognizing patterns.

Same goes for the ML family.

~~~
robluxus
Interesting observation. Do you have some real world DP codebase examples
where one can see how they avoid word soup (without sacrificing
understandability)?

------
jchw
FWIW, and definitely somewhat off-topic, when they say code is reviewed
"twice," they don't mean necessarily literally. When someone gets
"readability" in a language, they can approve changes in that language for
readability; if neither the reviewer nor the person writing the code yet have
readability in a given language, they will need someone who does to approve it
in addition. The idea is to have someone who has pretty good knowledge of the
style and conventions used for a given language to have reviewed it.

More information is available on the net if you're curious. A cursory Duck
Duck Go leads me here: [https://www.pullrequest.com/blog/google-code-review-
readabil...](https://www.pullrequest.com/blog/google-code-review-readability-
certification/)

------
kccqzy
I personally rather like the idea of making type names long but variable names
short.

Instead of

    
    
        DockableModelessWindow window;
    

I might write

    
    
        DockableModelessWindow dmw;
    

if this is a local variable whose type is nearby. Using acronyms also help
people remember its type.

For global variables, though, it would not be appropriate.

~~~
wolfgang42
If abbreviating, why 'dmw' and not 'win'? Is the fact that it's dockable and
modeless really important enough to use two-thirds of the variable name on a
cryptic abbreviation? (And if it is, why not call it by what it _is_ rather
than how it's _shaped,_ like 'toolbar' or 'tbar'?)

~~~
clarry
I agree (at least as far as function/block local variables are concerned),
except that I'd probably just name it w. If it's not obvious from context that
w stands for window, then the function probably needs to be refactored anyway.
That said, dmw is fine if the function needs to deal with more than one type
of window.

------
YeGoblynQueenne
That's why I like Prolog:

    
    
      factorial(0,F,F). 
      factorial(N,A,F) :-  
          N > 0, 
          A1 is N*A, 
          N1 is N -1, 
          factorial(N1,A1,F).
    

Because 90% of variables in 90% of the Prolog code I've ever read __* are
named A, B, C, D, H, I, J, K, L, M, N, P, Q, R, S, T, U, V, W, X, Y or Z. Or
with an "s" (as in Xs, Ys, Zs...) to denote a list. Or a number to denote a
new version (where you'd like to put a "'" but syntax doesn't let you).

Theeere you are. No need to think hard.

:dusts hands:

(Tail-recursive factorial predicate from here:
[https://www.cpp.edu/~jrfisher/www/prolog_tutorial/2_2.html](https://www.cpp.edu/~jrfisher/www/prolog_tutorial/2_2.html))

______________

 __* Including my own code that I 've written before reading it.

------
lloeki
[https://talks.golang.org/2014/names.slide](https://talks.golang.org/2014/names.slide)

Very cool presentation by Andrew Gerrand, with the following rule of thumb:

The greater the distance between a name's declaration and its uses, the longer
the name should be.

------
smoyer
Funny that three are so many typos on a treatise about short precise names.

------
kazinator
> _We have rightfully abandoned Hungarian notation. Let it go._

Earth to FreeRTOS ...

~~~
j1elo
I had a look at FreeRTOS for a project, and liked the architecture with
support for concurrent tasks and all the tooling included in Atmel Studio... I
would not let something as superficial as the naming conventions influence my
tooling choice, but for sure was left wondering who and why in the world would
opt for such awkward and (almost objectively) ugly names for their rtos
project.

Seems like if they tried hard to join all the worst things from all worlds:
mix your ALLCAPS with lower case, add a pinch of CamelCase mingled with some
snake_case, and top it with a confusing blend of semantic + sintactic prefix
notation.

Seriously wtf were they thinking about?

EDIT: Adding the first example that I could find, which already shows all of
the mentioned "features" (scroll down for the code):
[https://www.freertos.org/Hardware-independent-RTOS-
example.h...](https://www.freertos.org/Hardware-independent-RTOS-example.html)

------
aasasd
Well, Google must've changed course, seeing as Go made keyboard farts
fashionable again. I guess that's where Go's C heritage comes in.

