cmo
cmo

Reputation: 4114

good practice - similarly named variables

Trivial issue, but comes up a lot for me, and I imagine others too. Does anybody have a really good, really clever solution?

void some_function (obj &A, obj &B)
{
// do stuff with A...
//e.g.
double number_A = (value - A.member_func() ) * A.other_func();


// do stuff with B.  similar BUT NOT EXACTLY like A...
//e.g.
double number_B = (value + B.member_func()  )   *   A.other_func();  
  // !!!!
  // Big time TYPO  -   should say "B.other_func()", not "A.other_func()" !!!!   
  // !!!!
}

Any good guards against these types of errors?

I often have to work on two analogous variables, say one named version "A" and the other "B".

Because the code for each one is similar, I often use the code that worked on "A" as a "template" (i.e. copy & paste) for the code that works on "B" - making the small adjustments so that the code becomes appropriate for B.

Becuase I am human, I sometimes forget to change "A" to "B" in certain locations when copying the code. If I am lucky, this will cause the program to crash. Either way, this is disastrous.

Does anybody know any clever tricks for preventing such typos?

I've thought of...

Upvotes: 1

Views: 166

Answers (3)

Steve Jessop
Steve Jessop

Reputation: 279405

In the example you give, the best defence is to do as little as possible in each function:

void some_function (obj &A, obj &B)
{
    double number_A = do_stuff(A);
    double number_B = do_similar_stuff(B);
}

double do_stuff(obj &A) {
    return (value - A.member_func() ) * A.other_func();
}

// EITHER
double do_similar_stuff(obj &A) {
    // no variable rename when copying == no problem
    return value + A.member_func()  )   *   A.other_func();
}
// OR
double do_similar_stuff(obj &B) {
    // A not in scope == very brief problem until compiler tells us
    return value + B.member_func()  )   *   A.other_func();
    // Beware, also, the nightmare scenario that there's some *other* 
    // `A` in scope, so this *still* compiles. For that reason, prefer
    // the other option unless there's some good reason why this parameter 
    // should be `B`, and don't name member function parameters the same 
    // as data members etc.
}

Alternatively, you could make the relation between the two kinds of "stuff" explicit. Assuming that the unmatched parenthesis in your B code is supposed to go in the same place as the A. It all depends whether there really is a logical relationship between the two similar-looking operations:

void some_function (obj &A, obj &B)
{
    double number_A = do_stuff(A, true);
    double number_B = do_stuff(B, false);
}

double do_stuff(obj &A, bool subtract) {
    // yeah, never call variables "tmp". Unless you have no context
    // to give them meaning.
    // Depending on the type of `tmp`, there might be a better way to
    // write this, using multiplication by -1. But let's not assume, we'll do
    // one refactor at a time.
    auto tmp = subtract ? value - A.member_func() : value + A.member_func();
    return tmp * A.other_func();
}

Other examples will vary. As you say it can be tiresome to write, but it has a number of benefits other than catching this error. Not least is that it will direct you towards writing your code in a way that you try to avoid passing/returning many variables. As a consequence, each line of your code affects fewer other things in the program, which is basic code hygiene.

It may also mean you can test that your formula with A is correct independently of whether your formula with B is correct, and sundry other benefits of short functions.

Upvotes: 6

xception
xception

Reputation: 4297

I have a few ideas in mind

  1. you could use snippets if your editor supports them or move to an editor/ide which has support for them (personally I use kdevelop and snippets are very useful as they replace all occurences of a snippet variable)
  2. you could also use refactoring (in a separate function if you already used the names this one)
  3. also selecting a piece of code and doing replace all in selection might help
  4. using defines is also an option

Still, going with a smarter IDE is the best in my opinion.

Upvotes: 1

user195488
user195488

Reputation:

I think your best bet is not have similar function names in other classes. Also, having unit tests coupled with peer code reviews should catch these errors most of the time. However, there have been many times in SW history where these types of errors are never caught until many days, months, or years later.

Upvotes: 0

Related Questions