web-dev-qa-db-ja.com

オニオンアーキテクチャでリポジトリではなくサービスを公開する理由

私はプロジェクトをどのように構成するかを掘り下げているので、オニオンアーキテクチャに出くわしました。私がそれをどのように理解するかについては、データベース駆動型ではなく、ドメイン中心のアーキテクチャーに重点を置いています。

私はアーキテクチャを研究して学ぶためのgithubプロジェクトを探しているので、これを見つけました https://github.com/chetanvihite/OnionArchitecture.Sample

私は理解するのに苦労しています:

namespace Domain.Interfaces
{
    public interface IUserRepository
    {
        IEnumerable<User> GetUsers();
    }
}

namespace Services.Interfaces
{
    public interface IUserService
    {
        IEnumerable<User> GetUsers();
    }
}

namespace Services
{
    public class UserService : IUserService
    {
        private readonly IUserRepository _repository;

        public UserService(IUserRepository repository)
        {
            _repository = repository;
        }

        public IEnumerable<User> GetUsers()
        {
            return _repository.GetUsers();
        }
    }
}

彼がそれを使用する方法は、コンストラクター注入によるものです。

private readonly IUserService _service;

public HomeController(IUserService service)
{
  _service = service;
}
  1. IUserServiceなどのサービスを、それを使用するアプリに常に公開していますか?しかし、私はIUserRepositoryIUserServiceと同じメソッドを持っていることに気付きましたか?

  2. インフラストラクチャの懸念と言った場合、それはデータベースを意味するのでしょうか、それともデータベースに関係していますか?または必ずしもそうではありませんか?そうでない場合、インフラストラクチャの懸念の例は何ですか?

追伸私はオニオンアーキテクチャを学んでいるので、常にではないにしても、少なくともDDDについて言及しています。だから私はDDDも学ぶでしょう:)

4
Boy Pasmo

Q:IUserServiceなどのサービスを、それを使用するアプリに常に公開していますか?

通常は行います。慣性によって慣れる場合もあれば、テストを行う場合もありますが、ほとんどの場合、アプリケーション内の境界を分離するために使用されます。これは、小さなコスト(複雑さ)で興味深い利点をもたらす一般的な方法です。

サービスは、異なる境界のコンポーネント間の呼び出しを調整して、コンシューマーがこれらの他のコンポーネントおよび境界について知る必要がないようにします。サービスは、データと動作が大幅に分離されている貧血モデルに特に関連しています。このような設計では、ほとんどのロジックはサービスに配置され、このレイヤーにビジネストランザクションの境界を設定します。

Q:しかし、IUserRepositoryIUserServiceと同じメソッドを持っていることに気付きましたか?

それは私には設計上の欠陥に聞こえます。これはオーバーエンジニアリングの症状であり、-ユーザーサービスは必要ありません-と表示されます。この種のサービスは関連する抽象化を提供しません。オーケストレーションを実行せず、トランザクションスパンはリポジトリインターフェースの下のものと同じです。サービスを残して、ビジネストランザクションのスコープを永続化レイヤーではなくこのレイヤーに設定することもできますが、サービスの存在が議論の余地なくなるわけではありません。

したがって、_IRepositoryについて消費者に知らせる必要がありますはい。アプリケーションと永続性の間に何らかの抽象化が必要になるまで。

なぜ?シンプルさ。不必要な複雑さはコードを推論することを難しくします。推論するのが難しいコードは、維持するのが難しいコードであり、そのため高価です。

Q:インフラストラクチャの懸念と言った場合、それはデータベースを意味するのでしょうか?

はい、しかしデータベースだけではありません。もっとあります。

  • メールサーバーへのアクセス
  • メッセージブローカーへのアクセス
  • キューへのアクセス
  • リモートストレージ(DB、ファイルシステムなど)へのアクセス
  • リモートデバイスへのアクセス
  • インデクサーへのアクセス
  • サードパーティのサービスへのアクセス

これらは、ドメインやビジネスとは密接に関係していませんが、アプリケーションに必要なプロセスです。それらを非機能要件として数えます。

組立ラインで考えてみましょう。ラインの目標は物事を組み立てることであり、そのためにはエネルギー供給が必要になる可能性があります。エネルギーを供給しているものはすべて、インフラストラクチャサービスと見なされます。供給されたエネルギーの供給源は、組立ラインがその目標を変更することにはなりませんが、ラインにエネルギーを供給する方法はそれを変更することができます。

つまり、データベースへのアクセスは、オニオンアーキテクチャにおけるインフラストラクチャの問題と考えることができます。 Onionアーキテクチャは、データベースを通信するリモート要素と見なします。それらはもはや中心ではなく、ドメインを変更する必要なしにそれらを変更できるようにする必要があります。

8
Laiv

オニオンアーキテクチャ は、インターフェースの背後にあるインフラストラクチャへの依存関係を隠すことを意味します。

IUserServiceを使用するすべてのコンポーネントは、サービスがsoap、rest、http、またはその他の関連インフラストラクチャを使用して実装されているかどうかを知る必要はありません。

実際のUserService実装は、実装の詳細としてリポジトリインターフェースIUserRepositoryを使用します。 UserServiceは、UserRepositoryの実装が使用するインフラストラクチャ(odbc、odedb、mssql-nativeなど)を認識する必要はありません。

しかし、IUserRepositoryにはIUserServiceと同じメソッドがあることに気付きましたか?

これは偶然です。

3
k3b