良好做法 - 同样命名的变量

时间:2012-09-17 16:41:15

标签: c++

琐碎的问题,但对我来说很多,我也想象其他人。有没有人有一个非常好的,非常聪明的解决方案?

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()" !!!!   
  // !!!!
}

对这些类型的错误有什么好的防范?

我经常要处理两个类似的变量,比如一个名为“A”,另一个名为“B”。

因为每个代码的代码类似,我经常使用“A”代码作为“模板”(即复制和粘贴)代码,用于处理“B”的代码 - 进行小的调整代码变得适合B。

因为我是人,在复制代码时,我有时会忘记在某些位置将“A”改为“B”。如果我很幸运,这将导致程序崩溃。无论哪种方式,这都是灾难性的。

有没有人知道任何防止此类拼写错误的聪明伎俩?

我想过......

  • 用括号{ }括起来试图限制变量的范围 - 但如果对象A和B在函数参数中,那么这就不能解决它。
  • 将每个函数划分为子函数 - 一个用于A,一个用于B.从开发人员的角度来看,这有点麻烦(传递/返回许多变量)。
  • 仅使用指针处理对象本身 - 而不是实际对象。这样我们可以{ scope-control }指针。同样繁琐,(定义指针的开销可以忽略不计,即使我非常经常地调用函数,对吧?)

3 个答案:

答案 0 :(得分:6)

在你给出的例子中,最好的防御是在每个函数中尽可能少地做:

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.
}

或者,您可以将两种“东西”之间的关系明确化。假设B代码中不匹配的括号应该与A位于同一位置。这完全取决于两个看似相似的操作之间是否存在逻辑关系:

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();
}

其他例子会有所不同。正如你所说,编写它可能很烦人,但除了捕获此错误之外,它还有许多其他好处。尤其是它会指导您以一种尝试避免传递/返回许多变量的方式编写代码。因此,代码的每一行都会影响程序中较少的其他内容,这是基本的代码卫生。

这也可能意味着您可以测试A的公式是否正确,与B的公式是否正确以及短函数的其他好处无关。

答案 1 :(得分:1)

我有一些想法

  1. 如果您的编辑支持它们或者转移到支持它们的编辑器/ ide,您可以使用片段(我个人使用kdevelop和片段非常有用,因为它们替换了片段变量的所有出现)
  2. 您也可以使用重构(如果您使用单独的功能) 已经使用了这个名称)
  3. 还选择一段代码并在选择中替换所有代码 可能会有所帮助
  4. 使用define也是一个选项
  5. 但是,在我看来,使用更智能的IDE是最好的。

答案 2 :(得分:0)

我认为你最好的选择是在其他课程中没有类似的功能名称。此外,单元测试与同行代码评审相结合应该能够及时发现大多数的错误。然而,在SW历史中已经多次出现这些类型的错误,直到很多天,几个月或几年之后才会被捕获。