理論的には、お互いを強く認識して使用するクラスは、(packageを使用して、他のクラスで使用されていない関数の可視性を同じパッケージに含める必要がありますしたがって、簡潔で理解しやすいインターフェースを形成します。 [よく知られているクラス(ロガーなど、ほとんどどこからでもアクセスできる)は、独自のパッケージに移動し、utils
と呼ぶ必要があります。]
コードベース 数百のJavaファイル、約6ダース以上のパッケージをかなり自由に配布し、ほとんどのメソッドがpublic
と宣言されている(一部のprivate
ones)、そしてクラス間の関係は不明瞭です(重要な場合、メソッドはJSFインフラストラクチャから呼び出されるため、明確なエントリポイントもありません。いくつかのmain()
メソッドがあるかもしれませんが、通常未使用)
このような大規模なJavaクラスのセットをパッケージにグループ化するためにクラスタリングアプローチを適用することについて誰かが考えたことはありますか?クラス間の関係の強さを次のように概説することは、これが可能かどうか、またどのようにして可能になるのでしょうか。手動でのクリーンアップ、またはコードを何らかの方法で自動的に再編成するのに役立ちます。
距離の測定には、public
の宣言に必要な関数の数、およびコードに必要なパッケージimport
ステートメント(.*
で終わるステートメント)の数が含まれる場合があります。コンパイルする。その質問に対するアルゴリズム的に「最良の」答えは、すべてのクラスを1つのパッケージに含めることです(anyパブリックメソッドを必要としないか、これ以上インポートしません)。私が望むものではありません)、階層的クラスタリングアプローチが最良であるように思われますが(パッケージの最終的な粒度を人間の決定として残します)、おそらく私が知らないより良いアプローチがあるでしょう。
そのトピックに関する情報を見つけようとしましたが、「Java」と「クラスタリング」を検索すると、Javaでのクラスタリング実装の方法を説明するページにたどり着きましたが、これは私が探しているものではありません。 (もちろん、イントロスペクションを使用して実現できるため、Javaでもアプローチを実装できます。しかし、それは私の質問にとって重要ではありません。)
このような大量のJavaクラスのセットをパッケージにグループ化するために、クラスタリングアプローチを適用することについて誰かが考えたことはありますか?
はい、それは数年前のソフトウェア(リ)エンジニアリング(より具体的にはソフトウェアの再構築)の研究でホットなトピックであり、フローネットワークカッティングアルゴリズム(構造的観点と行動的観点の両方)と他のいくつかのアプローチがあります。
いくつかの参考文献、実際にはこのトピックに関する多くの研究論文があります:
距離/類似性の他の概念も考慮されています。たとえば、同じコミットで頻繁に変更されるモジュール(クラスなど)は、時間とともに共進化する傾向があるため、互いに「近い」と見なすことができます。したがって、これらの「類似した」モジュールのクラスターを決定すると、忘れられた共進化のニーズを回避し(クラスを変更し、その関連クラスを変更するのを忘れた)、モジュール間の暗黙的な(そしておそらく望ましくない)関係を強調できます。
私は実際にこの正確なトピックについて考えました。私が蹴ったアイデアは:
public void doWorkWith(ClassB b, ClassC c)
を使用すると、2つの有向エッジがグラフに追加されます。また、オンラインでざっと目を通したときに、このトピックに関する情報はほとんど見つかりませんでした。とはいえ、本 Robert Martinによるアジャイルソフトウェア開発 はこのトピックについて説明しています。
これを実装しなかったのは、次の理由によります。(1)多くの作業が必要であり、(2)この方法で分析する必要のあるプロジェクトでは、グラフを「完全に分離」するのが難しい、ひどく混ざり合ったグラフになることに、多額の資金を投じます。その結果、より多くの依存性注入を使用するようにプロジェクトをリファクタリングすることに集中しました。
編集用に追加:すばやく簡単なことの1つは、インポート文の数を数えることです。大まかに言えば、何億ものインポートステートメントで始まるクラスは、改善努力の主要なターゲットです。残念ながら、これらはおそらく最も危険なクラスです。
私は、パッケージ間の依存関係を最小限に抑えるためにクラスをパッケージに分離することが最善であるという基本的な仮定に同意しません。その極端なヒューリスティックに続いて、すべてのクラスが同じパッケージに含まれることになり、これは明らかにメンテナンスの悪夢です。しかし、そのような不条理な議論を使用しなくても、クラスがどこにあるべきかを決定する上で最も重要な要素は、それがチームのプログラマーがどこにあるべきかを推測できるように、パッケージに論理的に適合することです。あります。
依存関係を最小限に抑えることは良いことですが、ファサードや依存関係の逆転などの手法を、クライアントとサーバーが一緒になるようにコードを移動するのではなく、これを実現する主要な方法として使用する必要があります。