0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

「ドメイン駆動設計入門」を読んで_その2

Last updated at Posted at 2022-01-21

この記事は

前回記事 - 「ドメイン駆動設計入門」を読んでのつづき
リポジトリアプリケーションサービスについてまとめる

つづき:「ドメイン駆動設計入門」を読んで_その3

リポジトリ

リポジトリは、オブジェクト(データ)を永続化し、また再構築する

大事なのは、ドメインがデータストアの実態を知らなくてよいということ
ドメインはリポジトリに依頼するだけでよい

ドメインサービスの見通しをよくするリポジトリ

値オブジェクトやエンティティの補助となるドメインサービス

たとえば、あるエンティティがすでに存在するか確認するためには
データストアへの問い合わせを記述せねばならず、ドメインサービスのコード量が増える

見通しをよくするための方法

インターフェイスをつかって任意のリポジトリを注入することで
データストアの実態によらず、すっきり簡潔に書ける

class SomeDomainService
{
    private IRepo repo;

    public SomeDomainService(IRepo repo) // コンストラクタインジェクション
    {
        this.repo = repo;
    }

    public void OtherMethod()
    {
        // this.repo を使った何らかの処理
    }
}

リポジトリのインターフェイス

interface IRepo
{
    Obj Find(ObjName name)
    void Save(Obj obj)
    Option<Obj> Find(ObjName name)

    // リポジトリの責務は、永続化と再構築である
    bool Exist(ObjId id) // <- オブジェクトの有無を確認するのは責務範囲外ともいえる
}

サンプルコードの実現方法

データ永続化の手段が3つ用意されている

インメモリで動作するモジュール
SQL 文を利用したモジュール
Entity Framework を用いたモジュール

JSONファイルの一部を書き換えることで、コンフィグがスイッチするみたいだけど
コンフィグの中のセットアップ処理についてはよくわからない・・

  "Dependency": {
    "setup": "EFDependencySetup"
  },

アプリケーションサービス

アプリケーションサービスはドメインオブジェクトを協調させてユースケースを実現します (本書 P113)

ドメインモデルをドメインオブジェクトで表現できたら
次は目の前にある実問題を解決するためにアプリケーションサービスを構築する

ドメインサービスのおさらい

似たような言葉ですでにドメインサービスがある
ドメインサービスはドメインオブジェクトに対するサービスである

  • 値オブジェクトやエンティティがもつと不自然になるふるまいを代行する
    • まずは値オブジェクトやエンティティにふるいまいをもたせることを検討する
  • 自身のふるまいを変更するような状態をもたない

前回記事に詳細あり

ユースケースを組み立てる

QiitaなどSNSでは以下のようなユースケースが想定される

ドメインオブジェクトを用意する

GitHubに本書のリポジトリがあるので、そちらを参考にドメインオブジェクト群をつくる

ドメインオブジェクトは材料でしかない
かき集めたこれらの材料を利用するのはアプリケーションサービスである

アプリケーションサービスをつくる

UserApplicationService.csRegisterDeleteなど、ユースケースに沿ったメソッドが用意されている
そしてそれらのメソッドはドメインオブジェクトのインスタンスであるuserServiceuserRepositoryなどを利用している

ドメインオブジクトの公開範囲

「登録者情報を確認したい!」の文言のとおりに、そのままドメインオブジェクトであるユーザーインスタンスを戻り値で渡した場合、予期せぬふるまいまでされてしまう危険性がある
(単純に登録情報を閲覧するためだけにゲットしたuserchageName()メソッドが呼ばれた場合など)

DTO(Data Transfer Object) を使うことで、ドメインオブジェクトを直接渡さずに済ませられる

リポジトリから見つけたユーザー(ドメインオジェクト)をUserData(DTO)に詰め替えて、さらにUserGetResultに詰め替えて戻り値としている

こうすることで、必要最低限の情報のみを外部へ公開している

// UserApplicationServiceのGetメソッド
var user = userRepository.Find(id);
var data = new UserData(user);
return new UserGetResult(data);

ユーザー情報を更新するコマンド

登録情報を更新するUpdate処理を考える

リリース当初はUpdate(アカウント名)だけでよかったかもしれない
数か月後、Update(アカウント名、メールアドレス、性別)となり
数年後、Update(アカウント名、・・・たくさんの引数・・・)となる

将来引数が増えていくやもしれぬ処理については
ファサードとなるコマンドを導入することで対処する

UpdateCommandのコンストラクタに変更したいパラメータを渡す
変更したくないパラメータについてはnullのままとしておく

// コマンドのコンストラクに
UpdateCommand(arg1 = null, arg2 = null, arg3 =null)
{

}

// 更新処理 
public void Update(UserUpdateCommand command)
{
  if(command.arg1 != null)
  {
    // 更新処理
  }
}

登録処理と退会処理をわける

UserApplicationServiceはもっと細分化できる

登録や更新では、ドメインサービスuserServiceに重複確認を行う
一方、退会Deleteでは重複確認の必要はない

凝集度の指標として、そのクラスのメソッドがすべてのインスタンス変数を使っていることが目安になる

UserApplicationServiceUserRegisterServiceUserDeleteServiceにわけることで、より高い凝集度のクラスをつくることができる

アプリケーションサービスのインターフェイス

interface IUserSomeService
{
  void Handle(SomeCommand command)
}

サービスとはなにか

  • サービスは自身のためのふるまいをもたない
  • サービスはものごとではなく、活動や行動である
  • ドメインサービスとアプリケーションサービスの本質は同じ
    • ドメインの知識を表現したものがドメインサービス
    • 利用者の問題を解決するものがアプリケーションサービス

アプリケーションサービスのまとめ

とにかくドメインの知識がアプリケーションサービスに漏れ出ないようにすること!

0
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?