web-dev-qa-db-ja.com

UIアプリケーションの匿名クラスに関するベストプラクティス

ユーザーインターフェイスベースのJavaプログラムを使用する場合、特定のアクションに動作を関連付ける1つの方法(例:ボタンのクリック))は匿名クラスの使用によるものです。以下の例では、GUIフレームワークはSWTですが、SwingまたはAndroid UIコンポーネント)で同じ問題があります。つまり、プログラムの構造化です。

MenuItem sampleMenuItem = new MenuItem(popupMenu, SWT.NONE);
sampleMenuItem.addSelectionListener(new SelectionAdapter() {
    public void widgetSelected(SelectionEvent event) {
         doSomething();

         // handle all table entries
         for (int i=0; i<10; i++) {
             doSomething2();
         }

         doSomething3();
         doSomething4();
    }
});

もちろん、上のサンプルのコードの量は、ロジックを含む専用クラスの作成をすでに保証していると主張する人もいます。これは、Sonarの"匿名クラスは行が多すぎてはいけません"ルールによっても示唆されています。

興味深いことに、このルールは次のことも指定しています。

squid:S1188-Javaでのクロージャーのサポートを待つ間、匿名クラスは、専用クラスを作成せずに動作を注入するための最も便利な方法です。ただし、これらの匿名の内部クラスは、動作が数行で実行できる場合にのみ使用してください。より複雑なコードでは、名前付きクラスが必要です。

しかし、クロージャはまだJavaに到着していないため、私の質問は、よりエレガントな解決策があるかどうかです

  • あらゆる種類の欠点がある匿名クラス内でコードの束を書く(再利用が制限され、コード内の移動が遅くなる...)
  • それ自体が非常に限られた機能しか持たない可能性がある膨大な数の専用クラスを作成する(つまり:過剰エンジニアリング、...)

質問を拡張するには:Javaのこの側面に関するベストプラクティスを教えてください。ベースのUIアプリケーション?確立されたパターンはありますか?

8
Jérôme

私が見た唯一のパターンは、「コードが何が起こっているのか理解するのが困難になったときに、匿名クラスの使用をやめるときです」です。

あなたの例では、メソッド本体は匿名クラスです。 「new SelectionAdapter」をそれ自体の行に移動して、開始括弧をもう少しはっきりさせることができますが、それ以外の場合は問題ありません。問題が発生するのは、ランダムな人が匿名クラスとメソッドコードの場所を把握できなくなった場合です。

また、匿名クラスを保持するプライベート変数またはメソッドも作成しました。そんなことはクラスの一番下に置いておきます。それはちょっと新しいクラス間のギャップを埋め、コードの真ん中にそれを保ちます。一部の人はそれを悪いスタイルだと考えていますが、私の一般的な経験則は、最初に読みやすさのためにコーディングすることです。

2
Jim Barrows

匿名の内部クラスは、純粋に文体的なものです。それらは、コンパイル中に作成される.classファイルのレベルの包含クラス内には存在しません。すべての匿名内部クラスは、最上位クラスとして作成されたかのように、別個の.classファイルを作成します。

これは、出力ディレクトリ(通常は「out」という名前)に移動し、名前で内部クラスを探すとわかります。内部クラス用の別のクラスファイルが表示されます。私が覚えているように、その名前はOuterClassName $ InnerClassName.classです。匿名の内部クラス(自分で記述しなくても作成される)のコンストラクターには、 "this"への参照が渡されます。これはもちろん、外部クラスを含んでいます。

したがって、「多くのクラスを作成する」ことについての懸念に基づいて決定を行わないでください。それは純粋に文体的なものです。

Javaを開始したとき、可変クラスメソッドメソッドのようなクラスのリズムに違反したという理由だけで、匿名クラスは私にとって大きな混乱のように見えました。実際、彼らはまだ私を穏やかに苛立たせています。

それらの想定される利点は、コードの理解を容易にすることです。匿名の内部クラスのメソッドが何を行うかを確認するために他のファイルに移動する必要はありません。しかし、それだけです。

したがって、決定はスタイル上の決定であり、それ以上のものではありません。気に入った場合は使用し、そうでない場合は使用しないでください。

すぐにこれを追加したかったのですが、専用クラス内に限られた機能(たとえば、1つの短いメソッド)を含めることは、過剰なエンジニアリングを構成するという考えを再検討するかもしれません。クラスは、少なくともJavaでは、結束の単位です。オーバーエンジニアリングは、クラスごとのメソッドやクラス数でさえ測定されません。 O Eはこれらの両方に完全に直交しています。