1

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

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 }指针了。也很麻烦,(并且定义指针的开销可以忽略不计,即使我非常非常频繁地调用该函数,对吗?)
4

3 回答 3

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,以及短函数的其他各种好处。

于 2012-09-17T16:57:44.730 回答
1

我有几个想法

  1. 如果您的编辑器支持它们,您可以使用片段或移至支持它们的编辑器/ide(我个人使用 kdevelop 和片段非常有用,因为它们替换了片段变量的所有出现)
  2. 您还可以使用重构(如果您已经使用了这个名称,则在单独的函数中)
  3. 还选择一段代码并在选择中全部替换可能会有所帮助
  4. 使用定义也是一种选择

不过,在我看来,使用更智能的 IDE 是最好的。

于 2012-09-17T16:48:57.253 回答
0

我认为您最好的选择是在其他类中没有类似的函数名称。此外,将单元测试与同行代码审查相结合应该在大多数情况下发现这些错误。然而,在 SW 历史上,这些类型的错误在很多天、几个月或几年后才被发现。

于 2012-09-17T16:48:49.733 回答