I’m looking at a function that that has several statements like this:
n = returnDifferentVersionOf(n);
I.e., the value of the same variable n
changes progressively several times during the course of a subroutine — rather than a newly named variable being assigned at each change.
What is the generic name of this technique (if there is one)?
A more full example might be (in Ruby):
# reuse same var
def cromulentize(str="")
str = "wowza" if str.empty?
str += " adios!"
str = str * 3
str.gsub!('a', 'X')
str = str[0..-3]
str.upcase
end
What is that technique called, as opposed to this one:
# uses diff vars
def cromulentize(str="")
non_empty_str = str.empty? ? "wowza" : str
adios_str = non_empty_str += " adios!"
multiplied_str = adios_str * 3
gsubbed_str = multiplied_str.gsub!('a', 'X')
spliced_str = gsubbed_str[0..-3]
upcased_str = spliced_str.upcase
end
(Note that in Ruby the value of a method’s last expression is the return value.)
8
In some cases, n
might be called an accumulator, or you might say that you’re accumulating the result in n
. That’s especially true if n
is used to gather the result of a number of similar calculations, like adding up a list:
n = 0;
n += foo.price;
n += bar.price;
n += baz.price;
n += qux.price;
print("The total is: %f", n);
accumulator is an old computing term for a variable (or in hardware, a register) that stores results for further use. You can see how the name applies when the operations are all the same, as above… the value in n
piles up the way falling leaves accumulate on the ground. But I think you can still use the term accumulator even if the operations are not all the same, as in your example.
9
Unless I’m missing something here, the word you’re looking for is one you already have: variable.
In mathematics, a variable is a value that may change within the scope of a given problem or set of operations.
With this technique:
# uses diff vars
def cromulentize(str="")
non_empty_str = str.empty? ? "wowza" : str
adios_str = non_empty_str += " adios!"
multiplied_str = adios_str * 3
gsubbed_str = multiplied_str.gsub!('a', 'X')
spliced_str = gsubbed_str[0..-3]
upcased_str = spliced_str.upcase
end
What you actually have there is a bunch of constants since their value is assigned once and never changed after that.
4
The closest name you could really give this is “‘threading’ (not in the concurrent programming sense) or ‘compose’ in an imperative language”. This is exactly the sort of thing that (eg) Clojure solves with its -> macro.
http://blog.fogus.me/2009/09/04/understanding-the-clojure-macro/
It takes a series of functions that should be executed in a particular order and feeds the result of each function to the next function in the sequence. You could achieve the same effect by simply nesting function calls but that gets ugly fast.
6
ok, in response to downvotes on my reasoning, I submit.
this is called using a Temp variable
And
it is bad
I definitely like the second snippet better. With new variable names I know what is supposed to happening instead of having to guess about the intention of the original coder. This makes it a thousands times easier to refactor code, to simply add two lines in between two existing lines, or to create a whole function for what was a simple assignment or manipulation by a accumulation or something.
Managing complexity is critical to success of any non trivial program, and this ‘technique’ of using the same variable name is not helping manage complexity. In fact, it is making it worse, as the code reader has to deal with a kind of multipurpose, polymorphic variable.
The only case I can see this being somewhat helpful is when
-
The scope of this variable is very short and adding verbose names would only complicate things more. But beware, what seems simple and of short scope now, can easily be expanded over time, and programmers won’t rename anything and eventually you end up with a mess.
-
Sometimes, when you know the expected output format of a variable at the end of a function, you MAY use that variable as it’s own temporary holding area for some manipulations that are relatively incidental and the whole scope of the variable remains small. But even this, SO, SO, SO many times, when trying to redesign and refactor code like this, I’d would have rather the original coder spent twice as many lines and twice as many variables, just to show me exactly, in
explaining to 6-year old level of detail, what is supposed to be going on. Nonbelievers, flame on.
10
I would call it a mess. None of those changes are related, either in cause or in effect. Making all those checks and changes in one place in your code is pointless. If this string is a significant property of a domain object, there should be meaningful, distinct methods which change it, each change being separate. Unless you can provide some better evidence to show otherwise.
That is garbage code.
Edit: as I hope is clear from the discussion in the comments, this isn’t a dig at mtoast.
5