Good advice. If this sort of thing is appealing to you, then read Code Complete by Steve McConnell. It's basically an entire book full of very solid advice of this sort.
when it's coding as fast as humanly possible, the last thing I want to do is slow down to think of good var names. I'll often just name something "foo" if I can't think of a good name and come back and rename it later. Sometimes it's a little better than foo but still not perfect but I'll leave that and move on to something else. I really don't like the idea that code must be perfect. Code is never perfect.
The typical response of a developer inheriting legacy code from a no-longer-employed-there developer is "this is garbage, I need to rewrite it". So in that sense not only is 'foo' efficient for the original commenter, it is _also_ efficient for his/her replacement since it will present a very clear business case for a rewrite.
This is another example of how everything depends on the user.
From this comment I can only assume that you code by/for yourself or with very few other people, with which you surely share a lot of time and space which makes communication in that kind of shorthand possible.
And now, I want to highlight how difficult was for me to be an understanding and constructive member of society right now, and try to explain why you may be right in some cases, instead of why you're wrong in some other possibly larger number of cases, while foaming at the mouth with an eye twitching, which is what my first internet instinct was.
Even if you're working on a project by yourself this is still terrible practice! I know when I've done this and had to come back to my code weeks later, I've absolutely loathed my past self for writing opaque code.
You shouldn't be "coding as fast as humanly possible", that's how you end up with bad, brittle code full of technical debt that will be a nightmare to maintain.
Nothing's ever perfect. But code can anywhere in a spectrum from good to bad, and we should always strive to reach the good side.
Exactly. Good variable names are one of the best "bang for your buck" optimizations available. There might be other things you can do to make your code better, but few so easy and impactful.
Well, grasshopper, I guess you can code like a kung fu novice, trying to split a stone; repeatedly and thoughtlessly bashing your hands on it, making a bloody mess. Or like a master; contemplating the best way a while and then splitting the stone whith one precise, decisive motion.
Oh gosh. I really hope I will never have to work with you or ever use a product you have worked on. This is just terrible software engineering practice. You are doubling the amount of work you have to do and are creating a breeding ground for bugs. Remember this age-old wisdom "measure twice, cut once"? You are doing the exact opposite.
Great news for you, you are the master of your own destiny and never have to (:
The age-old wisdom holds of course for so many cases, but writing code isn't always software engineering. Wouldn't you grant that it would be a mistake to instil the value that all code written must be carefully crafted? There'd be a ton of missed opportunities for creativity if the act of coding was so sacred.
If you're doing fast prototyping or hacking for fun then mindless variable names make sense, but working on a production codebase that is or will likely be shared by others is a different situation.
There no argument for absolute quality in code, only value relative to its use case and context. Outside of correctness of behaviour and acceptable performance, the human-readability of code probably carries the most value in most situations.
Sure you can get by without it, but code that is readable will ultimately be more valued/reviewed/supported/improved.
I remember working with one developer who would get in at 10:30 AM, think about ONE variable name in ONE method until lunch, take a 2 hour lunch break, and THEN maybe code one perfect method. Sorry not sorry there is a happy medium here. My code is not unreadable. I like to name something "curIndex" and move on with my life.
Most of this, even if it's not my preference, I would never bother arguing with. But I have a question about a practice that is tremendously widespread.
I have real trouble with single-letter variable names like "c", for any function more than, say, 2-3 lines. I scan the code and it increases my mental load because I have to remind myself what it means.
Obviously a lot of people don't have problems with this, but I do. Anybody else?
Maybe it's because I jump around a lot from function to function?
I completely agree and I was a little surprised this blog post suggested that a simple 'c' was good enough. It's not good enough. While I understand the scope between two functions is different, if the variables can be unique then I say make them unique! It makes scanning, grepping, etc all so much easier.
Unless it's a very obvious index for a for loop I am against single letter variable names. Hell even if it's a for loop, if the code is so long within the loop that I have to scroll then I think the variable names need to be more obvious to keep the context with it as you scroll away from the declaration of the for loop.
> Or you could use a decent editor, that keeps track of variable scopes.
Are you suggesting doing a find / grep inside the context of a current scope? Or just color codes / indents / marks in some way the scope? That works to a degree if an editor can do that though that still doesn't ultimately help the fact that it's a single file that you may need to search around for something. Plus not every environment will have your favorite editor setup how you like it.
> Are you suggesting doing a find / grep inside the context of a current scope? Or just color codes / indents / marks in some way the scope? That works to a degree if an editor can do that though that still doesn't ultimately help the fact that it's a single file that you may need to search around for something.
At least IntelliJ will highlight all uses of the currently selected variable/method/whatever, and will quickly allow you to jump to any of them.
If I'm searching for something by name then it's almost always because it's in use somewhere, and a ctrl+click will take me there instantly, without getting bogged down in false positives.
> Plus not every environment will have your favorite editor setup how you like it.
Sure, but how often do you actually have to work with your regular codebase in such an environment? Sure, such a rule has its uses, but in 97% of cases it's just a symptom of a poor editor setup.
I think it works here because you're in a context where there's just one collection. So you don't really have to remember what c means, you can see c.size() and think "this is the size of the collection", because in this context there's only one thing you could be taking the size of.
If there were more than one collection, or we weren't using it in a way that makes it obvious it must be a collection, I would want a better name.
> you can see c.size() and think "this is the size of the collection"
If you see collection.size(), you don't even need to think; the meaning is right there in your field of vision and you don't need to dedicate one part of your extremely limited short-term memory to remembering what c stands for. I can't see any advantage to shortening it to c, apart from saving a trivial amount of typing.
I find that single letter variable names (or 2-letter names for that matter) really only work if both your coding style and your language allow it. You have to write short functions (5-20 LOC or something like that) in a language that encourages that style. C, Go, LISP, and Haskell (and many more) are great for this kind of thing. But object oriented languages like C++ and Java tend to have much longer functions (50-100 LOC isn't uncommon). I'm not sure the fact that they're object oriented has anything to do with that though.
I agree. It's not a mental tax to read a word we recognize. It's not like we have to sound it out letter by letter, we recognize its form at a glance. It's more taxing to maintain a mapping for an inherently meaningless single character.
Although there are some single characters that do have meaning due to long time convention such as 'i'.
Code like this is completely generic; we know absolutely nothing about `x`, `y`, etc. other than they're distinct arguments; we don't even know their type (they're "parametrically polymorphic").
Would it be better to call them something like `arg`, or `arg1` and `arg2`? The fact they're arguments is obvious, so that would be just as redundant as something like `int int1 = ...`.
This kind of generic "plumbing" appears all the time when using a functional style, where our function's job is to take in a bunch of values and combine them in some way, without caring what they are.
You answered your own question: such abstract (not meaningless) variables make sense when the code is completely generic. Most code however is somewhere between generic and specific, literal values, and variable names should represent that semantically.
Also, I would even argue that x and y are not meaningless in this context. There's a reason you didn't write:
function flip(gnarf) {
return function(t, m) {
return gnarf(m, t);
};
}
function compose(bip, boop) {
return function(blep) {
return bip(boop(blep));
};
}
The sequences {a, b, c}, and {i, j, k}, {m, n}, {p, q}, {x, y, z} are all well-established "abstract" variable names that most of us remember from high school algebra, and all have different baggage and expectations:
- a, b, and c tend to be generic labels for things, not numbers
- i, j, and k are used for indices and tend to be natural numbers (or more rarely for complex numbers/quaternions, where they are floats)
- m and n are used in matrices and also are used for natural numbers
- in maths, p and q are often fractions
- x, y, and z tend to represent coordinate systems and/or floating numbers
We can combine this to create variable sequences, with subtly different meanings. For example: compare (x1, y1), (x2, y2) with (xa, ya), (xb, yb). To me, if I see foo(x1, y1, x2, y2) that implies either top left, bottom right in an axis aligned bounding box, or perhaps the first point and the second point of a line or vector, or some other situation where the two points are somehow connected in one object or shape. Using (xa,ya) and (xb, yb) however suggests I'm dealing with two distinct points.
If the variables have no meaning other than argument placeholders in a transformation between functions, then they must not be given descriptive names that falsely hint at some deeper meaning.
TBH, when reading others' code, I would generally prefer a shorter name to a similarly informative longer name, as it definitely speeds up recognition.
There are a few situations when this is the case: on top of my head, (i) function arguments, (ii) implementations of mathematical formulae that already have standard conventions for notation, (iii) cases when longer variable names are not well chosen and don't tell us much (e.g. his "processElements" function is far, far easier to read than "doSomethingWithCollectionElements"), (iv) situations when there are multiple long names that only differ in the last few characters -- again, I would much rather see "in_x" and "in_y" than "ThisHereInputCoordinateX" and "ThisHereInputCoordinateY", particularly if these are a part of a formula with a few other variables involved.
Might be just me and how I read things, of course -- e.g. I usually print stuff in the smallest readable font, so that I can see more of the logic at the same time, and this is definitely not the case for all people.
Also agreed. I will use single-letter variables like "c" or "x" occasionally for lambdas or anonymous functions, but that's about it. "lambda x: not x" in python - anything longer I think should be descriptive.
I tend to call them index. If the loop is nested I grab functions to call inner bits. i and j especially can get crazy muddled coexisting (could you even pick two more similar letters? Capital I and l depending on the font maybe?).
In general, much prefer languages where I don't ever have to index. E.g. list comprehensions are much more expressive
One of my biggest digs with typical mathematical/scientific notation is that reading equations where there are a number of things that are variables and other things that are constants with all one letter isn't great. I WISH we had used SPEED_OF_LIGHT in math class.
I sometimes use one-character names as a semantic hint that the variable is short-lived and relatively unimportant. I may not know at a glance what "c" means, but I know it's something that was assigned within the last few lines, and that won't live beyond the next few.
I've seen variables with names like the above. It would have been better explained in a comment and used a short variable name. Unless you like typing it forces you to use an editor with autocomplete (which you are crazy not to use one), and IMO pollutes the code. Variables should be easy to type and read. It's a trade off.
If you need that much information about a variable, I would expect, in general, that the context it lives in is doing waaaay too much and should be broken up.
Well, there is a middle ground between 'c' and writing a novel in a variable's name.
Single letter variable names are okay for loop iteration variables, or e.g. x and y when dealing with 2D coordinates (i.e. if within the context a single letter name has useful meaning - I suspect physicists and the like find themselves in that situation often).
But trying to give variables short names (which is a good thing) should not be an excuse to give them obscure names.
As an extreme example, think of Perl, which has a "default variable", that has basically no name at all ($_). When used properly, one can, I guess, write marvelously succinct code, but I try to avoid it and use explicit names.
The older I get, the more I tend to agree with Aristotle's general approach to ethics: Avoid extremes, seek a middle ground/moderation. I am not sure if it is a good ethical principle, but in many cases where ethics don't matter, it is a good guideline.
So for Identifiers: Be short, but clear. When in doubt, choose clarity over brevity, but keep in mind that what might be clear to you could be highly obscure to somebody else. If at that point I was still in doubt, I would pick a name based on how the variable is used: The more rarely it used, and the more significant it is to the program, the more reasonable it becomes to use a verbose name, especially when it is a global variable. For locals, one can always use a short name and a comment to explain what role it plays.
Firstly, there are noise words in there. If there is no other kind of pricing in that context beside product pricing, "product" is useless. If the order of operations is perfectly clear from the program flow, "After" is useless. "But" is a useless conjunction which doesn't add any information to "EmailSent".
This kind of thing can be broken into multiple Booelan variables:
For 'local utility' vars - things like loop counters, short lived array indexes/pointers, collections data (the ubiquitous k,v for 'key', 'value') - things like that, even if a block of code whose scope they are tied to is in a 15-20 line range I'm totally fine with single-letter names.
Also, on the flip side, if say my chunk of code is solely dedicated to operating on a single object I'm totally fine using a one-letter name for those vars as well.
Like say 'Person p' or 'WebView w' etc.
These are notable exceptions though, at least as far as I'm concerned.
Personally I like to make even my short lived variables more verbose. If I'm iterating through a list of things, I'll call my loop var an iThing. It makes it immediately obvious if you're doing something wrong if you write NotAThingList[iThing].
it's obvious that computer scientists have COMPLETELY dropped the ball by not figuring out a way for anyone to write "it", "that", "which" and so on and have the IDE and language disambiguate it into what you were JUST talking about. This is stuff that my great-grandparents should have been suggesting some time after Ada Lovelace wrote about the analytical engine in 1842 or 1843. Not something I should be writing about in 2016. Yeah, okay, before always-on Internet it might make sense to have a small, unambiguous, self-contained grammar. The same is not true in 2016.
Here's how you calculate the absolute value of an integer:
-> "if it's non-negative, return it; if it's negative return its opposite".
Here's how you calculate the absolute value of an integer if you're using any programming language written in 60 years:
-> "if (argument <= 0) return argument; else return argument * -1." (or some variation)
There is literally no way to refer to "it" instead of "argument" except by changing "argument" to read "a" (or "i" or "x" or "$_" or...)
My point is that it's literally impossible to write "if (it > =0) return it; else return (it * -1)" if you've just mentioned "it" and you are there to check and correct the IDE if it's wrong. (Oh, wait, I should write "to correct the IDE if the IDE is wrong.")
I bet 90% of human languages have a way to refer to something you've JUST mentioned without repeating a word for it. (Words like it, that, etc.) I bet 0% of computer languages let you write "it" for the last thing you just referred to, even if there is literally 1 choice in the whole function, as in my absolute value example.
"Computer scientists" don't have an opinion much about a particular IDE; if you want that functionality in an IDE, it might be a shorter path to cause it to exist in the first place.
I bet it's harder than you think.
Also, IDEs are better than they used to be - I stopped using them because they caused problems in the late 20th Century. There was a proliferation of them until Eclipse got good enough to not cause problems. Eclipse still had less text editing power than some just-plain-old-editors from the 1980s. So I only use an IDE if it's the only logical choice for a development system. It usually isn't.
If, as in one shop at which I worked, you constantly write, say EMACS macros and use them a lot, you will evolutionary drift away and it will make your team more and more ... linguistically isolated, which has costs in onboarding and this sort of mild narcissism about your setup.
I think that dependence on an IDE is mostly a weakness, not a strength.
That is fair. I don't have a specific suggestion on how to implement it, which layer (language, IDE, some connected service) or where to do it. I just know that current coding practice must be wrong.
ISTR several environments that have a direct reference to the result of the previous computation, including at least one that uses "it" to refer to that result.
OTOH, I don't remember which one does that, and its a pretty-much completely search-proof topic.
AppleScript has an it keyword[0] that refers to the current application receiving commands. It's also made to resemble natural language in many other ways. From experience, this did not improve it's usability. It is often referred to as a read-only programming language because of that.
Wolfram includes the % keyword for the last result generated, IPython has something similar within their notebooks, R has the .Last.value keyword, Matlab has ans, and many other languages often used from a REPL probably have similar constructs.
I realize it's not quite your point, but if you don't like repeating yourself, macros and "statement expressions" make it simple to extend languages to capture "it" to a tmp variable and then reuse it:
#include <stdlib.h>
#include <stdio.h>
#define dry(x, test, if_true, if_false) ({ \
typeof(x) _x = (x); \
(_x test) ? if_true(_x) : if_false(_x); \
})
#define abs(x) dry(x, < 0, -, )
int main(int argc, char **argv) {
if (argc == 1) printf("usage: %s num [num]...", argv[0]);
for (int i = 1; i < argc; i++) {
char *string = argv[i];
int num = atoi(string);
printf("string '%s', num %d, abs %d\n",
string, num, abs(num));
}
return 0;
}
$ gcc -std=gnu99 -Wall -Wextra -O3 -g dry.c -o dry
$ dry 2 1 0 -1 -2
string '2', num 2, abs 2
string '1', num 1, abs 1
string '0', num 0, abs 0
string '-1', num -1, abs 1
string '-2', num -2, abs 2
Beats me. So this is something that hasn't gotten any better for you over time?
You should look at old school DSP code some time. :) Some of that is translating from variable names in mathematics papers.
Also - for us old guys, you could take typing or you could take a math class, so many of us never really learned to type properly. So typing can be an actual consideration. Schools adapted to this later.
> You should look at old school DSP code some time. :) Some of that is translating from variable names in mathematics papers.
I feel that is sort of a valid exception. If it is common notation in the field you need to be familiar with anyways or you are implementing from a specific source, not using short names adds another layer of mental translation. If I'm implementing an algorithm from a paper I put an "implementation based on: <citation/URL>" on top and try to match it as closely as possible. (DSP code probably doesn't do the latter, because performance, but where possible)
I, as a rule, only use single-letter vars when iterating over an emumerable, in which it is clear what the single-letter var represents. Outside of that, never. The single-letter var also is usually the first letter of whatever actual items are being iterated over. Something like:
The top version means I can read the return line by itself and get a feel for what it does without having to skip back up a few lines. And while there definitely is a tax on longer variable names, I usually don't feel that way with single words.
The brain chunks small common words, so hs probably takes just as much if not more working memory than hosts.
Footnote : Just while writing this I had to look up a couple of times to remember hs, js, and zs. But I never hard to look up to to remember hosts, versions, and zones.
The function is not very long and it's sort of pointless. Besides, what do you name it? collectionInts? That's in the declaration, right there. candidates? As obtuse (and useless) as c.
If you're grepping/ag'ing for c you've got another issue, because I can't think of the context that you would grep c in a function that fits on less than 2 24-row terminal screens. At worst, /c and a few presses of 'n' is all you need once you get to the function.
If you're outside the function grepping, it's because you saw printNFirstIntegers(4, someOtherVariableName). You'll hardly have named the variable (or collection literal) "c". So you'll be using ag printNFirstIntegers.
To me, your request is akin to the last time I had a code review for a rake task and someone complained about the 'f' in:
FileList['deploy_assets/ebextensions/*'] do |f|
@helper.process_template(f, ".ebextensions/#{File.basename(f)}")
end
Calling it File is horribly obvious and annoying.
Edit: The function name probably should be run_erb_on or something like that. None of us are free of naming sins. Lol.
There are some cases where short variable names make sense. In the example the loop index is called "i", and that's good. It's good because it's just an index. The only reason it's there is because the looping construct isn't expressive enough for the desired loop semantics, so the short name means you don't have to care about it.
The use of "n" is also alright. It describes a number, for which "n" is a convention.
"c", on the other hand, is a horrible name. It's worse than "collection", because it's important and the scope is large enough that it's hard to skim for. "collection", however, is also bad. The variable doesn't just refer to a collection, it refers to a collection of integers. Why not call it "integers", or "numbers"?
I find conventions around this to really influence the readability of the average code in different programming languages. Lots of Haskell code can get away with short variables in small functions. Their scopes are small, their purpose is incredibly generic. C code often uses short variable names despite not being concise nor generic, making it unnecessarily hard to read. Common Lisp tends to use descriptive names. It's dynamically typed and contains little type information, and yet you always know what you're working with.
For me it's not how many lines there are in the function, but how many lines of scope the single-character variable lives. If it lives for 2-3 lines in a 12 line function, the dude abides the name.
In dynamic languages, like Python, I think it's often good to call variables something like `fruit_list`, to quickly pick up on a bug where ie: `fruit_list == {'apple'}`.
A convention I've always done for this is to just use a plural name. There are fewer errors based on mixing up the names than you'd think, and it's very readable.
for fruit in fruits:
assert fruit is not 'apple'
print(fruit)
assert 'banana' not in fruits
etc. Especially in Python, it makes code flow very much like English.
Edit: It also goes with the "don't put the type in the name" point, which I agree with in most cases. Depending on your use case, it most likely won't matter if fruits is a list, tuple, set, generator, whatever. The plural implies an iterable interface. However, if the type does matter, I will often use it in the name (in a dynamic lang like Python).
That has always been a Java thing to me. I see it a lot in Sunacle, Apache, and Google originated code (which, for some reason, all three have their own different culture on how to write Java, but it's kind of subtle).
Maybe! My first real coding gig was Java, so I built up a lot of habits there. I've noticed the JetBrains IDEs do this style of naming and inference automatically. I haven't written Java in a long time, but it would make sense if that's where I picked it up. I do like the convention very much though.
I've always considered it a dangerous idiom in dynamic typed languages like Python to create identifiers that differ from each other by only a single character (fruit/fruits), point to completely different objects, and are used in close proximity to each other. It's just asking for a hard-to-detect typo that will blow up at runtime.
I written python for the last 4 years, and I've never had typo problems of that nature. I find the plural form to be so idiomatic it is expected and easier to understand.
I would normally agree, but in the case of plurals like this (at least for myself) it's instantly obviously when one is being used incorrectly.
for fruit in fruit:
print(fruit)
My brain is screaming at me right now that the above doesn't make sense. Even with a click glance, it sticks out like a sore thumb. I'm not entirely sure why, but I'd guess it's because it mimics natural language more, so my eyes are more used to parsing that for mistakes?
Even where the convention isn't to use natural language names, something like this is fairly common (e.g., in lots of fairly terse functional language the convention is to use, e.g., "xs" for a list and "x" for a member -- in some with destructuring matching on lists, the convention is "xs" for the list, "x" for the head, and "xr" for the tail (rest) of the list.)
Funnily enough for your example, depending on whether you are describing different types of fruit or multiples of one type of fruit, the plural of fruit may be "fruit". :)
> It also goes with the "don't put the type in the name" point, which I agree with in most cases.
Is that a problem in practice in Python? That's the whole reason Perl uses different sigils to denote different types of variables, which Python specifically rejected. Personally I prefer being able to tell if something is a collection, and which core type of collection, at a glance (barring refs).
That actually does allow the same name to be used as a scalar, an array and a hash, but it's considered very bad practice.
# Valid perl, but will get you nasty looks from coworkers
my @fruit = qw( apple banana banana apple apple mango apple mango banana );
my %fruit;
for my $fruit ( @fruit ) {
$fruit{$fruit}++; # increment %fruit hash item $fruit
}
> I prefer being able to tell if something is a collection, and which core type of collection, at a glance (barring refs).
Not really a problem, but if you're writing more than a one-off script, such as a module you plan on sharing, it may be common that you get a mixture of concrete types coming in depending on the app and platform. I think in practice, it's actually beneficial to assume you do not know the core type of collection (if your operations will work with many/all of them).
For example, a range object or generator in Python 3, but a list in Python 2. And then someone else comes along and uses your modules with sets.
So with "fruits" (or something like "fruit_iter" for anyone who disagrees with plural naming), you know that you can safely iterate through it. But you may not be able to do random access, or reassignment of elements. There might be times when this matters, in which case you'd want to enforce a specific type.
The only thing I do not like about this is that in Python strings are also iterables. So the difference between passing "Apple" and ["apple"] can be quite large, and yet your program will iterate through "a", "p", "p", "l", "e" with no complaints. The worst experience I've had with this was working with a web API that would return either an array of strings, or only a string if there was one result (not a 1-element array), or a dictionary of objects if there were many results. 99% percent of the time it returned the array of string, and since strings and dictionaries are iterable, it took me a while to notice the bug.
I ought to learn Perl, because that's pretty cool. You're right that that example is terrible to read, haha, but I'm sure there are scenarios where it's helpful.
> The only thing I do not like about this is that in Python strings are also iterables.
This touches on a big pet peeve of mine, and coincides with some ranting I was doing on the Scala Native post the other day. :)
Languages that support coercion should try to make sure they don't overload core operators for different types of operations for different core types. E.g. '+' for numerical addition and string concatenation (one is commutative, the other is not, and if you decide on which action to take depending the order of variables, that's confusing), or ==/!= for string equivalence and numerical equivalence (10.0 and 10 are numerically equivalent, but for strings we generally want an exact match).
Having an iterating operation work on a string without any preparation is one of those things that seems simple and useful, but likely causes a lot of confusion in dynamic languages in practice because you lose track of exactly what it's possible a variable can hold because it's often dependent on the return value of someone else's function. I imagine exposing a method on strings that returned an iterable interface, and requiring that be the method you iterate over a string, would reduce that confusion quite a bit.
> I ought to learn Perl, because that's pretty cool.
I think it's worth picking up the core concepts for anyone, because there's a few concepts (e.g. context) it implements as core parts of the language that are still rarely used elsewhere. Unfortunately, its hybrid beginnings mean that you can largely miss the importance of things like context early on because the code looks enough like what you are used to that you assume it works the exact same way, and 95% of the time that's true. The other 5% will leave you scratching your head and wonder why Perl seems so stupid or inconsistent, when really your mental model is wrong. List and scalar context and how they apply to the core types should be the first learning item on a new Perl programmer's list if they know another C-like language.
> That actually does allow the same name to be used as a scalar, an array and a hash, but it's considered very bad practice.
Are you sure? I could have sworn that I'd seen this as actual style advice in the Camel book. A trip through `perldoc perlvar` (http://perldoc.perl.org/perlvar.html) shows that, at the very least, Perl itself doesn't abide by this convention; for example, we have the scalar `$ARGV`, the list `@ARGV`, and the filehandle `ARGV`.
Sigils allow you to separate variables into different namespaces. It's
possible–though confusing–to declare multiple variables of the same name
with different types:
my ($bad_name, @bad_name, %bad_name);
Though Perl won't get confused, people reading this code will.
There are plenty of things that are shown as possible in the Perl docs, and only slightly less things recognized as generally a bad idea in most circumstances. Instead of Python's one way to do it, there's really more 1 to 3 accepted, idiomatic ways to do it, and another 2-3 that are considered "situationally acceptable" (those odd cases where it actually makes things more readable, etc). There's often a couple ways that are deemed generally just a bad idea, or at a minimum, still waiting for that special case where they can shine. ;)
> There are plenty of things that are shown as possible in the Perl docs, and only slightly less things recognized as generally a bad idea in most circumstances.
Notice, though, that I'm not talking about the Perl docs merely noting that it's possible—I agree that the spirit of the docs is more "look what I can do!" than "look what you should do." I'm talking about what Perl itself does (with the use of `$ARGV`, `@ARGV`, and `ARGV`—although maybe `$_` and `@_` is a better illustration).
chromatic is an excellent programmer, and I certainly respect his voice on Perl over, say, mine, but I feel that he is rather strict, and I do not take his opinions as necessarily representing those of the larger Perl community, as exemplified, among many others, by Wall, tchrist, Conway, and/or merlin.
> I'm talking about what Perl itself does (with the use of `$ARGV`, `@ARGV`, and `ARGV`
I suspect that's a combination of Perl's influence from awk (@ARGV), wanting something easier than awk's ARGIND for the current index in ARGV, and wanting to try out some of these new features Perl had in the beginning. I also suspect that things like this may be on the list of things Larry regrets about early Perl choices. I believe he's on record as saying he regrets the choice of sigil variance for array/hash and array/hash access (@foo as $foo[0] instead of something like @foo[0]). He's got good reasoning for why he chose what he did (based on language, it makes sense), but it's just overly confusing for beginners.
> although maybe `$_` and `@_` is a better illustration
I'm willing to give them a special case, because they are unique, as variables go (well, less so than they should be given Perl's many magic variables, but I think you understand my point). That said, I don't think many Perl programmers would argue that @_ was a better choice than @ARGUMENTS, or something equivalent.
As for assuming the docs in general reflect the current best practices.. I'll just note that the perlopentut man page still uses bare filehandles in the majority of its examples, and to my mind that was decided long ago as a community to be downplayed in favor of lexical filehandles (but for more practical reasons than what we are discussing, bare filehandles are globally scoped).
> chromatic is an excellent programmer, and I certainly respect his voice on Perl over, say, mine, but I feel that he is rather strict
I'm not going to argue with that. I respect chromatic's opinions on style and Perl 5, but I'm not entirely sure he's capable of being entirely objective with Perl 6 yet (which I can understand). He is rather adamant about what he believes are better approaches to a topic.
> I do not take his opinions as necessarily representing those of the larger Perl community, as exemplified, among many others, by Wall, tchrist, Conway, and/or merlin.
Fair enough, but I wasn't sourcing that believe from Modern Perl, just pointing to it as evidence. To be honest, I haven't read Modern Perl (but I've read a lot of chromatic's writing from his blog back in the day when he was writing it), I just assumed it might have something to back up my view, so looked in it. My view on variable naming here is perfectly capable of being more my own opinion that the community, and I was projecting. It's hard to know in Perl unless there's a discussion (and sometimes even after that), as what's acceptable is often a mostly overlapping set of best practices from person to person, but rarely are the sets of preferences entirely equivalent. :)
That said, Conway's Perl Best Practices suggests "Name arrays in the plural and hashes in the singular." It doesn't address our topic directly, but I don't know where my copy went (I sourced that from one of the many two page reference PDFs for PBP) and I don't recall the reasoning he used for that one. I wouldn't fault you for disagreeing with him though, I've shifted my view on some of his suggestions over the year towards or away from his suggestions (notably not using parens on built-ins, but I'm more in-line with his thinking now than I was a decade ago).
Your points are all very good ones, and I appreciate your civil engagement with my argument—especially since all I've really done is quibble with your sources rather than produce any of my own (because I am in the same boat as you, being away from my Perl books). In fact, even if I could find quotations from eminent Perl programmers to support my position, the very nature of TIMTOWTDI would mean that my argument wouldn't represent the entirety, or even the majority of, the Perl community.
Sure! In the end, there's not much that could really be said to definitively settle this besides a survey of a sizable amount of the Perl community. All we're left with is what our own preference is, and what's stuck out to us from books, blog posts, comments and meetings, which is very prone to confirmation bias. In the end, even if the consensus is it's better not done, I don't doubt it would be on the lighter side of ways you could disappoint coworkers. It's only really confusing to the Perl amateur. That's sort of what I meant by coworkers and dirty looks, rather than suggest your coworker will forcibly change your code for their own sanity. ;)
Keep in mind two things, with regard to Modern Perl:
* it's a book for novice programmers, people with perhaps six months of practical programming experience
* it's a book for novice Perl programmers, people who don't have voluminous experience with the language itself
I believe programming is an exercise in making tradeoffs based on incomplete information. You can't teach the kind of good judgment that's based on experience, but I can try, at least, to guide novices away from some of the traps that they're likely to fall into. The subtleties of separate namespaces are difficult enough to learn on your own that it seemed worthwhile to advise strongly against name cognates.
I don't expect that Larry, Tom, Damian, or Randal follow my advice. I don't even follow it in my own code many times. It's not advice for experts.
I appreciate this measured response, but want to make very explicit that I did not mean to criticise you or your advice, much less deny its value to the novice programmer; I certainly apologise if I did so unintentionally.
I always enjoy your writings on Perl, even if I sometimes disagree with specific opinion-based recommendations (as is, almost by definition, the prerogative of Perl programmers), and I hope that I didn't seem to be knocking you or them. I was not even disagreeing with this particular advice, just saying that it didn't necessarily establish the attitude of the broader Perl community on punning in variable names. (There always will be code golfers who will value cleverness over maintainability—and there should be; without them we would never have such gems as `[$a => $b]->[$b <= $a]` for `min($a, $b)`.)
That feels like an ad-hoc reinvention of half a type system. If you want to keep track of your values' types (and you should), why not use a typed language?
As dragonwriter points out (https://news.ycombinator.com/item?id=11690914), Haskell best practice in naming includes things like `head (x:xs) = x`, and I think that one would not accuse this definition of involving an ad hoc reinvention of half a type system.
I agree, the statement, "Pluralize the variable name instead of including the name of a collection type" massively increases the chance of referring to the wrong variables based on a simple typo. Also glancing at the code you have to pay extra attention to notice a single character.
In addition you have some words that don't pluralize well such as fruit or Lexus.
In my opinion the more verbose and unique you can make your variable names the better, even if that means adding redundant words.
Off-topic, but blogspot links are a constant frustration for me on the phone. It's super easy for my fingers to swipe slightly left/right when scrolling and triggering blogspot's next/previous post navigation. I can even accidentally end up slightly scrolled horizontally and have no way to see the left side again.
As a result I mostly ignore blogspot links. But this seems up my alley (http://akkartik.name/post/readable-bad). Anybody else run into these issues? Anybody have suggestions or workarounds? Why do technically savvy folks not notice how crappy blogspot has gotten?
I hadn't realized this was a blogspot thing. I had seen this multiple times and I completely agree. Almost every single time I go to keep scrolling, somehow slightly shift my finger to the right or left and BAM I'm in another article. Very frustrating and pretty counter intuitive for how we're used to the web working.
Blogspot is one of the most frustrating software out there that I interact with regularly (from HN mostly). Desktop version feels very slow and heavy, mobile version has this moronic feature of swiping to next/prev article, and countless other things that make UX really awkward.
Same with Google Groups and some other Google products. It's super weird, they sit on a pile of money, hire thousands of 'best of the best' and can't get some simple things right.
Edit: Firefox on Android seems to eat much of the article in readable mode, while Chrome or Opera on Android seem to have none. So I'm back at square one..
I had a few problems with that, too. English isn't a romance language (it stole a lot of romance vocabulary, though). I guess that the author eventually gets around to explaining what he means: too much vocabulary that doesn't break down into simpler, understandable words. It reminds me of the linguistic contortions you need to do in order to write like the Thing Explainer.
Me three. I guess it's better said that those borrowed words don't break down easily for native speakers of English. There may be more concise ways to assemble variable names in Romance languages if you're a native speaker.
I had the same reaction too. After googling it to make sure, english was a germanic language like I always knew. Then I'm like, English might as well be romance because it's riddled with french words.
Avoid Over-used Cliches
In addition to not being Teutonic, the following variable names have been
so horribly abused over the years that they should never be used, ever.
val, value
result, res, retval
tmp, temp
count
str
Cliches? If you are trying to communicate, these names are well known ways to do that. If there is something more specific to put in there, by all means, but I often find these names useful, combined with a good function name and docs of course. Thoughts?
Agreed with you. Perhaps if you're using temp or tmp, something could be done better, but I see no harm in using the others. If you're counting things, a variable named "count" sound perfectly reasonable to me.
Came here to say this. I bumped my head hard on this part of the text - the whole point of using a cliche is that it's immediately understandable. When I come across an incrementing loop that doesn't use a cliche variable like "count" or a function that doesn't return "return" it increases my mental tax. The nice thing about using a variable like "count" or "return" throughout your function is it's immediately intuitive what's going to happen with this variable.
Yeah this part is a bit ridiculous. A good reason to avoid "str" is because something more descriptive (and probably not much more verbose) would be helpful to see instead. "Because it's overused" is a silly reason, I would hope the author merely intends to criticize inappropriate overuse of these minimally-descriptive placeholder names.
When I'm mapping an array of line items with lodash, the predicate parameter is usually named "item" because it is short and perfectly adequate in context.
Agreed. The distinction between cliche and idiom is arbitrary. We have an idiom of using 'result' for many methods that return a value (e.g. derived getters, builders) making it clear that this thing we just introduced is what will ultimately be returned. As with any set of guidelines, apply common sense to suit your needs.
I think that those are valid names in a good context. e.g. if you have a function like "substring", then you can name "str" as the parameter and "result" the variable where you accumulate the result. Any other more semantic name for "result" would be "substring", i.e. the name of the function itself.
I guess what he's getting at here is that these variable names don't convey what the variable holds.
Let's say you're writing C and you want to return status information from processes as integers. Instead of:
> return retVal;
where retVal could be 0, -1 or -2 to indicate success or failure of the function, how about:
> return functionStatusCode;
? Or be even more specific (let's say the function tried to parse some text) with parserStatusCode.
All of those are more helpful than retval, because they give you some sort of idea as to what you're returning. You'r enot returning how many values were parsed, or some sort of information about what you parsed, you're returning the status of the parsing function.
The meaning of those values is probably a little harder to encode in the variable names (especially if there are many such values), but that's what the comments are for.
Ok, the 'function' part is not useful. And perhaps C was a bad example.
Let's say it's Python now, and for some reason I'm still returning 0, -1 or -2. Then 'statusCode' would be a good name for the variable I guess. The code part indicates that it's a codified version of the status. The smarter way might be to just return a status object or something, in which case perhaps 'statusObject' is better? Not sure.
I guess one thing I took away from the article is that it would be nice to be able to encode _how_ the data is being returned in the name of the return value. This saves me going and finding when the variable was created to get its type, or when the variable was assigned to.
I'm OK with the "one word" parameter / return value names, in part, I guess, because I'm also a big proponent of a "pro forma" comment banner for every routine. For simple things, the comment can be a one-liner ("Return thing X"), but otherwise, explain each param and the return value.
Now, if the internal variables require a "data dictionary" level set of comments, that's another matter. Something is (usually) wrong in that case.
I find this less useful than using retval. I might have a half dozen variables like parserStatusCode in my function, but there is only one retval. What you return is defined by the function definition. It's extra boilerplate to call your variable parserStatusCode when then function is called getParserStatusCode() returning a type of ParserStatusCode.
I have mixed feelings. For a return value, retval et al are completely appropriate. Same for count. Tmp/temp borrow meaning from whatever they are a temporary for. These are all fine.
But "value" is horrible. You really don't know what it is? You might as well name it "variable". "Str" is in the same boat, unless it's short for "tmpstr".
What if I don't? Some of us program more abstract things than the others. For example I might want to write a function, that given a tree, and, well, a value, returns a tree where all nodes that have this value are removed. Doesn't matter that the tree in question will in practice be a tree of Flooblooators, I'd rather write reusable code that works for everything.
Yeah, there's lots of places where "value" is a well-accepted, clear, domain-specific language for a specific component of a construct, and thus using "value" is an excellent variable name.
(Similarly with data: lots of times, I've seen specs where a composite structure had a part called "data". Whether or not that is good naming in the spec, if I'm implementing the spec, using "data" for the element in the program corresponding to that part of the composite in the spec is clearly the exactly right thing to do.)
I would personally use the word "placeholders" rather then "cliches" and think most pros find them useful at times as they convey the proper temporary meaning of their use.
I mostly agree. However, "tmp" and "temp" beg the question: "temp what?". But if you're using say node + express, and you're not using res and req - I'd have to question your sanity.
Yeah, the problem with outlawing "retval" in particular is that there's no good variable name in this situation:
int sum(Collection<Integer> c)
{
int retval = 0;
for(int i = 0; i < c.size(); i++){
retval += c.get(i);
}
return retval;
}
What the hell should I call retval? If I call it sum, that's redundant with the method name. Also, while it might work in Java, it would be more dangerous in a language like Ruby where the equivalent code:
def sum(c)
sum = 0
c.each do |e| retval += e end
sum
end
would, due to lexical scoping, make it impossible to call the method recursively.
- "val" in "retval" carries no meaning. Everything stored in a variable is a value.
- "ret" is an annoying abbreviation for "return" that makes it harder read.
- "return" focuses on an implementation detail—that the function produces its value using the language's "return" statement. It doesn't matter how the result is emitted, just that it is.
If a function is simple enough that the variable storing the result doesn't need a more specific name, "result" is a good default. You could call it "sum" here, but that shadows the function itself—a common problem for result variables—and doesn't really tell us anything we don't already know. We know we're inside a "sum" function.
Yeah, I agree with you completely! Maybe not with val or value, but with everything else.
One of the best ways to calculate something is to build it up line by line. It makes the code really easy to follow. Also see my other comment about languages lacking "it", "that", etc. Result is sometimes a good substitute!
Good advice about variable names (though surely "dentist" isn't all that obscure), but the example function suffers from the boilerplate that the author rightly says is a problem. Looking at the Java Collection interface, the removeIf() description sounds like it actually modifies the Collection rather than creating a new one. Is there a way in Java to do the equivalent of the following Haskell (I'm being lazy and not writing a version for Traversable)
You can use the Java 8 streams interface, converting back and forth at the ends. Or there's a method in Guava-collections (won't be lazy though). Or you can use Scala.
> iterating through a for loop using i is a well-established idiom that everyone instantly understands. Give that count was useless anyway, i is preferable since it saves 4 characters.
"Where does this idiom come from?" you might ask. Well, if I recall it's mostly due to languages like Fortran which implicitly typed identifiers starting with I through N as integers.
exactly right. Some jokes about writing fortran in any language focus on the use of "I, J, and K" as indexes and counters. But in mathematics the common iterator in a summation is also i, j, and k so mathematicians sometimes claim ownership of the use of i as a count.
Fortran, like most early programming languages, was explicitly modelled on mathematical notation. There was debate whether allowing multi-letter variable names was worth the loss of implicit multiplication. But today's programmer can write COBOL in any language.
English is a Germanic language with a strong Romance influence, thanks to the Norman Conquest. (That is to say, you are quite correct that it is not a Romance language.)
it's always funny to me when people talk about the Norman Conquest with respect to Romance Languages... the Normans were Vikings, Germanic. In terms of Romantic influences, it is the Normans who were conquested by Latinate language :)
English is a bastardized munge of a language, truthfully, with both Germanic and Romance parts. Initially it was a Germanic language, but after the Norman invasion of England, a great deal of Romance words were added to the language via the old French that the Normans spoke.
No mention of physical units? I always find it terribly frustrating when trying to read code that talks about physical dimensions like time and space without any clue as to what we're measuring.
const int timeout = strtol(argv[2], NULL, 10);
send_and_waitfor(&msg, timeout);
When I read this code, should I take for granted that the caller and callee are using the same order of magnitude that's intended?
If instead I see
const int timeout_ms = strtol(argv[2], NULL, 10);
send_and_waitfor(&msg, timeout_ms);
then I can quickly audit whether the inputs and outputs actually preserve the convention.
If possible, it's much better to handle physical units with the type system. If your timeout is a timedelta class (or duration/difftime/interval etc.), then this whole issue disappears.
Not trying to convince anybody of anything, but as a public service to expand your mind, I strongly urge anyone interested in these types of ideas to FORGET WHAT THEY THINK THEY KNOW OR HAVE HEARD and to REREAD Charles Simonyi's (he invented WYSIWYG) seminal piece of his PhD thesis which now is some 40 years old. Forget what you THINK you remember about these ideas--they've been butchered in popular understanding--read the original work and digest his system as a whole and on its own merits.
[EDIT add paragraph: Simonyi's overarching idea was to implement a novel solution to a familiar problem which I'll try to state as succinctly as possible: if two programmers are independently given the same programming task, and they turn out to write down the exact same code, you have won. Maintenance and working on other people's code is now solved if it's the same code you would write yourself. That's the problem he is trying to solve while also, incredibly, speeding up the process of independently writing code.]
Pay particular attention to his notions of "type" that lead his naming system quite logically to very opposite conclusions as OP. He's not talking about underlying implementation types, he's talking about the properties of the abtract types that you keep in your head and only attempt to capture in code. Absolutely DO encode them in the name of the variable so it is completely unambiguous what you mean, so it's a contract you will live up to; not for communicating to the compiler, for communicating to other human beings: your compiler talking to other human beings is not that effective.
As a simple example, how many times have you said to your coworker "you need to pass me the file" to which they'll respond, "the file handle (by which they mean POSIX), the file name, the file path, relative, absolute, socket, URI, or do you mean the FILE pointer?" These are all notions of type that are best resolved with a shorthand unambiguous (and yes, local) language which is precise about type.
It helps you track meaningful distinctions and shed meaningless.
Bear in mind that this system comes from "the age of C"; as such, it helps make simple concepts that many programmers find disturbingling confusing: if "ch" means "it's a character", and p- as a prefix means "it's a pointer", then a "ch" and a "* * ppch" will have the same type. What are the attributes of that character type? You need to learn them or define them; I never said it was a C char and you shouldn't think that either; it will be only if those are the type attributes that are useful to your abstract type.
I was under the impression that Hungarian was largely not recommended. I find it's redundant in strong static systems, and unhelpful in duck-typed systems.
As I said, READ THE PIECE, forget about what you think you already know.
A discussion of what he actually said will be more interesting than a discussion of what you misunderstand.
But in response to the point you raised, the purpose of Simonyi's system is NOT to avoid compilation errors (what you call redundant). The naming convention encapsulates precisely what programmers need to keep in their heads while they code; humans are not compilers, and the type information involved is NOT THE COMPILER OR LANGUAGE TYPE, it is the abstract (human) type.
It is to (1,2,3 might not be all or the only reasons) (1) speed the coding task for the human (2) speed the maintenance task for the human and (3) enhance programmer understanding of the code to eliminate errors of human logic.
I'm not saying it's anywhere near perfect :) but can you see that if a naming system works so well that two people would quickly write the same code, that reading that code could conceivably be easier too? That's the claim.
It's a shame that C ... Java like languages became dominant, in that they "hide" identifier names after the type types, rather than putting the identifiers at the start of a line where they are more visible. (thank God for type inference, I guess, in newer languages)
Also, I find CamelCraps an impediment to scanning the names in code, as well. This is less of an issue when the name is one word, but "we" sure seem to like our AdjectiveAdjectiveAdjectiveNoun names in Java-land :-(
E.g. -
qualifier qualifier AdjectiveAdjectiveAdjectiveNoun adjectiveAdjectiveAdjectiveNoun = new AdjectiveAdjectiveAdjectiveNoun(42)
My trouble with naming standards is the diversity of naming across systems/languages.
For your standard crud app you could have a database record with field ORD_NUM, service layer with property OrderNumber, and in javascript orderNumber.
If all I do is live in one part of the stack this may not bother me. But when I have to add a new field and propagate it through the stack I cringe at every mapping.
Here's a tip along these lines: Use 'j' and 'k' for integral loop control variables, not 'i'. Both 'j' and 'k' are pretty high-value Scrabble letters and it's easier to search for their appearances in code. Apart from "break", they don't appear in the reserved words of common programming languages.
(And never use 'l' as a variable name; but you knew that already.)
> Most names should be Teutonic, following the spirit of languages like Norwegian, rather than the elliptical vagueness of Romance languages like English. Norwegian has more words like tannlege (literally "tooth doctor") and sykehus (literally "sick house"), and fewer words like dentist and hospital (which don't break down into other English words, and are thus confusing unless you already know their meaning).
Not only is this vaguely racist; it's also wrong, which is worse.
- English is, in fact, a Germanic language.
- Using more specific words (and English has lots of words) is the opposite of vagueness. A "sick house" could be a house that contains sick people, a house that is sick itself (rotten beams?), a noble family ("house") whose fortunes have turned, etc. A "hospital" is, unambiguously, a facility where the sick are given professional care. Of course, in a different timeline "sickhouse" could have been the word for "hospital", but then it would have been a word of its own, taking up the same amount of space in your mental dictionary as "hospital" does.
- Romance languages are, arguably, less vague even in their grammar. You know that thing where you just jam two words together and call it a day? You see very little of that in Romance languages. Instead, you put a preposition in there, which forces you to be more specific about the exact way in which the two things are related.
- Of course, a "Teutonic" fan would then say that this is a problem with Romance language, and the ability to jam words together is what makes a language truly rich. (Because it's easier to form new words? In which case, see item 2.) And sure, it's ok to have preferences. But if you're going to be a Grammar Nazi, or a literal Nazi, you better have a clue what you're talking about.
What he means, but phases poorly, is to use compounds.
On your other point, at least German is very specific with how compounds work grammatically, namely that they follow a head-right principle which defines genus and declination and which essentially relegates everything left of the head to the status of further defining the head. Additionally, none of your examples work in German for the term "Krankenhaus" (sick house/hospital) for that very reason: a sick house (a house in disrepair) would have to be a krankes Haus following general rules of declension, which would also be the grammatically correct (though completely non-idiomatic) version for a fallen noble house. And while there is a very specific way that defines how stems of a compound are related, German can mark grammatical units differently from English (and akin to Latin) by requiring the agreement of case/numerus/genus between say an adjective and a noun, specifically making it grammatically impossible for krankes Haus to be understood as hospital or Krankenhaus to be understood as a dilapidated house.
edit: the above holds true for Norwegian and Danish as well, by the way.
int printFirstNPositive(int maxToPrint, Collection<Integer> c)
The method name uses "N", but the param for N is named "maxToPrint". Confusing and also violates his/her wasted space rule.
Instead:
int printFirstNPositive(int n, Collection<Integer> c)
I think the short variable names "n" and "c" are fine since they are part of the method signature and have unambiguous meaning, and also because the implementation is so short (so no problem remembering that n and c are the inputs.
As a German I totally agree with teutonic naming. Who doesn't love words like "Umsatzsteuervoranmeldung".
However, I disagree with the chapter "Remove Thoughtless One-Time Variables". I much prefer having a variable I can check in the debugger than having the result of some function passed into another function without being able to see what the value is. Any halfways good optimizer will remove the varibale anyway so there is no performance hit.
If the function doesn't have side effects (and even if it does), the IntelliJ IDEA debugger will gladly evaluate the function call and show you its result for java applications. PyCharm can also do this for python.
The Visual Studio debugger can do that too but that works for only for functions without side effects that can be executed repeatedly. This is often not the case.
I'm all for tricks that make 'coding in the small' easier, but grain of salt on this -- reading a large codebase, esp one with external dependencies, is a separate problem. In my day to day life (and not everybody is me, I know) the large program reading problem is THE problem; comprehending functions is a nice bonus but not as hard.
In small functions, I wish variable names were automatic based on type. If a function has only one local of type T, it should automatically get name t or something.
174 comments
[ 4.5 ms ] story [ 242 ms ] threadAnd now, I want to highlight how difficult was for me to be an understanding and constructive member of society right now, and try to explain why you may be right in some cases, instead of why you're wrong in some other possibly larger number of cases, while foaming at the mouth with an eye twitching, which is what my first internet instinct was.
Nothing's ever perfect. But code can anywhere in a spectrum from good to bad, and we should always strive to reach the good side.
The age-old wisdom holds of course for so many cases, but writing code isn't always software engineering. Wouldn't you grant that it would be a mistake to instil the value that all code written must be carefully crafted? There'd be a ton of missed opportunities for creativity if the act of coding was so sacred.
There no argument for absolute quality in code, only value relative to its use case and context. Outside of correctness of behaviour and acceptable performance, the human-readability of code probably carries the most value in most situations.
Sure you can get by without it, but code that is readable will ultimately be more valued/reviewed/supported/improved.
I have real trouble with single-letter variable names like "c", for any function more than, say, 2-3 lines. I scan the code and it increases my mental load because I have to remind myself what it means.
Obviously a lot of people don't have problems with this, but I do. Anybody else?
Maybe it's because I jump around a lot from function to function?
Unless it's a very obvious index for a for loop I am against single letter variable names. Hell even if it's a for loop, if the code is so long within the loop that I have to scroll then I think the variable names need to be more obvious to keep the context with it as you scroll away from the declaration of the for loop.
Or you could use a decent editor, that keeps track of variable scopes.
Are you suggesting doing a find / grep inside the context of a current scope? Or just color codes / indents / marks in some way the scope? That works to a degree if an editor can do that though that still doesn't ultimately help the fact that it's a single file that you may need to search around for something. Plus not every environment will have your favorite editor setup how you like it.
At least IntelliJ will highlight all uses of the currently selected variable/method/whatever, and will quickly allow you to jump to any of them.
If I'm searching for something by name then it's almost always because it's in use somewhere, and a ctrl+click will take me there instantly, without getting bogged down in false positives.
> Plus not every environment will have your favorite editor setup how you like it.
Sure, but how often do you actually have to work with your regular codebase in such an environment? Sure, such a rule has its uses, but in 97% of cases it's just a symptom of a poor editor setup.
If there were more than one collection, or we weren't using it in a way that makes it obvious it must be a collection, I would want a better name.
If you see collection.size(), you don't even need to think; the meaning is right there in your field of vision and you don't need to dedicate one part of your extremely limited short-term memory to remembering what c stands for. I can't see any advantage to shortening it to c, apart from saving a trivial amount of typing.
Although there are some single characters that do have meaning due to long time convention such as 'i'.
For example:
Code like this is completely generic; we know absolutely nothing about `x`, `y`, etc. other than they're distinct arguments; we don't even know their type (they're "parametrically polymorphic").Would it be better to call them something like `arg`, or `arg1` and `arg2`? The fact they're arguments is obvious, so that would be just as redundant as something like `int int1 = ...`.
This kind of generic "plumbing" appears all the time when using a functional style, where our function's job is to take in a bunch of values and combine them in some way, without caring what they are.
Also, I would even argue that x and y are not meaningless in this context. There's a reason you didn't write:
The sequences {a, b, c}, and {i, j, k}, {m, n}, {p, q}, {x, y, z} are all well-established "abstract" variable names that most of us remember from high school algebra, and all have different baggage and expectations:- a, b, and c tend to be generic labels for things, not numbers
- i, j, and k are used for indices and tend to be natural numbers (or more rarely for complex numbers/quaternions, where they are floats)
- m and n are used in matrices and also are used for natural numbers
- in maths, p and q are often fractions
- x, y, and z tend to represent coordinate systems and/or floating numbers
We can combine this to create variable sequences, with subtly different meanings. For example: compare (x1, y1), (x2, y2) with (xa, ya), (xb, yb). To me, if I see foo(x1, y1, x2, y2) that implies either top left, bottom right in an axis aligned bounding box, or perhaps the first point and the second point of a line or vector, or some other situation where the two points are somehow connected in one object or shape. Using (xa,ya) and (xb, yb) however suggests I'm dealing with two distinct points.
There are a few situations when this is the case: on top of my head, (i) function arguments, (ii) implementations of mathematical formulae that already have standard conventions for notation, (iii) cases when longer variable names are not well chosen and don't tell us much (e.g. his "processElements" function is far, far easier to read than "doSomethingWithCollectionElements"), (iv) situations when there are multiple long names that only differ in the last few characters -- again, I would much rather see "in_x" and "in_y" than "ThisHereInputCoordinateX" and "ThisHereInputCoordinateY", particularly if these are a part of a formula with a few other variables involved.
Might be just me and how I read things, of course -- e.g. I usually print stuff in the smallest readable font, so that I can see more of the logic at the same time, and this is definitely not the case for all people.
In general, much prefer languages where I don't ever have to index. E.g. list comprehensions are much more expressive
-loops (for i = 0; ...)
-scientific variables, in which case they should probably be constants anyway (c = speed of light in a vacuum)
Single letter variable names are okay for loop iteration variables, or e.g. x and y when dealing with 2D coordinates (i.e. if within the context a single letter name has useful meaning - I suspect physicists and the like find themselves in that situation often).
But trying to give variables short names (which is a good thing) should not be an excuse to give them obscure names.
As an extreme example, think of Perl, which has a "default variable", that has basically no name at all ($_). When used properly, one can, I guess, write marvelously succinct code, but I try to avoid it and use explicit names.
The older I get, the more I tend to agree with Aristotle's general approach to ethics: Avoid extremes, seek a middle ground/moderation. I am not sure if it is a good ethical principle, but in many cases where ethics don't matter, it is a good guideline.
So for Identifiers: Be short, but clear. When in doubt, choose clarity over brevity, but keep in mind that what might be clear to you could be highly obscure to somebody else. If at that point I was still in doubt, I would pick a name based on how the variable is used: The more rarely it used, and the more significant it is to the program, the more reasonable it becomes to use a verbose name, especially when it is a global variable. For locals, one can always use a short name and a comment to explain what role it plays.
This kind of thing can be broken into multiple Booelan variables:
These can be initialized or assigned at various points in the flow. Then later we can have:Also, on the flip side, if say my chunk of code is solely dedicated to operating on a single object I'm totally fine using a one-letter name for those vars as well. Like say 'Person p' or 'WebView w' etc.
These are notable exceptions though, at least as far as I'm concerned.
Here's how you calculate the absolute value of an integer: -> "if it's non-negative, return it; if it's negative return its opposite".
Here's how you calculate the absolute value of an integer if you're using any programming language written in 60 years: -> "if (argument <= 0) return argument; else return argument * -1." (or some variation)
There is literally no way to refer to "it" instead of "argument" except by changing "argument" to read "a" (or "i" or "x" or "$_" or...)
My point is that it's literally impossible to write "if (it > =0) return it; else return (it * -1)" if you've just mentioned "it" and you are there to check and correct the IDE if it's wrong. (Oh, wait, I should write "to correct the IDE if the IDE is wrong.")
I bet 90% of human languages have a way to refer to something you've JUST mentioned without repeating a word for it. (Words like it, that, etc.) I bet 0% of computer languages let you write "it" for the last thing you just referred to, even if there is literally 1 choice in the whole function, as in my absolute value example.
Ridiculous!
I bet it's harder than you think.
Also, IDEs are better than they used to be - I stopped using them because they caused problems in the late 20th Century. There was a proliferation of them until Eclipse got good enough to not cause problems. Eclipse still had less text editing power than some just-plain-old-editors from the 1980s. So I only use an IDE if it's the only logical choice for a development system. It usually isn't.
If, as in one shop at which I worked, you constantly write, say EMACS macros and use them a lot, you will evolutionary drift away and it will make your team more and more ... linguistically isolated, which has costs in onboarding and this sort of mild narcissism about your setup.
I think that dependence on an IDE is mostly a weakness, not a strength.
OTOH, I don't remember which one does that, and its a pretty-much completely search-proof topic.
Wolfram includes the % keyword for the last result generated, IPython has something similar within their notebooks, R has the .Last.value keyword, Matlab has ans, and many other languages often used from a REPL probably have similar constructs.
0: https://developer.apple.com/library/mac/documentation/AppleS...
Two years from now, I'm not going to be able to remember "c" from "v" without having to think harder than I have to.
If I name the variables something like what they actually mean or do, however, that's much better. I know what "particle_count" is more so than "p".
You should look at old school DSP code some time. :) Some of that is translating from variable names in mathematics papers.
Also - for us old guys, you could take typing or you could take a math class, so many of us never really learned to type properly. So typing can be an actual consideration. Schools adapted to this later.
I feel that is sort of a valid exception. If it is common notation in the field you need to be familiar with anyways or you are implementing from a specific source, not using short names adds another layer of mental translation. If I'm implementing an algorithm from a paper I put an "implementation based on: <citation/URL>" on top and try to match it as closely as possible. (DSP code probably doesn't do the latter, because performance, but where possible)
List<Host> hosts = hostService.fetchMatchingHosts(hostFilter);
Set<JVMVersions> versions = JVMServiceFactory.factory(region).getApprovedVersions(),
List<AvailabilityZone> zones = RegionFactory(region).getZones();
return hostUpdater.updateJVM(hosts, versions, zones);
to this
List<Host> hs = hostService.fetchMatchingHosts(hostFilter);
Set<JVMVersions> js = JVMServiceFactory.factory(region).getApprovedVersions(),
List<AvailabilityZone> zs = RegionFactory(region).getZones();
return hostUpdater.updateJVM(hs, js, zs);
The top version means I can read the return line by itself and get a feel for what it does without having to skip back up a few lines. And while there definitely is a tax on longer variable names, I usually don't feel that way with single words.
The brain chunks small common words, so hs probably takes just as much if not more working memory than hosts.
Footnote : Just while writing this I had to look up a couple of times to remember hs, js, and zs. But I never hard to look up to to remember hosts, versions, and zones.
If you're grepping/ag'ing for c you've got another issue, because I can't think of the context that you would grep c in a function that fits on less than 2 24-row terminal screens. At worst, /c and a few presses of 'n' is all you need once you get to the function.
If you're outside the function grepping, it's because you saw printNFirstIntegers(4, someOtherVariableName). You'll hardly have named the variable (or collection literal) "c". So you'll be using ag printNFirstIntegers.
To me, your request is akin to the last time I had a code review for a rake task and someone complained about the 'f' in:
Calling it File is horribly obvious and annoying.Edit: The function name probably should be run_erb_on or something like that. None of us are free of naming sins. Lol.
There are some cases where short variable names make sense. In the example the loop index is called "i", and that's good. It's good because it's just an index. The only reason it's there is because the looping construct isn't expressive enough for the desired loop semantics, so the short name means you don't have to care about it.
The use of "n" is also alright. It describes a number, for which "n" is a convention.
"c", on the other hand, is a horrible name. It's worse than "collection", because it's important and the scope is large enough that it's hard to skim for. "collection", however, is also bad. The variable doesn't just refer to a collection, it refers to a collection of integers. Why not call it "integers", or "numbers"?
I find conventions around this to really influence the readability of the average code in different programming languages. Lots of Haskell code can get away with short variables in small functions. Their scopes are small, their purpose is incredibly generic. C code often uses short variable names despite not being concise nor generic, making it unnecessarily hard to read. Common Lisp tends to use descriptive names. It's dynamically typed and contains little type information, and yet you always know what you're working with.
Edit: It also goes with the "don't put the type in the name" point, which I agree with in most cases. Depending on your use case, it most likely won't matter if fruits is a list, tuple, set, generator, whatever. The plural implies an iterable interface. However, if the type does matter, I will often use it in the name (in a dynamic lang like Python).
This is also useful when you have two types of collections in the same place, such as an array and dictionary.
`movie_collection` vs `movie_collections` is a bit trickier
> It also goes with the "don't put the type in the name" point, which I agree with in most cases.
Is that a problem in practice in Python? That's the whole reason Perl uses different sigils to denote different types of variables, which Python specifically rejected. Personally I prefer being able to tell if something is a collection, and which core type of collection, at a glance (barring refs).
That actually does allow the same name to be used as a scalar, an array and a hash, but it's considered very bad practice.
> I prefer being able to tell if something is a collection, and which core type of collection, at a glance (barring refs).
Not really a problem, but if you're writing more than a one-off script, such as a module you plan on sharing, it may be common that you get a mixture of concrete types coming in depending on the app and platform. I think in practice, it's actually beneficial to assume you do not know the core type of collection (if your operations will work with many/all of them).
For example, a range object or generator in Python 3, but a list in Python 2. And then someone else comes along and uses your modules with sets.
So with "fruits" (or something like "fruit_iter" for anyone who disagrees with plural naming), you know that you can safely iterate through it. But you may not be able to do random access, or reassignment of elements. There might be times when this matters, in which case you'd want to enforce a specific type.
The only thing I do not like about this is that in Python strings are also iterables. So the difference between passing "Apple" and ["apple"] can be quite large, and yet your program will iterate through "a", "p", "p", "l", "e" with no complaints. The worst experience I've had with this was working with a web API that would return either an array of strings, or only a string if there was one result (not a 1-element array), or a dictionary of objects if there were many results. 99% percent of the time it returned the array of string, and since strings and dictionaries are iterable, it took me a while to notice the bug.
I ought to learn Perl, because that's pretty cool. You're right that that example is terrible to read, haha, but I'm sure there are scenarios where it's helpful.
This touches on a big pet peeve of mine, and coincides with some ranting I was doing on the Scala Native post the other day. :)
Languages that support coercion should try to make sure they don't overload core operators for different types of operations for different core types. E.g. '+' for numerical addition and string concatenation (one is commutative, the other is not, and if you decide on which action to take depending the order of variables, that's confusing), or ==/!= for string equivalence and numerical equivalence (10.0 and 10 are numerically equivalent, but for strings we generally want an exact match).
Having an iterating operation work on a string without any preparation is one of those things that seems simple and useful, but likely causes a lot of confusion in dynamic languages in practice because you lose track of exactly what it's possible a variable can hold because it's often dependent on the return value of someone else's function. I imagine exposing a method on strings that returned an iterable interface, and requiring that be the method you iterate over a string, would reduce that confusion quite a bit.
> I ought to learn Perl, because that's pretty cool.
I think it's worth picking up the core concepts for anyone, because there's a few concepts (e.g. context) it implements as core parts of the language that are still rarely used elsewhere. Unfortunately, its hybrid beginnings mean that you can largely miss the importance of things like context early on because the code looks enough like what you are used to that you assume it works the exact same way, and 95% of the time that's true. The other 5% will leave you scratching your head and wonder why Perl seems so stupid or inconsistent, when really your mental model is wrong. List and scalar context and how they apply to the core types should be the first learning item on a new Perl programmer's list if they know another C-like language.
Are you sure? I could have sworn that I'd seen this as actual style advice in the Camel book. A trip through `perldoc perlvar` (http://perldoc.perl.org/perlvar.html) shows that, at the very least, Perl itself doesn't abide by this convention; for example, we have the scalar `$ARGV`, the list `@ARGV`, and the filehandle `ARGV`.
1: http://onyxneon.com/books/modern_perl/modern_perl_a4.pdf (But you should buy it if you are interested, chromatic knows what he's talking about).
Notice, though, that I'm not talking about the Perl docs merely noting that it's possible—I agree that the spirit of the docs is more "look what I can do!" than "look what you should do." I'm talking about what Perl itself does (with the use of `$ARGV`, `@ARGV`, and `ARGV`—although maybe `$_` and `@_` is a better illustration).
chromatic is an excellent programmer, and I certainly respect his voice on Perl over, say, mine, but I feel that he is rather strict, and I do not take his opinions as necessarily representing those of the larger Perl community, as exemplified, among many others, by Wall, tchrist, Conway, and/or merlin.
I suspect that's a combination of Perl's influence from awk (@ARGV), wanting something easier than awk's ARGIND for the current index in ARGV, and wanting to try out some of these new features Perl had in the beginning. I also suspect that things like this may be on the list of things Larry regrets about early Perl choices. I believe he's on record as saying he regrets the choice of sigil variance for array/hash and array/hash access (@foo as $foo[0] instead of something like @foo[0]). He's got good reasoning for why he chose what he did (based on language, it makes sense), but it's just overly confusing for beginners.
> although maybe `$_` and `@_` is a better illustration
I'm willing to give them a special case, because they are unique, as variables go (well, less so than they should be given Perl's many magic variables, but I think you understand my point). That said, I don't think many Perl programmers would argue that @_ was a better choice than @ARGUMENTS, or something equivalent.
As for assuming the docs in general reflect the current best practices.. I'll just note that the perlopentut man page still uses bare filehandles in the majority of its examples, and to my mind that was decided long ago as a community to be downplayed in favor of lexical filehandles (but for more practical reasons than what we are discussing, bare filehandles are globally scoped).
> chromatic is an excellent programmer, and I certainly respect his voice on Perl over, say, mine, but I feel that he is rather strict
I'm not going to argue with that. I respect chromatic's opinions on style and Perl 5, but I'm not entirely sure he's capable of being entirely objective with Perl 6 yet (which I can understand). He is rather adamant about what he believes are better approaches to a topic.
> I do not take his opinions as necessarily representing those of the larger Perl community, as exemplified, among many others, by Wall, tchrist, Conway, and/or merlin.
Fair enough, but I wasn't sourcing that believe from Modern Perl, just pointing to it as evidence. To be honest, I haven't read Modern Perl (but I've read a lot of chromatic's writing from his blog back in the day when he was writing it), I just assumed it might have something to back up my view, so looked in it. My view on variable naming here is perfectly capable of being more my own opinion that the community, and I was projecting. It's hard to know in Perl unless there's a discussion (and sometimes even after that), as what's acceptable is often a mostly overlapping set of best practices from person to person, but rarely are the sets of preferences entirely equivalent. :)
That said, Conway's Perl Best Practices suggests "Name arrays in the plural and hashes in the singular." It doesn't address our topic directly, but I don't know where my copy went (I sourced that from one of the many two page reference PDFs for PBP) and I don't recall the reasoning he used for that one. I wouldn't fault you for disagreeing with him though, I've shifted my view on some of his suggestions over the year towards or away from his suggestions (notably not using parens on built-ins, but I'm more in-line with his thinking now than I was a decade ago).
* it's a book for novice programmers, people with perhaps six months of practical programming experience
* it's a book for novice Perl programmers, people who don't have voluminous experience with the language itself
I believe programming is an exercise in making tradeoffs based on incomplete information. You can't teach the kind of good judgment that's based on experience, but I can try, at least, to guide novices away from some of the traps that they're likely to fall into. The subtleties of separate namespaces are difficult enough to learn on your own that it seemed worthwhile to advise strongly against name cognates.
I don't expect that Larry, Tom, Damian, or Randal follow my advice. I don't even follow it in my own code many times. It's not advice for experts.
I always enjoy your writings on Perl, even if I sometimes disagree with specific opinion-based recommendations (as is, almost by definition, the prerogative of Perl programmers), and I hope that I didn't seem to be knocking you or them. I was not even disagreeing with this particular advice, just saying that it didn't necessarily establish the attitude of the broader Perl community on punning in variable names. (There always will be code golfers who will value cleverness over maintainability—and there should be; without them we would never have such gems as `[$a => $b]->[$b <= $a]` for `min($a, $b)`.)
I like type systems when I play around with personal projects in well-typed languages
In addition you have some words that don't pluralize well such as fruit or Lexus.
In my opinion the more verbose and unique you can make your variable names the better, even if that means adding redundant words.
As a result I mostly ignore blogspot links. But this seems up my alley (http://akkartik.name/post/readable-bad). Anybody else run into these issues? Anybody have suggestions or workarounds? Why do technically savvy folks not notice how crappy blogspot has gotten?
Edit: PSA for blogspot owners https://productforums.google.com/forum/m/#!topic/blogger/8hN...
http://chrisltd.com/blog/2012/03/blogger-mobile-theme
Same with Google Groups and some other Google products. It's super weird, they sit on a pile of money, hire thousands of 'best of the best' and can't get some simple things right.
Edit: Firefox on Android seems to eat much of the article in readable mode, while Chrome or Opera on Android seem to have none. So I'm back at square one..
I also love it when people use primitives for time spans along with the units in the name or comment instead of TimeSpan/std::chrono.
Compare for example English with Spanish, Italian and Portuguese:
While the Romance Languages are very similar, English is completely different.https://en.wikipedia.org/wiki/Swap_(computer_science)#Using_...
When I'm mapping an array of line items with lodash, the predicate parameter is usually named "item" because it is short and perfectly adequate in context.
Let's say you're writing C and you want to return status information from processes as integers. Instead of:
> return retVal;
where retVal could be 0, -1 or -2 to indicate success or failure of the function, how about:
> return functionStatusCode;
? Or be even more specific (let's say the function tried to parse some text) with parserStatusCode.
All of those are more helpful than retval, because they give you some sort of idea as to what you're returning. You'r enot returning how many values were parsed, or some sort of information about what you parsed, you're returning the status of the parsing function.
The meaning of those values is probably a little harder to encode in the variable names (especially if there are many such values), but that's what the comments are for.
Let's say it's Python now, and for some reason I'm still returning 0, -1 or -2. Then 'statusCode' would be a good name for the variable I guess. The code part indicates that it's a codified version of the status. The smarter way might be to just return a status object or something, in which case perhaps 'statusObject' is better? Not sure.
I guess one thing I took away from the article is that it would be nice to be able to encode _how_ the data is being returned in the name of the return value. This saves me going and finding when the variable was created to get its type, or when the variable was assigned to.
Now, if the internal variables require a "data dictionary" level set of comments, that's another matter. Something is (usually) wrong in that case.
But, sometimes I use generic names on purpose, so that I can factor the code into something general.
Repeating that in the return value variable is then redundant.
I like naming my result variables `result`. It makes it clear when you first see it what it's for, without having to read the function to the end.
But "value" is horrible. You really don't know what it is? You might as well name it "variable". "Str" is in the same boat, unless it's short for "tmpstr".
What if I don't? Some of us program more abstract things than the others. For example I might want to write a function, that given a tree, and, well, a value, returns a tree where all nodes that have this value are removed. Doesn't matter that the tree in question will in practice be a tree of Flooblooators, I'd rather write reusable code that works for everything.
(Similarly with data: lots of times, I've seen specs where a composite structure had a part called "data". Whether or not that is good naming in the spec, if I'm implementing the spec, using "data" for the element in the program corresponding to that part of the composite in the spec is clearly the exactly right thing to do.)
> I declare The World's Worst Variable Name to be:
> I declare The World's Second Worst Variable Name to be: I would lump in "value" with those two.[1] http://archive.oreilly.com/pub/post/the_worlds_two_worst_var...
- "val" in "retval" carries no meaning. Everything stored in a variable is a value.
- "ret" is an annoying abbreviation for "return" that makes it harder read.
- "return" focuses on an implementation detail—that the function produces its value using the language's "return" statement. It doesn't matter how the result is emitted, just that it is.
If a function is simple enough that the variable storing the result doesn't need a more specific name, "result" is a good default. You could call it "sum" here, but that shadows the function itself—a common problem for result variables—and doesn't really tell us anything we don't already know. We know we're inside a "sum" function.
One of the best ways to calculate something is to build it up line by line. It makes the code really easy to follow. Also see my other comment about languages lacking "it", "that", etc. Result is sometimes a good substitute!
"Where does this idiom come from?" you might ask. Well, if I recall it's mostly due to languages like Fortran which implicitly typed identifiers starting with I through N as integers.
https://elms.wordpress.com/2008/03/04/lexical-distance-among...
If instead I see
then I can quickly audit whether the inputs and outputs actually preserve the convention.[EDIT add paragraph: Simonyi's overarching idea was to implement a novel solution to a familiar problem which I'll try to state as succinctly as possible: if two programmers are independently given the same programming task, and they turn out to write down the exact same code, you have won. Maintenance and working on other people's code is now solved if it's the same code you would write yourself. That's the problem he is trying to solve while also, incredibly, speeding up the process of independently writing code.]
https://msdn.microsoft.com/en-us/library/aa260976(v=vs.60).a... (please read past dr. dimento's introduction)
Pay particular attention to his notions of "type" that lead his naming system quite logically to very opposite conclusions as OP. He's not talking about underlying implementation types, he's talking about the properties of the abtract types that you keep in your head and only attempt to capture in code. Absolutely DO encode them in the name of the variable so it is completely unambiguous what you mean, so it's a contract you will live up to; not for communicating to the compiler, for communicating to other human beings: your compiler talking to other human beings is not that effective.
As a simple example, how many times have you said to your coworker "you need to pass me the file" to which they'll respond, "the file handle (by which they mean POSIX), the file name, the file path, relative, absolute, socket, URI, or do you mean the FILE pointer?" These are all notions of type that are best resolved with a shorthand unambiguous (and yes, local) language which is precise about type.
It helps you track meaningful distinctions and shed meaningless.
Bear in mind that this system comes from "the age of C"; as such, it helps make simple concepts that many programmers find disturbingling confusing: if "ch" means "it's a character", and p- as a prefix means "it's a pointer", then a "ch" and a "* * ppch" will have the same type. What are the attributes of that character type? You need to learn them or define them; I never said it was a C char and you shouldn't think that either; it will be only if those are the type attributes that are useful to your abstract type.
A discussion of what he actually said will be more interesting than a discussion of what you misunderstand.
But in response to the point you raised, the purpose of Simonyi's system is NOT to avoid compilation errors (what you call redundant). The naming convention encapsulates precisely what programmers need to keep in their heads while they code; humans are not compilers, and the type information involved is NOT THE COMPILER OR LANGUAGE TYPE, it is the abstract (human) type.
It is to (1,2,3 might not be all or the only reasons) (1) speed the coding task for the human (2) speed the maintenance task for the human and (3) enhance programmer understanding of the code to eliminate errors of human logic.
Easier perhaps, but certainly not solved. I often have trouble maintaining and working on code I wrote.
It's a shame that C ... Java like languages became dominant, in that they "hide" identifier names after the type types, rather than putting the identifiers at the start of a line where they are more visible. (thank God for type inference, I guess, in newer languages)
Also, I find CamelCraps an impediment to scanning the names in code, as well. This is less of an issue when the name is one word, but "we" sure seem to like our AdjectiveAdjectiveAdjectiveNoun names in Java-land :-(
E.g. -
Or was I supposed to @AutoInject that?Please, just shoot me now.
For your standard crud app you could have a database record with field ORD_NUM, service layer with property OrderNumber, and in javascript orderNumber.
If all I do is live in one part of the stack this may not bother me. But when I have to add a new field and propagate it through the stack I cringe at every mapping.
Is it too late to camel case everything?
(And never use 'l' as a variable name; but you knew that already.)
Not only is this vaguely racist; it's also wrong, which is worse.
- English is, in fact, a Germanic language.
- Using more specific words (and English has lots of words) is the opposite of vagueness. A "sick house" could be a house that contains sick people, a house that is sick itself (rotten beams?), a noble family ("house") whose fortunes have turned, etc. A "hospital" is, unambiguously, a facility where the sick are given professional care. Of course, in a different timeline "sickhouse" could have been the word for "hospital", but then it would have been a word of its own, taking up the same amount of space in your mental dictionary as "hospital" does.
- Romance languages are, arguably, less vague even in their grammar. You know that thing where you just jam two words together and call it a day? You see very little of that in Romance languages. Instead, you put a preposition in there, which forces you to be more specific about the exact way in which the two things are related.
- Of course, a "Teutonic" fan would then say that this is a problem with Romance language, and the ability to jam words together is what makes a language truly rich. (Because it's easier to form new words? In which case, see item 2.) And sure, it's ok to have preferences. But if you're going to be a Grammar Nazi, or a literal Nazi, you better have a clue what you're talking about.
On your other point, at least German is very specific with how compounds work grammatically, namely that they follow a head-right principle which defines genus and declination and which essentially relegates everything left of the head to the status of further defining the head. Additionally, none of your examples work in German for the term "Krankenhaus" (sick house/hospital) for that very reason: a sick house (a house in disrepair) would have to be a krankes Haus following general rules of declension, which would also be the grammatically correct (though completely non-idiomatic) version for a fallen noble house. And while there is a very specific way that defines how stems of a compound are related, German can mark grammatical units differently from English (and akin to Latin) by requiring the agreement of case/numerus/genus between say an adjective and a noun, specifically making it grammatically impossible for krankes Haus to be understood as hospital or Krankenhaus to be understood as a dilapidated house.
edit: the above holds true for Norwegian and Danish as well, by the way.
Instead:
I think the short variable names "n" and "c" are fine since they are part of the method signature and have unambiguous meaning, and also because the implementation is so short (so no problem remembering that n and c are the inputs.However, I disagree with the chapter "Remove Thoughtless One-Time Variables". I much prefer having a variable I can check in the debugger than having the result of some function passed into another function without being able to see what the value is. Any halfways good optimizer will remove the varibale anyway so there is no performance hit.
In small functions, I wish variable names were automatic based on type. If a function has only one local of type T, it should automatically get name t or something.
For me, the second block is more readable than the "good" example. It has issues, but it's more readable.