Javaプロジェクトでパッケージの命名にどの戦略を使用していますか。その理由は何ですか。[閉まっている]


88

私はしばらく前にこれについて考えましたが、私の店が最初の実際のJava Webアプリを実行しているときに最近再浮上しました。

イントロとして、2つの主要なパッケージ命名戦略を見ます。(明確にするために、この「domain.company.project」の部分全体を指すのではなく、その下のパッケージ規則について話しています。)とにかく、私が見るパッケージの命名規則は次のとおりです。

  1. 機能:パッケージを、ビジネスドメインに基づくIDではなく、機能に応じてアーキテクチャに名前を付けます。 これの別の用語は、「レイヤー」に基づく名前付けかもしれません。したがって、*。uiパッケージ、*。domainパッケージ、および* .ormパッケージがあります。パッケージは垂直ではなく水平スライスです。

    これは論理的な命名よりもはるかに一般的です。実際、これを行うプロジェクトを見たことも聞いたこともないと思います。もちろん、私はひどく頭がよくないので(NPの問題の解決策を思いついたようなものです)、誰もが自分のやり方でやるには大きな理由があるはずだと思います。一方、私はちょうど部屋に象を行方不明の人に反対していないよ、私は実際の引数聞いたことがないため、このように名前を付けるパッケージをやって。それは事実上の標準のようです。

  2. 論理:パッケージをビジネスドメインIDに従って名前を付け、その垂直方向の機能スライスに関係するすべてのクラスをそのパッケージに入れます。

    前に述べたように、これについては見たり聞いたりしたことがありませんが、それは私にとっては意味のあることです。

    1. 私はシステムを水平ではなく垂直にアプローチする傾向があります。データアクセス層ではなく、注文処理システムを開発したいと考えています。明らかに、そのシステムの開発でデータアクセス層に触れる可能性は十分ありますが、重要なのは、そのように考えていないということです。これが意味することは、もちろん、変更要求を受け取ったり、いくつかの新しい機能を実装したりするときに、関連するすべてのクラスを見つけるために、たくさんのパッケージを探し回る必要がないのは素晴らしいことです。代わりに、私がしていることはXと関係があるため、Xパッケージを調べるだけです。

    2. 開発の観点から、私はあなたのパッケージがあなたのアーキテクチャーではなくあなたのビジネスドメインを文書化することは大きな勝利だと思います。ドメインはほとんど常にシステムの一部であり、システムのアーキテクチャが、特にこの時点で、実装においてほぼ平凡になっているため、理解するのが難しいように感じます。このタイプの命名規則を使用してシステムにアクセスでき、パッケージの命名から即座にシステムが注文、顧客、企業、製品などを扱うことができるという事実は、かなり便利なようです。

    3. これにより、Javaのアクセス修飾子をより効果的に利用できるようになります。これにより、システムのレイヤーではなくサブシステムへのインターフェースをより明確に定義できます。したがって、透過的に永続化したい注文サブシステムがある場合、理論的には、DAOレイヤーに永続クラスへのパブリックインターフェイスを作成せずに、DAOクラスをそれが扱うクラスだけで。もちろん、場合あなたは、この機能を公開したかった、あなたはそれのためのインタフェースを提供したり、それを公開することができます。システム機能の垂直スライスを複数のパッケージに分割することで、これの多くを失うようです。

    4. 私が見ることができる1つの不利な点は、それがレイヤーの切り取りを少し難しくすることだと思います。パッケージを削除または名前変更してから、別のテクノロジーを使用して新しいパッケージを所定の場所にドロップする代わりに、すべてのパッケージ内のすべてのクラスを変更する必要があります。しかし、これは大した問題ではないと思います。経験不足のせいかもしれませんが、テクノロジーを入れ替える回数は、システム内で垂直方向の機能スライスにアクセスして編集する回数と比較すると、見劣りするものだと想像しなければなりません。

だから私は質問があなたに出てくると思います、あなたはあなたのパッケージにどのように名前を付けますか、そしてなぜですか?私は必ずしもここで金色のガチョウや何かに偶然出会ったとは限らないことを理解してください。私はこれらすべてにかなり新しいですが、ほとんどが学問的な経験があります。しかし、私は私の推論の穴を見つけることができないので、私が先に進むことができるように、皆さんができることを望んでいます。


私がこれまでに聞いたことは、それが一種の判断の呼びかけであることを示しているようです。ただし、ほとんどの回答は実際的な考慮事項に焦点を当てていません。それが私が探しているものです。ただし、これまでのご協力に感謝いたします。
Tim Visher、2009

それは裁判の呼びかけではないと思います。最初にレイヤーで分割し、次に機能で分割するのが確実です。回答を更新しています。
eljenso

@eljenso:Eclipseの人にそれを伝えてください:) Eclipseでは、最初の分割はデプロイメントの機能である「機能」と機能です。「機能」の内部には「プラグイン」があり、通常はレイヤーによって分割されますが、同じ「機能」内のプラグインは常に一緒にデプロイする必要があります。デプロイメントユニットが1つしかない場合は、最初にレイヤーで分割し、次に機能でのみ分割することもできます。複数のデプロイメントユニットを使用すると、プレゼンテーションレイヤーだけをデプロイするのではなく、追加の機能が必要になります。
PeterŠtibraný

回答:


32

パッケージデザインでは、まずレイヤーで分割し、次に他の機能で分割します。

追加のルールがいくつかあります。

  1. レイヤーは、最も一般的なもの(下)から最も具体的なもの(上)に積み上げられます
  2. 各レイヤーにはパブリックインターフェイスがあります(抽象化)
  3. レイヤーは、別のレイヤーのパブリックインターフェイスにのみ依存できます(カプセル化)
  4. レイヤーはより一般的なレイヤーにのみ依存できます(上から下への依存)
  5. レイヤーは、そのすぐ下のレイヤーに依存することが好ましい

たとえば、Webアプリケーションの場合、アプリケーション層に(上から下に)次のレイヤーを含めることができます。

  • プレゼンテーション層:クライアント層に表示されるUIを生成します
  • アプリケーション層:アプリケーションに固有のロジックを含み、ステートフル
  • サービス層:ドメインごとに機能をグループ化し、ステートレス
  • 統合レイヤー:バックエンド層(db、jms、emailなど)へのアクセスを提供します

結果のパッケージレイアウトの場合、これらはいくつかの追加ルールです。

  • すべてのパッケージ名のルートは <prefix.company>.<appname>.<layer>
  • レイヤーのインターフェースは、機能ごとにさらに分割されています。 <root>.<logic>
  • レイヤーのプライベート実装の前にはプライベートが付けられます: <root>.private

これがレイアウトの例です。

プレゼンテーション層は、ビューテクノロジによって、およびオプションでアプリケーション(のグループ)によって分割されます。

com.company.appname.presentation.internal
com.company.appname.presentation.springmvc.product
com.company.appname.presentation.servlet
...

アプリケーション層はユースケースに分かれています。

com.company.appname.application.lookupproduct
com.company.appname.application.internal.lookupproduct
com.company.appname.application.editclient
com.company.appname.application.internal.editclient
...

サービスレイヤーはビジネスドメインに分割され、バックエンド層のドメインロジックの影響を受けます。

com.company.appname.service.clientservice
com.company.appname.service.internal.jmsclientservice
com.company.appname.service.internal.xmlclientservice
com.company.appname.service.productservice
...

統合レイヤーは「テクノロジー」とアクセスオブジェクトに分かれています。

com.company.appname.integration.jmsgateway
com.company.appname.integration.internal.mqjmsgateway
com.company.appname.integration.productdao
com.company.appname.integration.internal.dbproductdao
com.company.appname.integration.internal.mockproductdao
...

このようにパッケージを分離することの利点は、複雑さの管理が容易になり、テスト性と再利用性が向上することです。かなりのオーバーヘッドのように思えますが、私の経験では実際には非常に自然になり、この構造(または類似の)に取り組んでいる誰もが数日でそれを拾います。

なぜ垂直アプローチがあまり良くないと思いますか?

階層化モデルでは、いくつかの異なる高レベルモジュールが同じ低レベルモジュールを使用できます。たとえば、同じアプリケーションの複数のビューを作成したり、複数のアプリケーションで同じサービスを使用したり、複数のサービスで同じゲートウェイを使用したりできます。ここでの秘訣は、レイヤーを移動するときに機能のレベルが変化することです。より具体的なレイヤーのモジュールは、より一般的なレイヤーのモジュールに1-1をマッピングしません。これは、それらが表す機能のレベルが1-1をマッピングしないためです。

パッケージ設計に垂直アプローチを使用する場合、つまり最初に機能で分割する場合、機能レベルの異なるすべてのビルディングブロックを同じ「機能ジャケット」に強制します。より具体的なモジュール用に一般的なモジュールを設計できます。しかし、これは、より一般的な層がより具体的な層について知ってはならないという重要な原則に違反しています。たとえば、サービスレイヤーは、アプリケーションレイヤーのコンセプトに基づいてモデル化するべきではありません。


「このようにパッケージを分離することの利点は、複雑さの管理が容易になり、テスト性と再利用性が向上することです。」あなたはこれがそうである理由に本当に入りません。
mangoDrunk

1
それそうではない理由に行きません。しかしとにかく...整理するためのルールはかなり明確で簡単なので、複雑さを軽減します。組織自体により、よりテストと再利用が可能です。誰もがそれを試すことができ、その後、私たちは同意することもできないこともできます。垂直方向のアプローチのいくつかの欠点を簡単に説明し、水平方向のアプローチの方が簡単だと思う理由を暗黙的に示します。
eljenso

8
この記事では、package-by-layerの代わりにpackage-by- featureを使用する方が良い理由を非常にうまく説明しています
トム

@eljenso「そうでない理由にあなたは入りません」、証明の重荷をシフトしようとしていますか?トムが投稿した記事は、機能ごとのパッケージの方が優れている理由を非常にうまく説明していると思います。「判断の呼びだとは思わない。最初にレイヤーで分割し、次に機能で分割するのが間違いなく方法です。行く」と真剣に。
2013

18

ボブおじさんのパッケージデザイン原則に固執しています。まとめると、一緒に再利用され、一緒に変更されるクラス(同じ理由で、たとえば、依存関係の変更やフレームワークの変更)は、同じパッケージに入れる必要があります。IMO、機能の内訳は、ほとんどのアプリケーションで垂直/ビジネス固有の内訳よりもこれらの目標を達成する可能性が高くなります。

たとえば、ドメインオブジェクトの水平スライスは、さまざまな種類のフロントエンドまたはアプリケーションで再利用でき、Webフロントエンドの水平スライスは、基盤となるWebフレームワークを変更する必要があるときに一緒に変更される可能性があります。一方、さまざまな機能領域のクラスがそれらのパッケージにグループ化されている場合、多くのパッケージにわたるこれらの変更の波及効果を想像するのは簡単です。

明らかに、すべての種類のソフトウェアが同じであるとは限らず、特定のプロジェクトでは(再利用性と変更の接近性の目標を達成するという観点から)垂直分割が意味をなす場合があります。


おかげで、これは非常に明確です。質問で述べたように、テクノロジーを交換する回数は、機能の垂直スライスをシフトする回数よりもはるかに少ないように感じます。これはあなたの経験ではありませんか?
Tim Visher、2009

テクノロジーだけではありません。元の投稿のポイント#1は、垂直スライスが何らかのインターフェース(SOAの場合)を介して相互に通信する独立したアプリケーション/サービスである場合にのみ意味があります。詳細はこちら...
Buu Nguyen、

独自のgui / business / dataを持つ細かいアプリ/サービスの詳細に進むと、テクノロジー、依存関係、ルール/ワークフロー、ロギングなど、垂直方向のスライスの変化を想像することはできません、セキュリティ、UIスタイル、他のスライスから完全に分離できます。
Buu Nguyen、


@BuuNguyenパッケージ設計原則へのリンクが壊れています。
johnnieb 2016年

5

通常、両方のレベルの部門が存在します。上から、デプロイメントユニットがあります。これらは「論理的に」(あなたの言葉では、Eclipseの機能だと思います)という名前です。デプロイメントユニット内には、パッケージの機能分割があります(Eclipseプラグインを考えてください)。

たとえば、機能はcom.featureでありcom.feature.clientcom.feature.corecom.feature.uiプラグインで構成されています。プラグインの内部では、他のパッケージへの分割はほとんどありませんが、それも珍しいことではありません。

更新:ところで、InfoQ:http : //www.infoq.com/presentations/code-organization-large-projectsで、コード編成についてのJuergen Hoellerによる素晴らしい講演があります。ユルゲンは春の建築家の1人であり、このことについてはよく知っています。


私は完全に従わない。通常、com.apache.wicket.xが表示されることがあります。ここで、xは機能的または論理的です。通常、com.xは表示されません。com.company.project.feature.layer構造で行くと言っていると思いますか?理由はありますか?
Tim Visher、2009

理由は、「com.company.project.feature」がデプロイメントの単位であるためです。このレベルでは、一部の機能はオプションであり、スキップすることができます(つまり、デプロイされません)。ただし、内部機能では、物事はオプションではなく、通常はすべてが必要です。ここでは、レイヤーで分割する方が理にかなっています。
PeterŠtibraný2009

4

私が取り組んだほとんどのJavaプロジェクトでは、まずJavaパッケージを機能的にスライスしてから、論理的にスライスしています。

通常、パーツは十分に大きいため、個別のビルドアーティファクトに分割されます。コア機能を1つのjarに、apiを別のjarに、webフロントエンドの要素をwarfileに配置できます。


それはどのように見えるでしょうか?domain.company.project.function.logicalSlice?
Tim Visher、2009

かなり!egdcpweb.profiles、dcpweb.registration、dcpapis、dcppersistenceなどは、通常、かなりうまく機能しますが、距離は異なる場合があります。ドメインモデリングを使用しているかどうかにも依存します。複数のドメインがある場合は、最初にドメインで分割することをお勧めします。
ベンハーディ

私は個人的には反対で論理的で機能的である方を好みます。apples.rpc、apples.model、次にbanana.model、banana.store
mP。

すべてのアップルのものをグループ化できることには、すべてのWebのものをグループ化するよりも価値があります。
mP。

3

パッケージは、1つの単位としてコンパイルおよび配布されます。パッケージに属するクラスを検討する場合、重要な基準の1つはその依存関係です。このクラスが他のどのパッケージ(サードパーティライブラリを含む)に依存しているか。適切に編成されたシステムは、パッケージ内の同様の依存関係を持つクラスをクラスター化します。明確に定義された少数のパッケージのみがライブラリに依存するため、これにより1つのライブラリの変更の影響が制限されます。

論理的な垂直システムは、ほとんどのパッケージにわたって依存関係を「塗りつぶす」傾向があるように思えます。つまり、すべての機能が垂直スライスとしてパッケージ化されている場合、すべてのパッケージは、使用するすべてのサードパーティライブラリに依存します。ライブラリへの変更は、システム全体に波及する可能性があります。


ああ。したがって、水平スライスを行うことの1つは、使用しているライブラリの実際のアップグレードからユーザーを保護することです。垂直方向のスライスは、システムがすべてのパッケージにわたって持っているすべての依存関係を塗りつぶすことは正しいと思います。なぜこれがそんなに重要なのですか?
Tim Visher、2009

「機能」については、それほど大したことではありません。それらはより変動しやすく、とにかく依存性が高い傾向があります。一方、この「クライアント」コードは再利用性が低い傾向があります。再利用可能なライブラリにするつもりであれば、小さな変更からクライアントを分離することは大きな投資です。
エリクソン2009

3

私は個人的に、クラスを論理的にグループ化することを好みます。その中には、各機能参加のサブパッケージが含まれます。

包装の目的

パッケージは結局のところ、物事をグループ化することです。関連するクラスであるという考えは、互いに密接に関係しています。彼らが同じパッケージに住んでいる場合、可視性を制限するためにパッケージプライベートを利用できます。問題は、すべてのビューとパーシスタンスを1つのパッケージにまとめることで、多くのクラスが1つのパッケージに混ざってしまう可能性があります。したがって、次に行うべき賢明なことは、ビュー、永続性、utilサブパッケージを作成し、それに応じてクラスをリファクタリングすることです。残念ながら、保護されたパッケージプライベートスコーピングは、現在のパッケージとサブパッケージの概念をサポートしていません。これは、このような可視性ルールの適用を補助するためです。

ビューに関連するすべてのものをグループ化するためにどのような価値があるかを考えると、機能を介して分離された価値がわかります。このネーミング戦略に含まれるものは、ビュー内の一部のクラスから切り離されますが、他のクラスは永続化されます。

私の論理的なパッケージ構造の例

説明のために、2つのモジュールに名前を付けます。名前モジュールを、パッケージツリーの特定のブランチの下にあるクラスをグループ化する概念として使用します。

apple.model apple.store banana.model banana.store

メリット

Banana.store.BananaStoreを使用するクライアントは、利用可能にする機能にのみ公開されます。hibernateバージョンは実装の詳細であり、ストレージ操作に混乱を与えるため、これらのクラスを認識したり、これらのクラスを表示したりする必要はありません。

その他の論理v機能上の利点

ルートに近づくほどスコープが広くなり、1つのパッケージに属するものは、モジュールに属するものへの依存性をますます示し始めます。たとえば「バナナ」モジュールを調べた場合、ほとんどの依存関係はそのモジュール内に限定されます。実際、「banana」の下のほとんどのヘルパーは、このパッケージスコープの外ではまったく参照されません。

なぜ機能するのか?

機能に基づいて物事をひとまとめにすることによって、どのような価値が達成されますか。このような場合のほとんどのクラスは互いに独立しており、パッケージのプライベートメソッドやクラスを利用する必要はほとんどありません。それらを独自のサブパッケージにリファクタリングしてもほとんど効果はありませんが、混乱を減らすのに役立ちます。

システムに対する開発者の変更

自明ではない変更を行うように開発者に課せられた場合、パッケージツリーのすべての領域からのファイルを含む変更がある可能性があるのはばかげているように見えます。論理的に構造化されたアプローチでは、それらの変更はパッケージツリーの同じ部分内でより局所的ですが、これは正しいように見えます。


「開発者がパッケージツリーのすべての領域のファイルを[...]にしたとき。」これはばかげているようだと言うときあなたは正しいです。これがまさに適切な階層化のポイントだからです。アプリケーションの構造全体に変更波及することはありません
eljenso 2009

アドバイスありがとうございます。私はあなたをはっきりと理解しているとは思いません。私はあなたが論理パッケージを主張しようとしていると思いますが、その理由は正確にはわかりません。答えを少し明確にして、言い換えれば言い換えてみてください。ありがとう!
Tim Visher、2009

3

パッケージ化に対する機能的(アーキテクチャ的)と論理的(機能)の両方のアプローチがあります。多くのサンプルアプリケーション(テキストブックなどにあります)は、プレゼンテーション、ビジネスサービス、データマッピング、およびその他のアーキテクチャレイヤーを個別のパッケージに配置するという機能的アプローチに従います。アプリケーションの例では、各パッケージに含まれるクラスが少数または1つしかないことがよくあります。

この最初のアプローチは問題のない例でよく機能するため、1)提示されているフレームワークのアーキテクチャを概念的にマッピングする、2)単一の論理的な目的(たとえば、クリニックからペットを追加/削除/更新/削除する)でこれを行う。問題は、多くの読者がこれを境界のない標準と見なしていることです。

「ビジネス」アプリケーションが拡張されてより多くの機能が含まれるようになると、機能的アプローチに従うことが負担になります。アーキテクチャレイヤーに基づいてタイプを探す場所は知っていますが(たとえば、「web」または「ui」パッケージの下のwebコントローラーなど)、単一の論理機能を開発するには、多くのパッケージ間を行き来する必要があります。これは、少なくとも面倒ですが、それよりも悪いです。

論理的に関連するタイプは一緒にパッケージ化されていないため、APIは過度に公開されます。論理的に関連するタイプ間の相互作用は強制的に「パブリック」になり、タイプが相互にインポートおよび相互作用できるようになります(デフォルト/パッケージの可視性を最小化する機能が失われます)。

私がフレームワークライブラリを構築している場合、私のパッケージは必ず機能的/アーキテクチャ的パッケージングアプローチに従います。私のAPIコンシューマーは、インポートステートメントに、アーキテクチャにちなんで名付けられた直感的なパッケージが含まれていることを高く評価するかもしれません。

逆に、ビジネスアプリケーションを構築するときは、機能別にパッケージ化します。Widget、WidgetService、およびWidgetControllerをすべて同じ「com.myorg.widget。」パッケージに配置し、デフォルトの可視性を利用する(そしてインポートステートメントとパッケージ間の依存関係を少なくする)ことに問題はありません。

ただし、クロスオーバーのケースがあります。私のWidgetServiceが多くの論理ドメイン(機能)で使用されている場合、「com.myorg.common.service。」パッケージを作成する可能性があります。また、機能全体で再利用できるように意図してクラスを作成し、「com.myorg.common.ui.helpers。」や「com.myorg.common.util。」などのパッケージで終わる可能性もあります。これらすべての「共通」クラスを別のプロジェクトに移動して、myorg-commons.jar依存関係としてビジネスアプリケーションに含めることもできます。


2

それは論理プロセスの粒度に依存しますか?

スタンドアロンの場合、新しいパッケージではなく、ソース管理に新しいプロジェクトが含まれることがよくあります。

私が現在取り組んでいるプロジェクトは、論理分割に誤りがあります。jythonアスペクト用のパッケージ、ルールエンジン用のパッケージ、foo、bar、binglewozzle用のパッケージなどがあります。XML固有のパーサーを探しています(以前に行った)XMLパッケージではなく、そのパッケージ内の各モジュールの/ writers。ただし、共有ロジックが進むコアXMLパッケージは引き続き存在します。ただし、これは拡張可能(プラグイン)であり、各プラグインはXML(またはデータベースなど)コードも定義する必要があるため、これを集中化すると後で問題が発生する可能性があるためです。

結局のところ、特定のプロジェクトにとって最も賢明であるように思われます。ただし、典型的なプロジェクトの階層化された図の線に沿ってパッケージ化するのは簡単だと思います。結局、論理パッケージと機能パッケージが混在することになります。

タグ付けされた名前空間が必要です。一部のJython機能のXMLパーサーは、JythonとXMLの両方をタグ付けすることができ、どちらか一方を選択する必要はありません。

または多分私はぐらついています。


私はあなたの主張を完全に理解していません。私はあなたが言っていることはあなたがあなたのプロジェクトにとって最も意味のあることをするべきだとあなたが考えていることだと思います。
Tim Visher、2009

言ったように、組み込みの機能を拡張するプラグインを用意します。プラグインは、機能を提供するだけでなく、XMLを解析して書き込む(そして最終的にはDBに書き込む)ことができる必要があります。したがって、com.xx.feature.xmlまたはcom.xx.xml.featureがありますか?前者はすっきりしているようです。
JeeBee

2

私は、依存関係グラフを描画する場合、循環参照をできるだけ少なくして、一貫したパターンをたどって簡単に使用できるように、パッケージ構造を設計しようとします。

私にとって、これは、水平方向よりも垂直方向の命名システムで維持および視覚化する方がはるかに簡単です。component1.displayにcomponent2.dataaccessへの参照がある場合、display.component1にdataaccessへの参照がある場合よりも多くの警告ベルがスローされます。コンポーネント2。

もちろん、両方で共有されるコンポーネントは独自のパッケージに入れられます。


私があなたを理解しているように、あなたは縦の命名規則を擁護するでしょう。これは、複数のスライスにまたがるクラスが必要な場合の* .utilsパッケージの目的です。
Tim Visher、2009

2

私は完全に論理的(「機能別」)の組織に従い、提案します!パッケージは、「モジュール」の概念にできる限り厳密に従う必要があります。機能組織は、モジュールをプロジェクト全体に広げ、カプセル化を減らし、実装の詳細を変更する傾向があります。

たとえば、Eclipseプラグインを見てみましょう。すべてのビューまたはアクションを1つのパッケージに入れるのは面倒です。代わりに、機能の各コンポーネントは、機能のパッケージに移動するか、多数ある場合はサブパッケージ(featureA.handlers、featureA.preferencesなど)に移動する必要があります。

もちろん、問題は階層的なパッケージシステム(特にJavaが持っている)にあり、直交する懸念の扱いを不可能にするか、少なくとも非常に困難にします。


1

個人的には機能的なネーミングに行きます。短い理由:コードの重複や依存関係の悪夢を回避します。

もう少し詳しく説明しましょう。独自のパッケージツリーで外部jarファイルを使用するとどうなりますか?(コンパイルされた)コードをプロジェクトに効果的にインポートし、それとともに(機能的に分離された)パッケージツリーをインポートします。2つの命名規則を同時に使用することは理にかなっていますか?いいえ、それがあなたから隠されていない限り。そして、それは、プロジェクトが十分に小さく、単一のコンポーネントを持つ場合です。しかし、複数の論理ユニットがある場合は、おそらく再実装したくないでしょう。たとえば、データファイルロードモジュールです。論理ユニット間でそれを共有し、論理的に無関係なユニット間に人為的な依存関係を持たせず、特定の共有ツールを配置するユニットを選択する必要がない。

これが、特定のサイズに到達する、または到達することを目的とするプロジェクトで関数名が最も使用される理由であり、特定の役割を追跡するために、クラスの命名規則で論理名が使用されます。パッケージ。

論理的なネーミングに関するあなたの各ポイントに、より正確に対応するように努めます。

  1. 計画が変更されたときに機能を変更するために古いクラスで釣りに行く必要がある場合は、抽象化が悪い兆候です。1つの短い文で定義できる、明確に定義された機能を提供するクラスを構築する必要があります。ビジネスインテリジェンスを反映するために、これらすべてを組み立てるのは少数の最上位クラスだけです。このようにして、より多くのコードを再利用し、メンテナンスを容易にし、ドキュメントを明確にし、依存関係の問題を減らすことができます。

  2. これは主に、プロジェクトのやり方に依存します。間違いなく、論理的かつ機能的な見方は直交しています。したがって、1つの命名規則を使用する場合は、順序を維持するためにクラス名にもう1つを適用するか、ある命名規則から別の命名規則にいくらか深く分岐する必要があります。

  3. アクセス修飾子は、処理を理解する他のクラスがクラスの内部にアクセスできるようにする良い方法です。論理関係は、アルゴリズムや同時実行性の制約を理解することを意味するものではありません。機能しますが、機能しません。パブリックおよびプライベート以外のアクセス修飾子は、適切なアーキテクチャとクラスの抽象化の欠如を隠すことが多いため、非常にうんざりしています。

  4. 大規模な商業プロジェクトでは、テクノロジーの変更が予想以上に頻繁に発生します。たとえば、XMLパーサーの3倍、キャッシングテクノロジーの2倍、ジオローカリゼーションソフトウェアの2倍を変更する必要がありました。細かい部分を専用パッケージで隠していたのは良いことです...


1
私が間違っていても許してください。でも、多くの人が使用することを目的としたフレームワークの開発についてもっと話しているように思えます。そのタイプの開発とエンドユーザーシステムの開発では、ルールが変わると思います。私が間違っている?
Tim Visher、2009

多くの垂直スライスで使用される一般的なクラスの場合、utilsパッケージのようなものを持つことは理にかなっていると思います。次に、それを必要とするクラスは、そのパッケージに単純に依存することができます。
Tim Visher、2009

繰り返しになりますが、サイズは重要です。プロジェクトが十分に大きくなると、それは複数の人々によってサポートされる必要があり、ある種の専門化が発生します。対話を容易にし、間違いを防ぐために、プロジェクトを部分的に分割することが迅速に必要になります。そして、utilsパッケージはすぐに巨大になります!
バルカン、2009

1

パッケージをまったく使用しないことは興味深い実験です(ルートパッケージを除く)。

そのときに生じる問題は、いつ、なぜパッケージを導入することが理にかなっているのかということです。おそらく、答えはプロジェクトの最初に答えたものとは異なるでしょう。

パッケージはカテゴリのようなものであり、どちらか一方を決めるのが難しい場合があるので、あなたの質問はまったく発生すると思います。クラスが多くのコンテキストで使用可能であることを伝えるには、タグの方が望ましい場合があります。


0

純粋に実用的な観点から見ると、Javaの可視性構造は、同じパッケージ内のクラスが、可視性を持つメソッドとプロパティ、protectedおよびそれらにアクセスできるdefaultようにしpublicます。コードの完全に異なるレイヤーの非公開メソッドを使用することは、間違いなく大きなコードのにおいになります。そのため、同じレイヤーのクラスを同じパッケージに入れる傾向があります。

クラスの単体テストを除いて、これらの保護されたメソッドやデフォルトのメソッドを他の場所で使用することはあまりありませんが、使用する場合は常に同じレイヤーのクラスからのものです


常に下のレイヤーに依存しているのは、多層システムの性質ではありませんか?たとえば、UIはサービスレイヤーに依存し、サービスレイヤーはドメインレイヤーなどに依存します。垂直スライスを一緒にパッケージ化すると、パッケージ間の過度の依存関係から保護されているようです。
Tim Visher、2009

保護されたメソッドやデフォルトのメソッドはほとんど使用していません。99%は公的または私的です。一部の例外:(1)単体テストでのみ使用されるメソッドのデフォルトの可視性、(2)抽象基本クラスからのみ使用される保護された抽象メソッド。
Esko Luontola、2009

1
Tim Visher、依存関係が常に同じ方向を指し、依存関係グラフに循環がない限り、パッケージ間の依存関係は問題になりません。
Esko Luontola、2009

0

場合によります。私の業務では、機能(データアクセス、分析)または資産クラス(クレジット、株式、金利)によってパッケージを分割することがあります。チームにとって最も便利な構造を選択するだけです。


どちらに行く理由はありますか?
Tim Visher、2009

アセットクラス(より一般的には、ビジネスドメイン)で分割すると、新しい人々がコードを簡単に見つけられるようになります。関数による分割は、カプセル化に適しています。私にとって、Javaの「パッケージ」アクセスは、C ++の「友達」に似ています。
quant_dev 2009

@quant_dev「..by関数はカプセル化に適しています」に同意しません。私はあなたが完全に反対のことが真実であることを意味すると思います。また、「便利さ」だけではありません。それぞれにケースがあります(私の答えを参照してください)。
i3ensays 2013年

-3

私の経験から、再利用性は解決よりも多くの問題を引き起こします。最新で安価なプロセッサとメモリを使用する場合、再利用するために、緊密に統合するよりも、コードを複製することを好みます。


5
コードの再利用は、ハードウェアの価格ではなく、コードのメンテナンスコストです。
user2793390 2014

1
同意しますが、単純なモジュールで何かを修正してもコード全体には影響しません。どのような維持費について話しているのですか?
Raghu Kasturi 2014

1
モジュールのバグ修正は、アプリケーション全体に影響を与えるはずです。同じバグを何度も修正したいのはなぜですか?
user2793390
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.