0

レガシー コードの大部分を維持する一環として、主にテスト (単体テスト) を容易にするために、設計の一部を変更する必要があります。解決する必要がある問題の 1 つは、コンポーネント間の既存のインターフェイスです。2 つのコンポーネント間のインターフェイスは、静的メソッドのみを含むクラスです。

簡単な例:

class ABInterface {

    static methodA();
    static methodB();
    ...
    static methodZ();
};

インターフェイスはコンポーネント A によって使用されるため、さまざまなメソッドが ABInterface::methodA() を使用して入力データを準備し、コンポーネント B 内の適切な関数を呼び出すことができます。

現在、さまざまな理由から、このインターフェイスを再設計しようとしています。

  • 単体テストの範囲を拡張する - コンポーネント間のこの依存関係を解決する必要があり、スタブ/モックが導入されます

  • これらのコンポーネント間のインターフェースは、元の設計から分岐しました (つまり、コンポーネント間の i/f に使用される多くの新しい関数が、このインターフェース クラスの外で作成されます)。

  • コードは古く、時間の経過とともに大幅に変更されたため、リファクタリングが必要です。

この変更は、システムの残りの部分に影響を与えるものであってはなりません。テストに必要な多くのアーティファクトを本番コードに残すことを制限しようとしています。パフォーマンスは非常に重要であり、再設計後の低下はまったくない (またはごくわずかである) 必要があります。コードは C++ で OO です。

どのようなアプローチを取るべきか、いくつかのアイデアを探しています。これを効率的に行う方法について何か提案はありますか?

4

3 に答える 3

1

最も簡単な答えは、静的インターフェイスを持つ古いライブラリをファサードにラップし、古いライブラリの代わりに新しいファサードを呼び出すようにコードをリファクタリングすることです。この新しいウェッジにより、単体テストの目的でライブラリを置き換えることができます。最初に単一のメソッドでテストして、実装方法を確認してください。

本当に気になるのは、質問が「パフォーマンスの問題」で汚染されている場合です。私たちは皆、パフォーマンスが重要なコードを書いたことがありますが、パフォーマンスの低いコードを書くことを意図的に提案する人は誰もいません。これらの「懸念」は通常、すべての変更を非難する否定論者から来ており、特定の変更がうまく機能するかどうかについての手がかりがありません. パフォーマンスの唯一の有効な証拠はテストから得られることを忘れないでください。パフォーマンス テストを実行し、ベースラインを確立します。変更を加えます。新しいコードでパフォーマンス テストを再度実行します。実際の影響を示します。そうして初めて、変更の実際の影響について決定を下すことができます。別の方法で示されるまで、サイクルに関する小言が設計を支配することを決して許可しないでください。

あなたのプロジェクトで重要な人物は古い C プログラマー* のようです。彼は昔、「C++ を高速に実行する唯一の方法は静的メソッドを使用することです」などと大声で言っているのを聞いたことがあります。問題は、彼がまだそれを信じていることです。20 年前の騒ぎは正しかったかもしれませんが、コンパイラとオプティマイザはこの 20 年間で大幅に改善されました。だからあなたの変更を試してみてください。

最新のコンパイラを使用している場合、オプティマイザがオブジェクト コード内の余分な逆参照を削除する可能性は十分にあります。つまり、実行時の影響がまったく追加されないということです。

また、パフォーマンスが非常に重要であるにもかかわらず、パフォーマンス テストを行っていない場合、または最新のコンパイラを使用していない場合、またはすべてのリリース ビルドの最適化を調整していない場合 (たとえば、プロファイル ガイド付き最適化を使用)次に、抽象化の余分なレイヤーのパフォーマンスを心配する前に、はるかに大きなエンジニアリングの問題に対処する必要があります。

  • 注: 私も 20 年前にそのような愚かなことを言っていた古い C プログラマーです。違いは、一部の最適化が他の最適化よりもはるかに重要であること、および新しいコンパイラがほとんどのものを自分で理解するのに驚くほど優れていることを学んだことです。物事を時期尚早に「最適化」しようとする私の試みは、通常、いずれにせよストック コンパイラの設定よりも優れたパフォーマンスを発揮しないコードを維持するのに費用がかかります。
于 2010-06-05T06:11:31.333 に答える
0

メソッドA〜Zが非静的で仮想である場合、これを簡単に行うことができますか?したがって、静的なmethodA-Zが非静的な仮想のmethodA-Zを呼び出す場合、動作をオーバーライドできます。これを知っていると、テスト用に非静的バージョンを含むインスタンスを変更する方法が必要になります。

または、リファクタリングする2つのクラスを取得して、この静的のみのクラスのラッパーを使用するようにすることもできます。その後、2つは必要なだけ分岐することができます。

それは本当の問題を見ずに私の考えのすべてについてです。

于 2010-06-03T15:56:20.383 に答える
0

回答とコメントをありがとう。

『レガシー コードを効果的に使用する』の「依存関係を破る手法」の章を確認した後、次の 2 つの手法を組み合わせることで、実際に問題を解決できるようです。

  • Instance Delegator - ユーティリティ クラスの静的メソッドを新しい仮想メソッドでラップ/置換します。
  • Static Setter - 異なるユーティリティ クラス (プロダクション コードまたはスタブ コード) のインスタンス化を有効にします。

これら 2 つを組み合わせることで、テスト対象のコンポーネントを残りの製品コードから切り離すことができます。

現在の唯一の懸念事項は、(仮想関数の使用による) パフォーマンスへの影響です。

于 2010-06-04T06:34:48.120 に答える