4

私は、Java で「漏れやすい抽象化」をチェックするプログラムを作成するという考えを熟考しています。すぐに頭に浮かんだ 1 つの領域は、例外があります。

public class X
{
    // this one is fine, Readers throw IOExceptions so it is 
    // reasonable for the caller to handle it
    public void parse(final Reader r)
        throws IOException
    {
    }

    // This one is bad.  Nothing in the API indicate that JDBC 
    // is being used at all.
    public void process()
        throws SQLException
    {       
    }
}

注意してください、私はチェックされた/チェックされていない例外の相対的なメリットについて議論したくありません. 私が探しているのは、他の例 (例外処理である必要はありません) であり、ソース コードまたはクラス ファイルを調べることで合理的に把握できるものです。

私はcheckstyle、findbugs、およびPMDを認識していますが、知る限り、これを扱っているものはありません(そして、自分で作成するのではなく、これらのツールのいずれかにチェックを入れることに反対していません)。

静的にチェックできる漏れやすい抽象化の他の例はありますか?

編集:

2 番目の方法が悪い理由は、クライアントが JDBC (たとえば、何でもかまいません) が使用されていることを知る方法がない場合に、メソッドが例外をスローすることです。したがって、「漏れやすい抽象化」は、JDBC が使用されていることです。基礎となるメカニズムが別のものに変更された場合 (別のデータベース抽象化ライブラリである JPA など)、例外もすべて変更する必要があります。そのため、基盤となるデータベース ライブラリが流出しています。

4

4 に答える 4

2

元の投稿で質問を検出できなかったので、とりとめのない質問をします。

そのようなツールは、特定のクラスの非リークと見なされる例外をユーザーに通知させる必要があり、そのようなリストにないものはすべてリークになります。

それはただの例外です。私が理解しているように、漏れやすい抽象化はさらに多くのことに適用されます。このことを考慮:

class Client
{
    private Integer ID;

    public Integer ID() { return this.ID; }
}

これはリークに該当しますか?後でIDをLongとして表す必要がある場合は、そうします。このようなシナリオを次のように修正できます。

class Client
{
    private ClientID ID;

    public ClientID ID() { return this.ID; }
}

class ClientID
{
    private Integer value;

    public ClientID(String id) { this.value = Integer.parseInt(id); }

    public String asString() { return value.toString(); }

    ... other methods that don't reveal value's type here ...
}

これで Client からのリークは解決されますが、今度は ClientID でツールを実行することになります。漏れやすいですか?

単純なゲッターではないメソッドを調べる必要がある場合、これはさらに複雑になる可能性があります。ClientID に、その ID に対して何らかの数学的演算を実行し (私を満足させてください)、整数を返すメソッドがあったとしたらどうでしょう。それは漏れですか?これは、その値が整数であることを漏らしていると見なされますか?

したがって、これがマシンが簡単に検出できるコードの匂いかどうかはわかりません。

于 2009-02-24T03:32:44.973 に答える
2

そう。

API が実装の詳細をリークしているか、同じレベルの抽象化を維持していないかを検出する方法。

あなたはおそらくこのトークを見るかもしれません。優れた API がどのように見え、どのように設計されているかを説明しています (優れたプラクティスから悪いプラクティスを差し引くことができます)。

例えば

機能は簡単に説明できる必要があります。難しい名前の場合、それは一般的に悪いデザインです。

そのことから、メソッドまたは戻りパラメーターが詳細な指示を与える場合、それらは抽象化のレベルに沿っていないことがわかります。

たとえば、高レベルのメソッド

 -initProcess(): SGN_MTL

戻り値の実装の詳細が漏れている可能性があります。

ここで難しいのは、抽象化のレベルがいつ変化したかを検出することです。

たとえば、メソッドで、コード自体が JDCB レイヤーの実装である場合、SQLExceptions をスローしても問題ありません。

これらのトピックをさらに見ることができる他のソースは、このリストです。 http://www.jetbrains.com/idea/documentation/inspections.jsp

「抽象化」の下の項目を参照してください。

  • 具象クラスのインスタンス変数: インスタンス変数の型がインターフェイスではなく具象クラスとして宣言されている場合に報告します。

古典的な例は次のとおりです。

 private ArrayList list;

いつ良くなるか

 private List list;
于 2009-02-24T04:11:26.657 に答える
0

別のものの考え。非公開タイプを扱う公開メンバーを持つ。

class Foo{...}//パッケージに対してローカル

パブリッククラスバー
{{
    クラスCar(){...}

    public Bar(Foo f){...}

    public Car star(){...}
}

バーとスターは漏れやすいでしょう。Barコンストラクターbを見ることができますが、Barクラスと同じパッケージ内からのみ呼び出すことができます。starメソッドを呼び出すことはできますが、戻り値はオブジェクトとしてのみ使用できます。

これらの両方について、メンバーをプライベートまたはパッケージアクセスにするか、タイプをパブリックにすることを検討する必要があることがわかります。

于 2009-02-24T20:05:58.020 に答える
0

Liskov Substitution Principleへの違反をチェックするために例を拡張することを検討できます。インターフェースを実装するクラスは、インターフェースによって定義されたのと同じ例外のみをスローするべきだと言う人もいます。

オブジェクトの使用法を分析できる場合は、より一般的な型を使用できることを提案することをお勧めします (たとえば、メソッドには IDBConnection が必要な場合に SQLConnection が必要です)。

于 2009-02-24T02:48:58.480 に答える