58

Should I reuse variables?

I know that many best practices say you should not do it, however, later, when different developer is debugging the code and have 3 variables that look alike and the only difference is that they are created in different places in the code, he might be confused. Unit-testing is a great example of this.

However, I do know that best practices are most of the time against it. For example they say not to "override" method parameters.

Best practices are even are against nulling the previous variables (in Java there is Sonar that gives a warning when you assign null to variable, that you don't need to do it to call the garbage collector since Java 6. You can't always control which warnings are turned off; most of the time the default is on.)

  • 11
    Since Java 6? You never needed to assign null to variables in any version of Java. When a variable goes out of scope, it releases the reference to its object. – Kevin Panko Oct 21 '11 at 14:53
  • 35
    re-using of variables is one of the first thing that code-obfuscators use – Lelouch Lamperouge Oct 21 '11 at 15:33
  • 6
    Variable re-use conflicts with choosing decent identifiers for your variables. In modern languages there aren't really any advantages to variable re-use that outweigh the benefits of having good identifiers. – Joren Oct 21 '11 at 19:26
  • 4
    Also note that not all reuse is reuse. Old FORTRAN programmers, even those that have drifted off to other languages, routinely use I,J,K,L,M,N (or i,j,k,l,m,n) for all our DO-loop (for-loop) counters. We are used to seeing things like SUM = SUM + A(I,K) * B(K,J), or sum += a[i][k]*b[k][j];. – John R. Strohm Oct 22 '11 at 15:32
  • 1
    Reusing variables could be justified when programming microcontrollers with very limited resources (a few kBytes of RAM). – m.Alin Oct 26 '11 at 19:09

12 Answers 12

129

Your problem appears only when your methods are long and are doing multiple tasks in a sequence. This makes the code harder to understand (and thus maintain) per se. Reusing variables adds on top of this an extra element of risk, making the code even harder to follow and more error prone.

IMO best practice is to use short enough methods which do one thing only, eliminating the whole problem.

  • what about unit-testing? for example I need to test if after executing the method for the second time it still works as expected. – IAdapter Oct 21 '11 at 8:11
  • 20
    @IAdapter, unit test code is a different issue, where the standards may be more relaxed than for production code. Still, making it readable and easy to maintain is high priority. You can (and should) extract methods from your unit tests as well, to keep them short and easy to read (and to eliminate the need to reuse variables). – Péter Török Oct 21 '11 at 8:17
  • 3
    @IAdapter, for the scenario you described I would not reuse a variable. The appropriate thing would be something like result1 = foo(); result2 = foo(); Assert.AreEqual(result1, result2); I'm not seeing a lot of places where you'd need to reuse a variable in this case. – JSBձոգչ Oct 21 '11 at 14:31
  • 1
    @IAdapter for(int i=0;i<2;i++) {result=foo();assertEquals(expectedResult,result);} – Bill K Oct 21 '11 at 23:07
  • 2
    +1 - this is a good code smell for when to make smaller methods. – user1249 Dec 29 '11 at 10:11
49

Variable reuse in a method is a strong sign that you should refactor/split it.

So my answer would be that you shouldn't reuse them, because if you do then it would be that much harder to refactor it later.

19

It depends.

Some variables might be created exactly for the purpose of holding a certain kind of data, which can change during the execution of a function. Return codes come to mind here, for example:

void my_function() {
    HRESULT errorcode;
    errorcode = ::SomeWindowsApiFunction();
    if (FAILED(errorcode)) { /* handle error */ }
    errorcode = ::AnotherWindowsApiFunction();
    if (FAILED(errorcode)) { /* handle error */ }
}

The variable name makes it very clear what this variable is intended to store. I think other usecases such as this are possible, where a variable is conceptually a container which is logically used by different instances of very similar things during the course of a function.

In general, however, this should be done only in circumstances where it is absolutely clear to possible readers of the code. In no case, except maybe extreme optimization with no regard to code legibility, should a variable be reused just because the type fits.

All of this basically follows from good practices in variable naming. Names should speak for themselves. If it is difficult to put the exact purpose for all re-uses in a short name, it is best to just use distinct variables.

15

The biggest reason I don't reuse variables (especially in unit tests) is because it introduces an unecessary code path, one that is hard to test and debug. A good unit test should be independent from other tests and when you reuse class (instance) level variable in a unit test fixture you have to ensure to assert on their state before each test. A good unit test also isolates defects so in theory each test case (method) should only assert 1 behavior for the system under test. If your test methods are written like this there is rarely a need or benefit to reusing a method level variable. Last, in languages that support closures and asynchronous processing, it is really hard to reason about what the hell is going on if you are reusing variables throughout a method.

  • so I should write test methods like -testSomething and assert for single method invocation -testSomethingTwoInvocations and asserts for only second invocation? – IAdapter Oct 21 '11 at 9:19
  • 2
    Yes. It helps you pinpoint if it's the first or second iteration that failed. mspec may help for this, its inheritance tree will be very useful. – Bryan Boettcher Oct 21 '11 at 15:37
  • If you use "variable" when you mean "class variable" or "instance variable" then you need to express yourself more clearly. – gnasher729 Jul 6 '17 at 10:30
13

You should use different variables. If you are worried that your colleague will be confused, give them names that clearly cover their roles.
Re-using variables is a likely source of confusion in the future; better to clear it up now.
In some cases, the same variable name can be re-used; for example i in a simple counting loop. In these cases, you should of course make sure that the variables are in their own scope.

EDIT: Re-using variables is sometimes a sign that the Single Responsibility Principle is violated. Check to see if the re-used variable is used in the same role. If it is, it may not be re-use at all (although it may still be preferable to have two different variables, to restrict the scope of said variables). If it is used in different roles, you have an SRP violation on your hands.

4

There is one situation in which you may want to reuse a variable regardless of the great advice given by other answers: when your compiler needs a helping hand.

In some cases your compiler may not be clever enough to realize that a certain register-allocated variable is no longer being used by the next part of the code. Therefore it will not re-use that theoretically free register for the next variables, and the generated code may be sub-optimal.

Note that I don't know of any current mainstream compilers that fail to catch this situation correctly, so never, ever, ever do this unless you know for a fact that your compiler is generating sub-optimal code. If you are compiling for special embedded systems with custom compilers, you might run into this problem still.

  • 17
    -1 unless you can point to a real-world situation where this actually happens, and where reusing a variable makes an appreciable difference. This is a theoretical solution to a theoretical problem, and not a very good one at that. Where the compiler decides to put variables is the compiler's concern; if your compiler generates poor code, and if it really makes a difference, then fix or replace the compiler. – Caleb Oct 21 '11 at 15:35
  • 3
    @Caleb - you do not always have access to the compiler source code for the platform you are developing on, especially for proprietary embedded platforms. I also DID say in my answer that I don't know of any current mainstream compilers (or interpreters/VMs in fact) that do not correctly perform this liveness analysis in all cases that I've looked at. However, I have worked on proprietary embedded systems with custom compilers that were very bare-bones in the past (10 years ago or so). The system was very limited in capability, and so was the compiler, so this situation did occur there. – Joris Timmermans Oct 25 '11 at 7:55
  • 2
    +1 I did exactly such a reuse in past project (highly optimized media code written in ANSI C). As far as I recall the difference was easily visible in assembly and measurable in benchmarks. Never ever did and hope that will never ever have to do such a reuse in Java. – gnat Oct 25 '11 at 13:45
  • @Caleb fixing or replacing the compiler may not be an option for a number of reasons, and you simply have to make do with what you have. – user1249 Dec 29 '11 at 9:59
  • @ThorbjørnRavnAndersen Is it conceivable that one might be forced to use a lousy compiler, and furthermore that performance might be so critical that you need to second guess the compiler and manipulate your code in order to reuse a register? Yes. Is it likely? No. MadKeithV agrees that he can't provide a real world example. Is it a best practice? Is it good style? Is it an indicator of code quality? Definitely not. Is this a useful answer to the question as written? Due respect to MadKeithV, but I don't think it is. – Caleb Dec 29 '11 at 13:23
2

I would say NO.

Think about this scenario: your program crashed and you need to work out what happened by inspecting a core dump... can you see the difference? ;-)

  • If your core dump is from an optimized build, it may have the variables share memory anyways. So that's less helpful then it might be. – Winston Ewert Oct 22 '11 at 3:03
  • of course, an optimized build is not very useful for debugging! but in any case you still have the option of using a debug build... And when you have the debugger attached, you don't need to go step by step from the beginning of a function to see how the variables change, because they don't! :-D – fortran Oct 22 '11 at 11:04
2

No, you're not improving the code that the machine is running (... the assembly code). Leave reusing whatever memory the compiler uses for the variable to the compiler. Quite often it's going to be a register, and reusing bought you nothing. Focus on making the code easier to read.

0

It depends. In a dynamic language, where type resides on values rather than variables then if I had a well-named argument to a function that, for example, was a string. I a change in algorithm meant that it was always used after being interpreted as an integer, then, as a first draft I might do the equivalent of

scrote = int(scrote)

But I would eventually look to change the type sent in to the function and note the change in parameter type.

  • 1
    Putting a line like "scrote = int(scrote)" in the middle of a long batch of code is a great way to drive maintenance programmers crazy. – jhocking Oct 21 '11 at 16:07
  • The issue is more likely to be with the "long batch of code" you mention. – Paddy3118 Nov 11 '11 at 20:42
  • Well as the accepted answer notes, reusing variables is only really an issue with long batches of code. Basically, in any situation where you would write something like "scrote=int(scrote)" I would prefer to put int(scrote) in a new variable, or better yet pass int(scrote) to a new function. – jhocking Nov 12 '11 at 15:14
0

First, look at your development environment. If you have problems debugging because you have five variables in different scopes with identical names, and the debugger doesn't show you which of these variables is the one you need, then don't use five variables with the same name. There are two ways to achieve this: Use one variable, or use five different names.

Your debugger may also make it painful to debug a function with many variables. If a function with 20 variables is harder to debug than one with 16 variables, then you might consider replacing 5 variables with one. ("Might consider" is not the same as "should always").

It's Ok to have one variable used in multiple places as long as the variable always has the same purpose. For example, if ten function calls return an error code, which is handled immediately for each call, use one variable and not 10. But don't use the same variable for completely different things. Like using "name" for a customer name, and 10 lines later using the same variable for a company name, that's bad and will get you into trouble. Worse, using "customerName" for a customer name, and 10 lines later using the same variable "customerName" for a company name.

Importantly, nothing is an iron rule. Everything has advantages and disadvantages. If "best practices" suggests one thing, and you have reasons to say that it's a bad idea in your specific situation, then don't do it.

0

First, look at your development environment. If you have problems debugging because you have five variables in different scopes with identical names, and the debugger doesn't show you which of these variables is the one you need, then don't use five variables with the same name. There are two ways to achieve this: Use one variable, or use five different names.

Your debugger may also make it painful to debug a function with many variables. If a function with 20 variables is harder to debug than one with 16 variables, then you might consider replacing 5 variables with one. ("Might consider" is not the same as "should always").

It's Ok to have one variable used in multiple places as long as the variable always has the same purpose. For example, if ten function calls return an error code, which is handled immediately for each call, use one variable and not 10. There is one problem with this: Usually, the compiler will tell you when you use an uninitialised variable. But here, if you read the error code after call 6, but the variable hasn't actually been changed after call 5, you will get useless data without the compiler warning you. Because the variable has been initialised, with data that is now useless.

Importantly, nothing is an iron rule. Everything has advantages and disadvantages. If "best practices" suggests one thing, and you have reasons to say that it's a bad idea in your specific situation, then don't do it.

-2

Use global variables when you need to maintain a state or store constants. By reusing variables you are only reusing the name that points to a location in memory. Descriptive names on initializations can only win you clarity (Assuming Java and no primitive OCD).

Unless you're into code obfuscation by hand or irritating other developers.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.