web-dev-qa-db-ja.com

(Java)パッケージ編成のベストプラクティスはありますか?

少し前に、Javaパッケージのきめ細かな組織に関する質問に答えました。たとえば、my.project.utilmy.project.factorymy.project.serviceなど。

私は今それを見つけることができないので、質問をすることもできます。

Javaのパッケージの構成に関して、ベストプラクティスはありますか?

Javaプロジェクトでクラスをどのように整理しますか?

たとえば、私が数人で作業しているプロジェクトには、beansというパッケージがあります。単純なBeanを含むプロジェクトから始まりましたが、(ほとんど経験のない)時間をかけて(すべて)を含むプロジェクトになりました。いくつかのファクトリクラスをファクトリパッケージ(Beanを作成する静的メソッドを持つクラス)に入れることで少しクリーンアップしましたが、ビジネスロジックを実行する他のクラスと、取得などの単純な処理(ビジネスロジックではなく)を実行する他のクラスがありますプロパティファイルからのコードのメッセージ。

あなたの考えやコメントを歓迎します。

185
Cyntech

パッケージの編成またはパッケージの構造化は、通常、白熱した議論です。以下に、パッケージの命名と構造化に関するいくつかの簡単なガイドラインを示します。

  • Java パッケージの命名規則 に従ってください
  • 機能的役割とビジネス的役割に応じてパッケージを構成します
    • パッケージを機能またはモジュールに従って分類します。例えばcom.company.product.modulea
    • ソフトウェアのレイヤーに基づいてさらに細分化することもできます。ただし、パッケージに含まれるクラスがわずかしかない場合は、行き過ぎにしないでください。パッケージにすべてを含めることは理にかなっています。例えばcom.company.product.module.webまたはcom.company.product.module.utilなど。
    • 構造化で船外に出ることを避け、差し迫った必要がない限り、IMOは例外、工場などの個別のパッケージングを避けます。
  • プロジェクトが小さい場合は、少数のパッケージでシンプルに保ちます。例えばcom.company.product.modelおよびcom.company.product.utilなど。
  • Apacheプロジェクト で人気のあるオープンソースプロジェクトのいくつかを見てみましょう。さまざまなサイズのプロジェクトで、構造化の使用方法をご覧ください。
  • また、命名時にビルドと配布を検討します(APIまたはSDKを別のパッケージで配布できます。サーブレットAPIを参照してください)

いくつかの実験とトライアルを行った後、自分が満足できる構造を思いつくことができるはずです。 1つの慣習に固執するのではなく、変更に対してオープンになります。

158
naikus

パッケージを整理します機能別。パターンや実装の役割ではありません。私のようなパッケージだと思う:

  • beans
  • factories
  • collections

間違っている。

例えば、私は好む:

  • orders
  • store
  • reports

パッケージの可視性で実装の詳細を隠すことができます。注文のファクトリはordersパッケージに含まれている必要があるため、注文の作成方法の詳細は非表示になっています。

155
onof

簡単な答え:モジュール/機能ごとに1つのパッケージ。サブパッケージがある場合もあります。密接に関連するものを同じパッケージにまとめます。パッケージ間の循環依存を避けます。

長い答え: この記事の大部分に同意します

38
Peter Tseng

レイヤーより前の機能が好きですが、それはプロジェクトに依存していると思います。あなたの力を考慮してください:

  • 依存関係
    特に機能間のパッケージの依存関係を最小限に抑えてください。必要に応じてAPIを抽出します。
  • チーム編成
    一部の組織では、チームが機能に取り組んでおり、他のチームではレイヤーに取り組んでいます。これは、コードの編成方法に影響を与え、それを使用してAPIを形式化するか、協力を促します。
  • 展開とバージョン管理
    すべてをモジュールに入れると、デプロイメントとバージョン管理が簡単になりますが、バグ修正は難しくなります。分割することにより、制御、スケーラビリティ、および可用性が向上します。
  • 変更への対応
    よく整理されたコードは、大きな泥の塊よりも変更がはるかに簡単です。
  • サイズ(人とコードの行)
    大きくするほど、より形式化/標準化する必要があります。
  • 重要度/品質
    一部のコードは他のコードよりも重要です。 APIは実装よりも安定している必要があります。したがって、明確に分離する必要があります。
  • 抽象化レベルとエントリポイント
    コードが何であるか、およびパッケージツリーを見ることからどこから読み始めるかを部外者が知ることが可能であるべきです。

例:

com/company/module
  + feature1/
    - MainClass          // The entry point for exploring
    + api/               // Public interface, used by other features
    + domain/
      - AggregateRoot
      + api/             // Internal API, complements the public, used by web
      + impl/ 
    + persistence/       
    + web/               // presentation layer 
    + services/          // Rest or other remote API 
    + support/            
  + feature2/
  + support/             // Any support or utils used by more than on feature
    + io
    + config
    + persistence
    + web

これは単なる例です。とてもフォーマルです。たとえば、feature1の2つのインターフェイスを定義します。通常、これは必須ではありませんが、別の人が別の方法で使用する場合は良い考えです。内部APIに公開を拡張させることができます。

「impl」または「support」の名前は好きではありませんが、重要度の低いものと重要なもの(ドメインおよびAPI)を区別するのに役立ちます。ネーミングに関しては、できるだけ具体的になることが好きです。 20個のクラスを持つ「utils」というパッケージがある場合、StringUtilsをsupport/stringに、HttpUtilをsupport/httpなどに移動します。

14
ThomasGran

Javaのパッケージの構成に関して、ベストプラクティスはありますか?

本当にありません。たくさんのアイデアと意見がありますが、「ベストプラクティス」は常識を使うことです!

ただし、おそらく広く受け入れられているプリンシパルが1つあります。パッケージ構造は、アプリケーションの(非公式の)モジュール構造を反映する必要があり、モジュール間の循環依存関係を最小限に抑える(または理想的には完全に回避する)ことを目指してください。

(パッケージ/モジュール内のクラス間の循環依存関係は問題ありませんが、パッケージ間サイクルはアプリケーションのアーキテクチャを理解するのを難しくする傾向があり、コードの再利用の障壁になる可能性があります。特に、Mavenを使用すると、パッケージ間/モジュール間の依存関係は、相互接続された混乱全体が1つのMavenアーティファクトでなければならないことを意味します。

また、パッケージ名に関する広く受け入れられているベストプラクティスの1つisを追加する必要があります。そして、パッケージ名は組織のドメイン名から逆順で始まる必要があります。この規則に従えば、(完全な)クラス名が他の人と衝突することによって引き起こされる問題の可能性を減らすことができます。

11
Stephen C

「レイヤーごとのパッケージ」よりも「機能ごとのパッケージ」を宣伝する人がいますが、長年にわたってかなりのアプローチを使用し、「機能ごとのパッケージ」よりも「レイヤーごとのパッケージ」の方がはるかに優れていることがわかりました。

さらに、「機能ごとのパッケージ」の多くの利点があるため、「モジュールごと、レイヤーごと、機能ごとに」というハイブリッド戦略が実際には非常にうまく機能することがわかりました。

  • 再利用可能なフレームワークの作成を促進します(モデルとUIの両方の側面を持つライブラリ)
  • プラグアンドプレイレイヤーの実装を許可します-レイヤー実装をモデルコードと同じパッケージ/ディレクトリに配置するため、「パッケージごとの機能」では実質的に不可能です。
  • さらに多く...

ここで詳細に説明します: Javaパッケージ名の構造と組織 しかし、私の標準のパッケージ構造は次のとおりです。

revdomain.moduleType.moduleName.layer。[layerImpl] .feature.subfeatureN.subfeatureN + 1 ...

どこ:

revdomainリバースドメインcom.mycompany

moduleType[app * | framework | util]

moduleName例:モジュールタイプがアプリの場合はmyAppName、会計フレームワークの場合は「finance」

layer[model | ui | persistence | securityなど、]

layerImpl例:wicket、jsp、jpa、jdo、hibernate(注:レイヤーがモデルの場合は使用されません)

feature例えば、finance

subfeatureN例、会計

subfeatureN + 1例:減価償却

* moduleTypeがアプリケーションの場合、「app」が省略されることもありますが、そこに配置すると、パッケージ構造がすべてのモジュールタイプで一貫します。

6
Volksman

パッケージ編成の標準的な慣行を知りません。私は通常、ある程度広い範囲をカバーするパッケージを作成しますが、プロジェクト内で差別化することができます。たとえば、現在作業中の個人プロジェクトには、カスタマイズされたUIコントロール(swingクラスをサブクラス化するクラスのフル)専用のパッケージがあります。データベース管理用のパッケージ、作成した一連のリスナー/イベント用のパッケージなどがあります。

一方、私は同僚に彼がやったことのほとんどすべてのために新しいパッケージを作成してもらいました。彼が欲しかった異なるMVCにはそれぞれ独自のパッケージがあり、MVCセットが同じパッケージに含まれることが許可されたクラスの唯一のグループであるように見えました。ある時点で、彼には5つの異なるパッケージがあり、それぞれに単一のクラスが含まれていました。彼の方法は極端なものだと思います(そして、チームは彼が単に処理できなかったときにパッケージ数を減らすことを強制しました)が、重要なアプリケーションでは、すべてを同じパッケージに入れます。それは、あなたとあなたのチームメイトが自分で見つけなければならないバランスポイントです。

あなたができることの1つは、あなたがプロジェクトに紹介された新しいメンバーであったか、あなたのプロジェクトがオープンソースまたはAPIとしてリリースされた場合、あなたが望むものを見つけるのはどれくらい簡単/困難ですか?私にとって、それは私がパッケージから本当に欲しいもの、つまり組織だからです。コンピューターのフォルダーにファイルを保存する方法と同様に、ドライブ全体を検索しなくても、それらのファイルを再び見つけることができると期待しています。パッケージ内のすべてのクラスのリストを検索することなく、必要なクラスを見つけることができることを期待しています。

3
Brian S