ダックタイピングとは?振る舞いでオブジェクトを判断する
ダックタイピングとは、オブジェクトの適合性を、宣言されたクラスではなく、実際に持つメソッドとプロパティで判断することを意味します。アヒルのように歩き鳴くなら、アヒルとして扱うのです。
PythonやRubyのような動的言語でよく見られるダックタイピングは、同一性より振る舞いを重視します。コードは「このオブジェクトはDuck型か?」とは尋ねません。必要なメソッドを呼び出すだけで、オブジェクトがそれを持つと信頼します。これはコードを柔軟で疎結合にしますが、安全網を完全に実行時とあなたのテストへ移します。
ダックタイピングの背後にある考え
ダックタイピングは、オブジェクトの宣言された型を調べる代わりに、必要な操作をサポートするかを調べます。正しいメソッドを持つオブジェクトなら、そのクラスや継承に関わらず何でも動きます。インターフェースは暗黙的で、コードがたまたま使うものそのものです。
ダックタイピングが便利な理由
- 疎結合: コードは具体的な型ではなく振る舞いに依存する。
- test doubleやmockを含む容易な差し替え。
- 形式的なインターフェースを宣言するよりも少ないボイラープレート。
- 継承階層のない自然なポリモーフィズム。
リスク
契約を事前に検査するものが何もないため、メソッドを欠くオブジェクトを渡すと、そのメソッドが呼ばれる実行時にのみfailします。暗黙のインターフェースは文書化もされていないため、気づかずに壊しやすいのです。
ダックタイピングとテスト
オブジェクトが適合するかを検証するコンパイラがないため、正しいメソッドが存在し正しく振る舞うことを確認する負担をテストが背負います。徹底したテストこそが、ダックタイピングのコードが信頼できるものであり続ける手段です。さもなければエラーは本番でのみ表面化します。
手短な例
obj.read() を呼ぶ関数は、ファイル、ネットワークストリーム、あるいはメモリ内の偽物、つまり read メソッドを持つ何であれ、その型を気にせず動きます。
CIにおけるダックタイピング
ダックタイピングの不一致によるメソッド欠落エラーは、毎回同一にfailする決定論的なバグなので、リトライは役立ちません。Latchkeyは一時的なインフラ障害のみを自動でリトライし、本物のダックタイピングのエラーは修正されるよう見えたままにします。
重要なポイント
- ダックタイピングはオブジェクトを、宣言された型ではなく持つメソッドで判断する。
- 柔軟で疎結合だが、あらゆる検査を実行時とテストへ先送りする。
- メソッド欠落エラーは決定論的なバグであり、リトライすべき一時的な障害ではない。