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


8

ユーザーインターフェイスベースの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アプリケーションのこの側面に関するベストプラクティスは何ですか?確立されたパターンはありますか?


コードの再利用の可能性が比較的低く、インターフェースの複数の実装が必要な場合は、匿名クラスを使用します。これにより、実装ごとに新しいクラスを記述する必要がなくなります。これ
Robert Harvey

@ロバート、匿名クラスに添付されたコードは通常再利用を意図していないという事実を知っています。しかし、それでもこれを実行できるようにしたいと思っていたインスタンスがいくつかありました。たとえば、ButtonとMenuItemが同じコードを実行する必要があるが、わずかな変更を加えて、DRYに違反しない場合。このため、コードをより適切に分離および構造化できる手法を探しています。
ジェローム2014年

それには、匿名クラスを実際のクラスに昇格させます。
Robert Harvey

私の質問で述べたように、これは私が知っている解決策の1つです。ただし、他の手法や、それらが存在する場合のベストプラクティス探しています。ただし、そのようなものが存在せず、匿名クラスを作成するか、実際のクラスを作成するかを選択する必要がある場合、これも有効な回答となる可能性があります。異なるプログラミング言語。DelphiからVisual Studioまで、さらにEiffel [sic]まで、私は常に、結果を達成するために必要なLOCに関して非常に冗長な匿名クラスを使用するJavaの方法を検討しました。
ジェローム2014年

1
これは、Javaが本質的に冗長であるためです。あなたは愚かを修正することはできません。
Robert Harvey

回答:


2

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

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

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


私はあなたの最初の段落に関して完全に同意します。ただし、専用のクラスを作成するのは面倒な場合があります。特に、数行で始まるものが時間とともに大きくなる場合は特にそうです。これまで、親クラスの末尾で誰かがプライベート変数に匿名クラスを割り当てるのを見たことがありませんでした。しかし、小さな専用のクラスをたくさん作成しなくても、コードを構造化することのメリットはわかります。それが悪いスタイルかもしれませんが、それは他にどのようなテクニックが存在するかについての私の質問に部分的に答えます。+1
ジェローム2014年

1

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

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

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

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

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

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

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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.