- Where they are actually correct, such as dimensions (x, y, z) or vectors (j, k, l, u, v, w).
- Other mathematical symbols (N, M, e, t). Maths is also a special case in which I'm personally willing to do away with usual variable naming conventions, for example when translating formulas from a scientific paper into program code.
- Very short code, e.g. lambdas (lambda x: x2), list comprehensions ([p.title for p in posts]) or simple loops.
If you look at SQLite, you'll notice that most variable and struct field names are short and cryptic, and that library is still considered a high-quality piece of code.
Regardless, I don't understand all the downvotes you're getting.
for (int i = 0, len = string.length(); i <= len; i++) {
char c = string.charAt(i);
if (c == '\t') {
return true;
}
}
return false;
rather than something like boolean tabFound = false;
int stringLength = string.length();
for (int characterIndex = 0; characterIndex <= stringLength; characterIndex++) {
char character = string.charAt(characterIndex);
if (character == '\t') {
tabFound = true;
}
}
return tabFound;You should probably abstract away some of that logic though (and `string` isn't a great variable name either):
boolean tabFound = includes(line, '\t');Yes. Very much yes. My personal rule is to _always_ use single-letter names for Python comprehension indices, because line length is the biggest enemy of readability there.
I was today years old... :|
Some of that is from mathematics, for example (random code from the Internet):
reverse2 xs = go [] xs
where
go ys [] = ys
go ys (x:xs) = go (x:ys) xs
In general, more abstract you get, the less important it is to devise long names, because things are going to be abstract anyway. Often, all you can tell about the object is already encoded in the type system.Even in current practice, people prefer "log.info(..)" to "centralizedLoggingSystem.informationalMessage(..)". They prefer "Exception e" to "Exception unexpectedlyFailedToWriteAccountingFileException". We also prefer to write "a * b" instead of "a.multiplyBy(b)".
Sometimes simply the global consistency trumps the local context.
This is something every hello world tutorial should point out, but obviously most of them leave a lot to be desired. Or "argument count," as I know it, not "counter".
Because of this, whenever you're reducing something you inherently peel off information and it's lost to 'simplify' something. This is where all sorts of forms of documentation come in handy: they provide a venue to retain and share some of that lost information you think might be critical and explain those 'simplification' assumptions.
In the above, information for reductionist abstractions often get lost over time when people make assumptions and don't share them in some form. Once you understand the original meaning--information that was lost, often times if well designed, everything falls into place for understanding fairly quickly.
I recently saw a post somewhere explaining why "uppercase" and "lowercase" described characters due to historical context where on printing machines, what we know as uppercase letters were stored in the top of the case while what we know as lowercase letters were stored in the bottom of the case (hence the upper and lower cases). Most my life I just assumed "upper" meant "bigger" and lower meant "smaller." In this particular case, that lost nomenclature information didn't add much value (although interesting). In some cases, it does (like the argc and argv information pointed out). Choosing what information to reduce and carry forward is an art form. You also have to be careful when teaching about what assumptions you take for granted that most don't start with.
I'm a believer in understanding at least one level beyond what an abstraction system is doing for me. It's not the most efficienct thing, but it demystifies the abstraction and when you run into hurdles introduced because the structure of that abstraction, you know why and often can devise ways to fix it. It's not always possible and in some cases isn't worth it.
Most modern software development has so many high level abstractions that understanding even one level down is typically impossible for any sane person given typical resource constraints for a given API. Because of this, we run into all sorts of messes where were drowning in abstractions (that aren't very standardized or widely adopted, instead composed together in case by case basis) we don't understand (i.e. complexity). That's all well and all until those abstractions fail and you're the person responsible to repair/mend them back into usefulness for a particular case--then it's a nightmare.
When I parse code I'm mentally reading to myself, so argv is deplorable gibberish that has to be translated to "arg-vee". It's like traveling over rocky ground, one step is easy enough but over a distance it really slows you down. argvec saves almost as many letters, is way more readable, abbreviates both words down to the same scale, carries more semantic meaning through for a newbie, etc.
Some English words can't be phonetically abbreviated and I think those are better off written in full.
Huh wow, I've never actually been taught what argv stands for and have gone my whole life (post learning C) assuming it means Argument Values.
I'd also say that short names are sooner a product of line-length limitations than refactoring. Having to spread out every single statement over many lines because your reference a 12 character function 3 times in the same line and you are limited to 80 characters sucks.
I'm not a fan of sacrificing readability for some arbitrary screen-width limitation.
Going up to 100 or 120 is already sufficient
I actually like the limitation, because it makes me use more enters, so that the information ends up not within one line but in multiple. Which mans more lines (and LOC) but better readability.
I guess a good comparison is Twitter's limitation on the characters. It has its pros and cons.
Only other use case I can think of is doing metaprogramming or some sort of templating where you have a variable, but might no even know what it represents, because it isn't your concern.
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (a:as) = f a : map f as
Personally I don't see any reason to use longer names than f, a, and as because you can't add any additional information.You might say "well I don't write code like that", and I don't have any answer for you. But I find I write a fair amount of generic code.
Well you could...
map transforming_function (element:rest_of_list) = transforming_function element : map transforming_function rest_of_list
...but the cost in terms of loss of brevity would far outweigh a benefit that would only accrue to complete beginners, who would be better served by comments and test cases.Because you are writing abstract code.
Odds are that a lot of your code is better done abstract, and only fully specified in a short context.
when I look through older C codebases (Python, Linux), I often notice the extremely short and cryptic names. I wonder whether this practice is an artefact of a time before auto-completion & automatic refactoring?
These days, you can use meaningful names without much typing. From a reading perspective, I believe that longer names (within limits) are easy to parse. Humans see words, not characters.
--
E.g. When I first understood that argc means "argument counter" and that argv stands for "argument vector" it was a little revelation to me.