りゅうじの学習blog

学習したことをアウトプットしていきます。

5/15 ドメイン駆動設計 Chapter4

ドメインサービスとは何か

値オブジェクト・エンティティに定義すると不自然なメソッドを定義するドメインオブジェクトのこと

不自然なメソッドを確認する

ユーザ名の重複処理

こちらをドメインオブジェクトに定義すると重複の有無を自信に問い合わせることになります。

以下、不自然な例

class UserId {
  constructor(private readonly id: string) {}
}

class UserName {
  constructor(private readonly name: string) {}
  public getName() {
    return this.name;
  }
}

class User {
  constructor(private readonly id:UserId, private name: UserName) {}
  public getName() {
    return this.name;
  }
  public exists(newName: User): boolean {
    return (this.name === newName.getName()) ? true : false;
  }
}
const userId = new UserId('3');
const userName = new UserName('yunosuke');
const user = new User(userId, userName);

const duplicateCheckResult = user.exists(user);
console.log(duplicateCheckResult); // true
  • Userクラスにユーザ名重複チェックのexistsメソッドを定義している
    • メソッド呼び出し時のuser.exists(user);が不自然である
      • これが、先ほど言っていた、重複の有無を自信に問い合わせることになる

『私の名前って登録されていますか?』と自分に聞いている。←不自然である。

私の所感

ドメインオブジェクトには自分のルールを定義するのはいいが、他者も関わるメソッド(今回だと重複チェック←自分と他者を比較している)を定義すると不自然になるのではないか。

不自然さを解決するためにドメインサービスというオブジェクトを作る

class UserId {
  constructor(private readonly id: string) {}
}

class UserName {
  constructor(private readonly name: string) {}
  public getName() {
    return this.name;
  }
}

// ドメインサービスに重複チェックのメソッドを移行
class UserService {
  constructor(private readonly user: User) {}
   public exists(newName: User): boolean {
    return (user.getName() === newName.getName()) ? true : false;
  }
}

class User {
  constructor(private readonly id:UserId, private name: UserName) {}
  public getName() {
    return this.name;
  }
}
const userId = new UserId('3');
const userName = new UserName('yunosuke');

const user = new User(userId, userName);
const userService = new UserService(user);

const duplicateCheckResult = userService.exists(user); //自分の名前の重複チェックをドメインサービスで確認している
console.log(duplicateCheckResult);
  • UserServiceクラスを作成してexistsメソッドを移行
    • メソッド実行時のuserService.exists(user);ドメインサービスを使うことで不自然さをなくしている

ドメインモデル貧血症

やろうと思えば全てのメソッドをドメインサービスに定義できますが、それをするとドメインオブジェクトはどんなルールを持っているか?など、何もわからなくなってしまいます。

このような自身の語るべきことを何も語っていないドメインオブジェクトの状態をドメインモデル貧血症と言います。

どうすると良いか?

  • ドメインサービスには、ドメインオブジェクトに定義すると不自然なものだけにする
    • 迷ったらまずはドメインオブジェクトに定義するようにする
    • 可能な限りドメインサービスに定義するべきではない

参考

ドメイン駆動設計入門 ボトムアップでわかる!ドメイン駆動設計の基本