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」という名前の 2 つの類似した変数で作業する必要があります。

それぞれのコードは似ているため、「A」で機能したコードを「B」で機能するコードの「テンプレート」として使用することがよくあります (つまり、コピー & ペースト)。 Bにふさわしい。

私は人間なので、コードをコピーするときに特定の場所で「A」を「B」に変更するのを忘れることがあります。運が良ければ、これによりプログラムがクラッシュします。いずれにせよ、これは悲惨です。

そのようなタイプミスを防ぐための巧妙なトリックを知っている人はいますか?

考えてみた...

  • 括弧{ }を囲んで変数のスコープを制限しようとしますが、オブジェクト A と B が関数の引数にある場合、これは解決しません。
  • すべての関数をサブ関数に分割します。1 つは A 用、もう 1 つは 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.
}

あるいは、2 種類の「もの」の間の関係を明確にすることもできます。Bコード内の一致しない括弧がA. すべては、見た目が似ている 2 つの操作の間に論理的な関係があるかどうかにかかっています。

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 に答える