(Java)パッケージ編成のベストプラクティスはありますか?[閉まっている]


201

少し前に、Javaパッケージのきめの細かい構成に関して、ここで答えられる質問を見ました。たとえば、my.project.utilmy.project.factorymy.project.service、など

今は見つからないので、質問してもいいです。

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

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

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

ご意見、ご感想をお待ちしております。


74
この質問の締めくくりには同意しません。ベストプラクティスの質問がほとんど常に経験と意見に基づいていることに異論はありませんが、これらの質問はスタックオーバーフローで閉じる必要があることに異論があります。これは優れたプログラミングの核心であり、ベストプラクティスを使用し、これらの意見や経験を使用して最適なソリューションを見つけます。この質問をもう一度開いてください。
Cyntech 2015

これを読むことをお勧めします: satisfice.com/blog/archives/5164。TL; DR ...「ベストプラクティス」の概念全体が壊れています。せいぜい、それは悪質な誤称であり、最悪の場合、まったく有害です。
スティーブンC

回答:


174

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

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

数回の実験と試行の後、使いやすい構造を考え出すことができるはずです。1つの慣習に固執するのではなく、変更を受け入れるようにしてください。


御返答いただき有難うございます。これは主に私たちが取り込もうとしたものですが、無関係なコードの多くがBeansパッケージに取り込まれました。
Cyntech

2
機能別パッケージが最も理にかなっていることに同意します。私はかつて会社のオフィス構造に関連した素晴らしいアナロジーを聞きました。階層化されたアプローチでは、会社のレベルごとに各個人が互いに座ります。つまり、役員、マネージャー、管理者、従業員/労働者はすべて、建物の別々のセクションに座っています。この構造は、「機能」編成アプローチほど効果的ではない可能性があります。つまり、セールスエグゼクティブが、すべてセールスアドミンと一緒に座っているセールス従業員と一緒に座っているセールスマネージャーと一緒に座っている場合。これにより、このように編成した場合に、部門間の結合が強化されます。
アレックス

ポイントに同意します。会社が取得した製品が販売されることがあるパッケージの会社名について強調するための1つのポイント。経営者は会社名を削除したい。それはオーバーヘッドになる可能性があります。
Tushar D

183

パッケージは、パターンや実装の役割ではなく、機能ごとに整理しています。私はパッケージが好きだと思います:

  • beans
  • factories
  • collections

間違っている。

たとえば、私は好む:

  • orders
  • store
  • reports

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


10
この投稿は、パッケージの可視性について良い点を示しています。Javaパッケージのスコープが使用されているのを見たことがありませんが、適切なパッケージ構造により、開発者はそれをよりよく活用できます。
Jpnh

23
これはまさに正しいですが、これを行う開発者はほとんどいません。パッケージは、クラスのまとまりのあるコレクションである必要があり、その一部はパッケージ内でのみ表示されます。これにより、異なる機能に関係するため結合しないクラス間の結合を最小限に抑えることができます。レイヤーごとのパッケージアプローチは、パッケージの可視性修飾子を利用せず、このようなプロジェクトのパッケージは、凝集度が低く、パッケージ間の結合が高度です。
ネイトリード

これの例はありますか?私はSpring-MVCを使用していますが、Springはconfig xmlを使用しているため、機能/モジュールごとに整理するのは難しいと思います。
Eric Huang

2
@onof私もコードを機能ごとに整理していますが、すべての機能で共有される基本クラスのベストプラクティスは何ですか?
マルク

私は最初のスタイルに従っていました。しかし、クラスを操作するときに、あるパッケージから別のパッケージにジャンプする必要があります。それは本当に悪い経験になります。関連するクラスを一緒にフォローする方が簡単になると思うので、今は2番目のスタイルに切り替えています。
M.kazem Akhgary 2018

40

短い答え:モジュール/機能ごとに1つのパッケージ、おそらくサブパッケージも。密接に関連するものを同じパッケージにまとめます。パッケージ間の循環依存関係を回避します。

長い答え:私はこの記事のほとんどに同意します


2
サブパッケージはカプセル化を壊します。「サブパッケージ」は、それ自体が完全に独立したパッケージです
Ricardo Gamba

21

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

  • 依存関係
    パッケージの依存関係、特に機能間の依存関係を最小限にしてください。必要に応じて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」というパッケージがある場合は、StringUtilssupport / string、HttpUtilsupport / httpなどに移動します。


13

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

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

(「ベストプラクティス」とそれを推進する人々の視点については、ベストプラクティスなしをお読みください。)

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

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

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


9

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

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

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

ここで詳しく説明します:Javaパッケージ名の構造と構成構成ですが、私の標準パッケージ構造は次のとおりです。

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

どこ:

revdomain逆ドメイン。例:com.mycompany

moduleType [app * | framework | util]

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

レイヤー [モデル| UI |永続性|セキュリティなど]

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

機能、例えば、金融

サブ機能N例、会計

subfeatureN + 1例:減価償却

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


5

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

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

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

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