8 ms·
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 hav
by rectang 11y ago
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?
- JamesBarney 11y agoI agree. I prefer this 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.
- BinaryIdiot 11y agoI 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.
- Nullabillity 11y ago> It makes scanning, grepping, etc all so much easier. Or you could use a decent editor, that keeps track of variable scopes.
- BinaryIdiot 11y ago> 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.
- Nullabillity 11y ago> 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.
- burkaman 11y agoI 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.
- chimprich 11y ago> 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.
- teamhappy 11y agoI 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.
- elishacook 11y agoI 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'.
- chriswarbo 11y agoWhat about variables which are inherently "meaningless", i.e. they're only given a name in order to distinguish them from each other? For example: function flip(func) { return function(x, y) { return func(y, x); }; } function compose(func1, func2) { return function(x) { return func1(func2(x)); }; } 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.
- kazinator 11y agoIf 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.
- vanderZwan 11y agoYou 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.
- owenconti 11y agoI can't stand that. I like using names that don't make me think about what the variable means.
- xixi77 11y agoTBH, 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.
- nilved 11y agoHave you considered not writing functions longer than 3 lines?
- euphemize 11y agoAlso 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.
- cagey 11y agoI too abhor single-letter variable names. My personal convention: minimum identifier length==2. {i,j,k}->{ix,iy,iz}, c->ch.
- ambulancechaser 11y agoI'm all for descriptive names but do you really not like iterator variable names like i,j,k or x,y,z? You prepend them i (for integer i suppose)?
- bpicolo 11y agoI 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
- ArkyBeagle 11y agoIn FORTRAN 64, variable names were significant. I was an integer, F was a float, that sort of thing. This created habits that persist to this day.
- cagey 11y agoactually i for "index" ('ix'->'index x'), not "integer"
- hnruss 11y agoAgreed. The part about 'c' seemed pretty contradictory, and without much explanation as to the exception.
- rocky1138 11y agoSingle letter variable names are valid only in two cases: -loops (for i = 0; ...) -scientific variables, in which case they should probably be constants anyway (c = speed of light in a vacuum)
- bpicolo 11y agoOne 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.
- fenomas 11y agoI 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.
- snarfy 11y agobool productPricingUpdatedAfterDeliveryFailedButEmailSent = false; 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.
- psylence519 11y agoIf 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.
- lgunsch 11y ago100% agree! I always try and remember the Single-Responsibility-Principle.
- krylon 11y agoWell, 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.
- ChemicalWarfare 11y agoFor '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.
- Splines 11y agoPersonally 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].
- logicallee 11y agoit'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. Ridiculous!
- ArkyBeagle 11y ago"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.
- drdeadringer 11y agoI agree with you. 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".
- ArkyBeagle 11y agoBeats 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.
- detaro 11y ago> 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)
- bobwaycott 11y agoI, 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: for c in customers: do_something(c)
- krinchan 11y agoThe 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.
- jorams 11y agoI very much agree. 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.
- pohl 11y agoFor 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.