C またはその他の手続き型プログラミング言語で大規模なアプリケーションを作成することにしたとします。次のような呼び出し依存関係を持つ関数があります。
A
|
+-------------+
| |
B1 B2
| |
+------+ +------+
| | | |
C11 C12 C21 C22
明らかに、リーフ関数 C11、C12、C21、および C22 の単体テストは非常に簡単です。入力をセットアップし、関数を呼び出し、出力をアサートします。
しかし、B1、B2、および A の適切な単体テストを有効にするための適切な戦略は何ですか?
依存性注入B1
は、 (B2
また) 次のように宣言することを示唆していますか?
// Declare B1 with dependency injection for invoking C11 and C12.
int B1(int input, int (*c11)(int), int(*c12)(int));
しかし、呼び出しのレイヤーが多数ある場合、その戦略はスケーラブルではないようです。A
の宣言がどのようになるか想像してみてください。
int A(int input, int (*b1)(int, int (*)(int), int(*)(int)),
int(*b2)(int, int (*)(int), int(*)(int)),
int (*c11)(int),
int (*c12)(int),
int (*c21)(int),
int (*c22)(int));
うん!もっと良い方法があるはずです。
モジュール性とメンテナンスの容易さを促進すると主張する DI やその他の同様のパターンが、実際にはコードの明瞭さを妨げ、単純なコーディングであるべきものを無意味な抽象化と複雑な間接化に複雑化させていると感じることがあります。
Perl や Ruby のような大規模な C のソフトウェア プロジェクトでは、単体テストはどのように処理されますか?