Thoughts Around Naming Variables
cerebralab.com
cerebralab.com
create_object(); delete_object();
I do:
project_module_object_create(); project_module_object_delete();
I then do the same with files, so the above would probably reside in a file called:
project_module_object.c
This makes everything easy to find, you know where things belong and you can search for partial names to find instances of interfaces.
For local variables, I have a small set of variable names that all have specific meninges like i, j, k, f, sum, found, best, length, count, that I always use in the same way. They therefore become very easy to read since I know their use. If something doesn't fit the limited set of common variables, I revert to long post fix names.
A much longer explanation of how is use C that goes in to more depth about naming can be found here: https://www.youtube.com/watch?v=443UNeGrFoM
K = dot(dot(H, dot(P, H.T)) + R, inv(S))
to
kalman_gain = dot(dot(measurement_function, dot(covariance_matrix, measurement_function.T) + measurement_noise_covariance, inv(system_uncertainty))
because if you don't know what any of these things are by reading up on the theory, the names (or I believe any others) aren't going to help you figure out how a kalman filter works.
For example I’m reading a PDF now where you have 6 variables involved - 2x2 matrix D which is decomposed to variables [g h], a set of points R, two points defining a parallelogram P and a vector v — where the definitions are a scattered (based on order introduction/definition to the pdf, since they’re used for other things as well).
I have to keep a LUT to follow any given formula because it’s just plain hard to keep track of anything.
And of course, the second I convert it to code, it all gets real names with arbitrary intermediaries and at least I can read it through in a single pass.
Names are there to remind you what the hell you’re talking about. Mathematics on the other hand always try to be as general as possible — your formulas don’t want to discuss anything specific; any object that fits the required properties will do, starting subject/context be damned.
(I also just looked up the equations and noticed the formula I gave was just completely wrong, so please don't implement a kalman filter like that.)
Another principle I use is: if a variable's definition and usage can fit on the screen then give it the shortest possible name. Again, this implies that both functional-leaning style of programming and short naming are encouraged.
Corollary: there's no reason to give an int loop variable any name other than "i" unless there's a naming conflict or the loop body is too long (which it shouldn't be). Right?
But at the end of the day I'd formulate the fundamental principle of naming as:
Do whatever it takes to reduce mental tax for the reader, assuming the reader is aware of the context of the codebase, and roughly has a median level of experience in programming.
The latter part is important because I think good code should teach less experienced programmers rather than make it easier for them to read it at the expense of succinctness.
But it isn't always easy to describe both clearly and succinctly what exactly a function (/ etc.) is doing.
And a particular issue I have is one of audience: to whom is this name addressed? Should it be at least somewhat obvious to a newcomer to the codebase to understand what the function is doing? Or can I assume that the reader / maintainer is already knowledgeable of the context in which this function exists?
In my (limited) experience, this becomes exacerbated when I'm trying to name some abstract operation in a context that doesn't already have a well defined lexicon. So then I, unfortunately, must be the person to create this dictionary of terms that I will be referring to repeatedly throughout the problem space.
On top of this, I generally don't even know how I'm going to solve the problem when I first start implementing, so my first round of names might be strikingly obtuse to an outside observer. But if the implementation becomes sufficiently complex, and I don't take the time to refactor or receive input early on, these names become intuitive to me via repetition, so then I end up building on top of them and create this pyramid of gibberish that at some point made sense to me but that someone will unfortunately have to take the time to grok at some point in the future.
This doesn't happen so often that I would say it's the second hardest problem in our field, but it definitely is something that can contribute significantly to tech debt. ¯\_(ツ)_/¯
I have swung back on forth on variable naming over the years. Right now for me the focus is on part V of this article. Currently I prefer shorter variable names, even if they require a bit more context.
Let's use a concrete example. Say I'm writing a lambda function, and I name it LambdaThatDoesTheThing. This is a long name that (suppose) clearly describes the Lambda. This requires little context, tells me what the function does, and it helps me to tell it apart from others. So far so good.
Now imagine we want to add Metrics, so we call them LambdaThatDoesTheThingMetrics. But maybe we have different kind of metrics, so we actually need two objects, LambdaThatDoesTheThingExecutionMetrics, and LambdaThatDoesTheThingFailureMetrics. We also want alarms, so we add LambdaThatDoesTheThingAlarms. And we want a dashboard, so we add LambdaThatDoesTheThingDashboard.
These variables by themselves might not be a big deal, but when you compose them together they create big chunks of code. At some point the long names actually obscure the intent of the code.
What if instead we encapsulate all of this in a function createLambdaThatDoesTheThing, and then remove the long prefix from all variables? Now we can clearly see that we are manipulating Metrics, Alarms and Dashboards. Sure, we need a bit more of context, but once we have that, the code is much easier to read and follow.
This infrastructure example might be a bit synthetic but I believe it represents how some real codebases are written.
Can someone explain this? What numbers?
(A brief aside on what I mean by inherent complexity: solving some partial differential equation or writing 'I must turn in my homework' one hundred times might both take the same amount of time, but the latter is less complex. Similarly, Dijkstra's algorithm to compute shortest paths might be easier to implement than a form to add a new employee to the database, but it is nevertheless more complex.)
When writing a program, one usually has to juggle lots of balls that move in simple ways. You can make a career out of writing programs that convert data between various mostly equivalent representations (table in database, packet on the network, Python object in RAM, pixels on the screen). I do not want to claim that this is easy: the details of what data ends up where, of how to deal with the not-quite-equivalent representations, of who is able to see what, etc., matter. But solving complex problems of which code to write does not mean that the code solves complex problems.
So it makes sense to use longer names. You have only little attention to spare on individual pieces and s.add(b) is more difficult to understand than submit_form.add(submit_button). Here, adding things to some container is a well-understood concept, you simply want to know which container and which things.
Conversely, when your problems have a high inherent complexity then you end up with a small number of balls that behave in a complicated manner. (If you have many complicated balls, the problem is too difficult to solve.) So you split up your explanation: first you describe the balls, then you assume that the reader knows what they are and give a succinct explanation of their interactions. (Flipping the order sometimes makes sense too.) It is clear that ax²+bx+c = (ax+b)x+c is easier to understand than equals(add(add(mul(parameter_quadratic, mul(variable, variable)), mul(parameter_linear, variable)), parameter_constant), add(mul(add(mul(parameter_quadratic, variable), parameter_linear), variable), parameter_constant)). The latter is simply too noisy, it does not allocate the symbols in an efficient manner to convey its meaning.
However, writing ax²+bx+c assumes that the reader is familiar with the meanings of a,b,c,x and with addition, multiplication and exponentiation. You probably are (else this would have made a poor example), but even if you were not, it would still make sense to explain these concepts first, to enable the succinct explanation.
import foo
foo.function(a)
foo.bar = b
I think a lot of naming problems in other languages are really workarounds for the lack of modularity.