クラスまたはモジュールはいつ独立したアセンブリ/ DLLに配置する必要がありますか?


22

クラスを独自のアセンブリ/ DLLに含めるタイミングを決定するためのガイドラインはありますか?私はしばしば二つの考え方を目にします:

1)クラスのすべての「グループ化」は、リポジトリ、サービス、DTO、インフラストラクチャなどの独自のDLLに属します。

2)すべてが単一のDLLにある必要がありますが、名前空間/フォルダーを介して分離する必要があります。たとえば、Core.Repositories、Core.Services、Core.DTOなどの追加の名前空間を持つ「Core」DLLが必要です。

仕事では、すべてを「ビジネス」と呼ばれる単一のアセンブリにまとめます。いくつかのフォルダーがありますが、本当の分離はありません。ビジネスオブジェクト(ロジックを含む、その一部はクラスであってはならない)は、「BusinessObjects」フォルダーに注意せずにまとめられます。複数のクラスで使用されるものは、「コア」フォルダーにあります。ユーティリティは「ユーティリティ」フォルダにあり、データアクセスインフラストラクチャは「データ」フォルダです。

私が取り組んでいる新しいモジュールの場合、個別のデータアクセスレイヤーが必要です(基本的なリポジトリ実装を考えてください)が、他の160(!)そこのクラス。同時に、誰もが単一のライブラリにクラスを詰め込むことに慣れているため、新しいクラスライブラリの作成について心配しています。ただし、フォルダ/ネームスペースは機能します。

回答:


12

各プロジェクトでカテゴリ別に分類されたクラスを持つプロジェクト(アセンブリ)を多く持つ方が、これらのクラスすべてが別々の名前空間にある場合よりも優れていると思います。プロジェクトを再利用可能にし、アプリケーション内の異なるレイヤーを表すことを目指してください。これらのプロジェクトを将来のアプリケーションで不必要に再利用でき、不必要なクラスを大量に含める必要がありません。

たとえば、あなたが述べたことに基づいて、私は間違いなく以下のプロジェクトを持っているでしょう:

  • コア
  • データ
  • ドメイン(またはBusinessObjects)
  • サービス
  • ユーティリティ(またはヘルパー)

2
残念ながら、私はその答えに反対票を投じることはできません。これがまさに当社で推奨されていることです。結果として、たとえば中規模のWebサイトなど、6個ほどのプロジェクトがある場合、機能ベースのディレクトリ階層などを維持できません。通常、これをアドバイスする人は、比較的大きなプロジェクトで機能ベースのプロジェクトの構造を試したことはありません(直接判断するのは申し訳ありませんが、そのようなオーバーウィーニングの結果を処理するのは本当に苦痛です)。jammycakesの回答は、正しいアプローチをアドバイスしています。
アレロ

クラスでクラスを分割することは、大規模なプロジェクトで混乱を招くものです。機能/アスペクトでそれらを分割します。そうすると、名前空間はこの部門をミラーリングするだけになります。そして、構造全体が仕様からレキシコンを反映します。カテゴリによるクラスの分割は、変数名に型の略語を追加するようなものです。通常は悪臭です。
アレロ

提案された両方のソリューションを乱用するのは簡単です(つまり、プロジェクトが多すぎるか少なすぎる)。再利用性と低カップリングを念頭に置いてバランスをとることで、よりテストと保守が容易になります。
バーナード

16

Clean Codeの「Uncle Bob」Martin、SOLID Principlesの名声は、ここで3つの原則を概説しています

  • リリースの再利用の等価性の原則:再利用のグラニュールは、リリースのグラニュールです。
  • 共通クロージャの原則:一緒に変更されるクラスは一緒にパッケージ化されます。
  • 一般的な再利用の原則:一緒に使用されるクラスは一緒にパッケージ化されます。

一般的な経験則では、ソリューション内のプロジェクトの数はできる限り少なくする必要があります。1つ以上の特定のユーザーストーリーを実装するために必要な場合、または単一のアセンブリが測定可能なパフォーマンスの問題を引き起こしている場合(通常、サイズが数メガバイトに達すると)のみ、それらを分割します。


2
+1これらの原則は良いガイドラインです。クラスを異なるアセンブリに分離すると、追加の設計上の考慮事項(たとえば、各アセンブリのどのバージョンが一緒に動作できるか)が導入され、全体のコードベースが増加し、メンテナンスのコストが増加します。
ベン14年

1
ただし、これらの原則に加えて、別のアセンブリで置換または交換される可能性が高いコードをパッケージ化することをお勧めします。このコードは、個別のアセンブリを結合するために必要な追加の考慮事項から恩恵を受け、個別のアセンブリを使用すると、異なるバージョンのテストと比較が容易になります。
ベン14年

4
はい。ただし、交換または交換するための真の要件があることを確認してください。たとえば、フレームワークとサードパーティライブラリ(NuGetパッケージなど)は通常、複数のIOCコンテナーと複数のロギングフレームワークをサポートする必要があります。一方、ユーザーランドコードの場合、そのような抽象化は通常純粋に投機的であり、不必要で邪魔なものであり、実際に必要とされるまれな状況では最終的に解決されません。
jammycakes 14年

「1つまたは複数の特定のユーザーストーリーを実装するために必要な場合、または単一のアセンブリが測定可能なパフォーマンスの問題を引き起こしている場合(通常、サイズが数メガバイトに達すると)のみ、それらを分割します。」-完全にランダムと現実のアドバイスに接地されていない
hyankov

1
申し訳ありませんが、まさに「完全にランダムで、現実に基づいていない」ものは何ですか?この答えは、何年もの間、必要以上に多くのプロジェクトに分割されたソリューションに取り組んできた後、「それはあなたがそれを行うことになっている」という理由以外の理由で投稿しました。結果?氷河期のコンパイル時間と依存性地獄の泥沼(特にNuGet以前の時代)。物を別々のアセンブリに分割することにはコストがかかり、そのコストを相殺するメリットがない場合は、ビジネスから盗むだけです。
ジャミーケーキ

4

私が協力している他の指導原則:

  • このコードを他のプロジェクトで再利用すると思いますか?関連するWebアプリケーションの1つのグループには、すべてのアプリケーションがユーザーアカウントとログインに同じモデルを使用したため、すべてのアプリケーションが使用する1つのユーザーアカウント関連モジュールがありました。ジオメトリライブラリと数学ライブラリで同様のことを行い、DLLを含めるだけで複数のアプリケーションでそれらを再利用しました。

  • プロジェクト全体を再デプロイ/再コンパイルせずに、このコードを変更/デプロイできるようにしたいですか?モジュールを再構築し、Webアプリケーションをデプロイして再起動するだけで便利な場合があります。

あなたの場合、基本的かつ一般的なリポジトリが将来再び役立つ可能性があるように思えますが、可能であれば新しいDLLに分離する価値があるかもしれません。


2番目のポイントは本当に合理的だと思います。モジュールに分割することは、開発/テストおよびコンパイル時間を支援するはずです。
WM
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.