9

以前に見たパターンに出くわしたので、それについて意見を求めたいと思いました。問題のコードには、次のようなインターフェースが含まれます。

public interface MyCrazyAnalyzer {
    public void setOptions(AnalyzerOptions options);
    public void setText(String text);
    public void initialize();
    public int getOccurances(String query);
}

そして、予想される使用法は次のようになります。

MyCrazyAnalyzer crazy = AnalyzerFactory.getAnalyzer();
crazy.setOptions(true);
crazy.initialize();
Map<String, Integer> results = new HashMap<String, Integer>();
for(String item : items) {
    crazy.setText(item);
    results.put(item, crazy.getOccurances);
}

これにはいくつかの理由があります。setText(...) と getOc​​curances(...) が存在するのは、データに対して同じ高価な分析を行った後に実行したいクエリが複数あるためですが、これは結果クラスにリファクタリングできます。

これが悪いと思う理由: 実装は、インターフェイスによって明確に示されていない方法で状態を保存しています。また、「prepareResult」を呼び出してから「getResult」を呼び出す必要があるインターフェースを含む同様のものを見てきました。さて、これらの機能のいくつかを採用した、適切に設計されたコードを思いつくことができます。Hadoop Mapper インターフェースは、JobConfigurable と Closeable を拡張しますが、これらのインターフェースを実装するユーザー コードを使用するフレームワークであるのに対し、複数の実装を持つ可能性のあるサービスであるため、大きな違いが見られます。呼び出す必要がある「close」メソッドを含めることに関連するものはすべて正当化されると思います。これを行うための合理的な方法は他にないからです。JDBC のように、これは漏れやすい抽象化の結果である場合もありますが、私が考えている 2 つのコードでは、

私の質問は次のとおりです。

  1. 誰もがこれが貧弱に設計されたインターフェースであることに同意しますか?
  2. これは記述されたアンチパターンですか?
  3. この種の初期化はインターフェイスに属しますか?
  4. 私は機能的なスタイルと不変性を好むので、これは私には間違っているように思えますか?

これが名前に値するほど一般的である場合は、インターフェイスが本質的にステートフルではない場合 (コレクションのように)、特定の順序で複数のメソッドを呼び出すことを強制するインターフェイスの「シークレット ハンドシェイク」アンチ パターンをお勧めします。

4

5 に答える 5

18

はい、それはアンチパターンです:シーケンシャルカップリング

私はリファクタリングしますOptions-ファクトリに渡され、メソッドResultsから返されます。analyseText()

于 2009-04-27T09:18:07.870 に答える
3

これが説明されているアンチパターンかどうかはわかりませんが、これは設計が不十分なインターフェースであることに完全に同意します。エラーが発生する可能性が非常に高く、少なくとも 1 つの重要な原則に違反しています。それは、API を誤用しにくくすることです。

誤用に加えて、この API は、複数のスレッドが同じインスタンスを使用する場合、デバッグが困難なエラーにつながる可能性もあります。

Joshua Blochは、実際に API 設計に関する優れたプレゼンテーション(36 分 16 秒と 40 分 30 秒) を行っており、これを不十分に設計された API の特徴の 1 つとして取り上げています。

于 2009-04-27T08:36:30.687 に答える
0

ここに悪いものは何も見えません。setText()ステージを準備します。その後、 への呼び出しが 1 つ以上ありますgetOccurances()。コストがかかるのでsetText()、これ以外に方法が思い浮かびません。

getOccurances(text, query)途方もないパフォーマンスコストで「シークレットハンドシェイク」を修正します。テキストをキャッシュして、テキストが変更されたときにのみ内部キャッシュを更新することもできgetOccurances()ますが、それはオブジェクト指向の原則への犠牲のように見え始めます。ルールが意味をなさない場合は、適用しないでください。ソフトウェア開発者には理由があります。

于 2009-04-27T09:11:41.270 に答える