私見ですが、変数やメソッドに一貫した方法で名前を付けるなど、いくつかの規則に従うと、ダックタイピングの利点がさらに大きくなります。ケンGの例をとると、私はそれが最もよく読めると思います:
class SimpleResults {
def mapOfListResults
def total
def categories
}
「calculateRating(A、B)」という名前の操作でコントラクトを定義するとします。ここで、AとBは別のコントラクトに準拠しています。擬似コードでは、次のようになります。
Long calculateRating(A someObj, B, otherObj) {
//some fake algorithm here:
if(someObj.doStuff('foo') > otherObj.doStuff('bar')) return someObj.calcRating());
else return otherObj.calcRating();
}
これをJavaで実装する場合は、AとBの両方が次のようなインターフェイスを実装する必要があります。
public interface MyService {
public int doStuff(String input);
}
さらに、評価を計算するための契約を一般化したい場合(たとえば、評価計算のための別のアルゴリズムがある場合)、インターフェイスも作成する必要があります。
public long calculateRating(MyService A, MyServiceB);
ダックタイピングを使用すると、インターフェイスを捨てて、ランタイムに依存するだけで、AとBの両方がdoStuff()
呼び出しに正しく応答します。特定の契約定義は必要ありません。これはあなたのために働くことができますが、あなたに対しても働くことができます。
欠点は、他の人がコードを変更したときにコードが壊れないようにするために、特に注意する必要があることです(つまり、他の人はメソッド名と引数の暗黙のコントラクトを認識している必要があります)。
これは特にJavaで悪化することに注意してください。この場合、構文は(たとえばScalaと比較して)それほど簡潔ではありません。これの反例はLiftフレームワークであり、フレームワークのSLOCカウントはRailsに似ていると言われていますが、テスト内で型チェックを実装する必要がないため、テストコードの行数は少なくなっています。