タイプ別または機能別フォルダー


59

AngularJSスタイルガイドを使用します。このガイド内にはfolder-by-feature、の代わりにと呼ばれるスタイルがあり、folder-by-type実際には最良のアプローチは何ですか(この例ではJavaの場合)

サービス、コントローラー、リポジトリー、もちろんドメインオブジェクトを使用して、ユーザーとペットを取得できるアプリケーションがあるとします。

folder-by -.....スタイルを使用すると、パッケージ構造に2つのオプションがあります。

1.タイプごとのフォルダー

com.example
├── domain
│    ├── User.java
│    └── Pet.java
├── controllers
│    ├── UserController.java
│    └── PetController.java
├── repositories
│    ├── UserRepository.java
│    └── PetRepository.java
├── services
│    ├── UserService.java
│    └── PetService.java
│   // and everything else in the project
└── MyApplication.java

2.機能ごとのフォルダー

com.example
├── pet
│    ├── Pet.java
│    ├── PetController.java
│    ├── PetRepository.java
│    └── PetService.java
├── user
│    ├── User.java
│    ├── UserController.java
│    ├── UserRepository.java
│    └── UserService.java
│   // and everything else in the project
└── MyApplication.java

良いアプローチとは何でしょうか、そうするための議論は何ですか?



1
@Laivがわかりません。言語/フレームワークは答えに本当に影響しますか?とにかく、他の質問は確かに関連しています。
ラバーダック16

1
次に、回答を編集する必要があります。そしてyest、それは可能性の重複だ
LAIV

2
タイプごとのフォルダの利点を理解できませんでした。ペット機能に関連するチケットに取り組んでいる場合、おそらく、、Petコントローラ、リポジトリ、およびサービスの局所性の恩恵を受けるでしょう。どのような状況で、すべてのコントローラーが必要になりますが、ビュー、リポジトリ、またはサービスは必要ありませんか?
アレクサンダー

2
Javaのパッケージは単なるフォルダーではないことを誰も言及していないようです。また、含まれているクラスのアクセスにも影響します。このため、package-by-layer / typeは実際にはJavaで何らかのセマンティック値を提供できます。
アンガスゴールドスミス

回答:


69

フォルダーごとのタイプは、小規模プロジェクトでのみ機能します。ほとんどの場合、機能ごとのフォルダが優れています。

少数のファイル(タイプごとに10未満の場合)がある場合は、タイプごとのフォルダーは問題ありません。プロジェクトに複数のコンポーネントがあり、すべてが同じタイプの複数のファイルである場合、探している実際のファイルを見つけるのは非常に難しくなります。

したがって、機能ごとのフォルダーは、そのスケーラビリティにより優れています。ただし、機能ごとにフォルダーを作成すると、ファイルが表すコンポーネントの種類に関する情報が失われることになります(フォルダーに含まれていないため、controller言うことができません)。これには2つの簡単な解決策があります。

まず、ファイル名のタイプを示す一般的な命名規則に従うことができます。たとえば、John Papaの人気のあるAngularJSスタイルガイドには次のものがあります。

命名ガイドライン

  • コンポーネントの機能を説明するパターンに従って、すべてのコンポーネントに一貫性のある名前を使用し、オプションでそのタイプを使用します。私の
    推奨パターンはfeature.type.jsです。ほとんどの
    アセットには2つの名前があります。

    • ファイル名(avengers.controller.js)
    • Angularで登録されたコンポーネント名(AvengersController)

次に、タイプごとのフォルダースタイルと機能ごとのフォルダースタイルを、タイプごとのフォルダーごとに組み合わせることができます。

com.example
├── pet
|   ├── Controllers
│   |   ├── PetController1.java
|   |   └── PetController2.java
|   └── Services
│       ├── PetService1.java
│       └── PetService2.java
├── user
|   ├── Controllers
│   |   ├── UserController1.java
│   |   └── UserController2.java
|   └── Services
│       ├── UserService1.java
│       └── UserService2.java

1
ジョンパパのスタイルガイドはまさに私が偽造したものでした:
Jelle

1
時々(私たちが考えているよりも)、簡単だと思われたものにあまりにも複雑を追加します。命名とパッケージ化はこれらのことの一部です。最善のアドバイスは、シンプルにすることです。両方の混合には、両方のアプローチの長所と短所があります。
Laiv

1
@Laiv私が与えた例ではそのやりすぎに同意しますが、各タイプフォルダーが10〜20個のファイルを簡単に持つことができる実際のビジネスケースのほとんどでは、機能フォルダー全体が50程度になるため、非常に便利だと思いますそれ以外のファイル。
モニカを

6
iPhoneの自動修正に感謝します!私は「話す」ことを意味しました。
Jelle

2
@Chaoticこの例は細かすぎて詳細を話せませんが、複数のコンポーネントで使用されるピースがあるような場合、他のコンポーネントが依存する独自のコンポーネントである可能性があります。
モニカの復元

26

これは、設定よりも規約に基づいたアプローチの一部としてタイプごとのフォルダーを強制するフレームワークを使用しない限り、問題のテクノロジーとはまったく関係ありません。

個人的には、フォルダごとの機能ははるかに優れており、可能な限りどこでも使用する必要があるという意見を強く持っています。実際に一緒に機能するクラスをグループ化しますが、フォルダごとのタイプは、通常クラス名にすでに存在するものを複製します。


10
機能ごとにフォルダを追加すると、クラスとメソッドのスコープ(保護、パッケージなど)を簡単に操作できるようになります。
LAIV

小規模なプロジェクトの場合、機能は1つしかありません。そのシナリオでは、タイプ別に整理する方がはるかに簡単です。
aaaaaa

例として、Grailsは、ドメイン、コントローラー、サービスなどに対してタイプ
ごとの

17

機能ごとのパッケージでの作業は、高いモジュール性と結束性で際立っています。これにより、コンポーネントのスコープを試すことができます。たとえば、アクセス修飾子を使用して、統合または拡張機能のLoDおよび依存関係の反転を強制できます。

その他の理由は次のとおりです。

  • 簡単なコードナビゲーション
  • より高いレベルの抽象化
  • スコープの最小化(境界コンテキスト)
  • 垂直モジュール化

フォルダーごとの層で、実装の詳細に重点を置きすぎています(@Davidが述べたように)。作業しているアプリケーションについてあまり多くを語っていないものです。パッケージごとの機能とは異なり、パッケージごとのレイヤーは水平方向のモジュール化を促進します。この種のモジュール化により、横断的なコンポーネントの操作が困難で退屈になります。

最後に、3番目のオプションがあります。「コンポーネントごとのパッケージ」は、ボブおじさんの言葉で言えば、彼のパッケージの原則とよく一致しているようです。おじさんのボブの意見が重要かどうかは、私が決めるのはあなたにお任せします。このコンベンションは彼のClean Architectureと一致しているので、私はそれが面白いと思います。

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