ドメイン駆動設計入門を3回読んで個人的に大事だと思ったことを並べてみた!

2022/03/25に公開

今回はDDD界隈で有名な成瀬さんの著書「ドメイン駆動設計入門」について書いてみようかと思います!この本は発売初日に買わせていただいて、実践的でわかりやすく実務でも大変お世話になっている大好きな本の一冊です。そこで今回は1年ぶりぐらいに読み直してみて個人的に改めて大事だなと思ったことを書いてみます。本のまとめとかの記事ではないので、そこら辺は悪しからず!

なぜ今ドメイン駆動設計か

ソフトウェアは変化するものです。ごく最初期の局所的な開発速度を優先したソフトウェアは、柔軟性に乏しく、変化を吸収しきれません。ソフトウェアに求められる変化に対応するために、開発者は継ぎはぎのような修正を重ねます。数年もすればソフトウェアは複雑怪奇な進化を遂げるでしょう。

この部分は中堅以上のエンジニアであれば、思い当たる経験があるのではないでしょうか?自分の乏しい経験を振り返っても以下にあげるような状態のソフトウェアばかりと向き合ってきました。。

  • FatController
  • 散財したビジネスロジック
  • 依存関係が多すぎる共通ライブラリ

ドメイン駆動設計はドメインと向き合うことで分析から設計、そして開発までが相互作用的に影響し合うよう努力を重ねることができます。ソフトウェアを構築する最初期においても一定の効果はありますが、その真価は変化に対応するときにこそ現れます。

特に自分がやっているようなSaasとかだと顧客要望や競合対策、または技術進歩に合わせて変更要求が絶えず上がってきます。そこで大事なのが「変更しやすいソフトウェア」なんですよね!特にビジネス上重要(価値を生み出す)なコアな部分ほど複雑かつ変更が発生しやすい気がしていて、そこを設計する時にROIが高いアプローチがドメイン駆動設計だと思っています。

値オブジェクトを採用するモチベーション

※値オブジェクトとはについては、ぜひこの著書を読んでいただければと思います。
本書では値オブジェクトを使うモチベーションとして以下の4つを挙げています。思い返すとこの辺りをしっかり意識していないせいか、前のプロダクトではとりあえず値オブジェクト作ってました。。反省です。

  1. 表現力をます

プリミティブな値を利用した製品番号

var modelNumber = "a20421-10001";

値オブジェクトで表現した製品番号

class ModelNumber
{
  private readonly string productCode;
  private readonly string branch;
  private readonly string lot;
  
  public ModelNumber(string productCode, string branch, string lot)
  {
    if (productCode == null) throw new ArgumentNullException(nameof(productCode));
    if (branch == null) throw new ArgumentNullException(nameof(branch));
    if (lot == null) throw new ArgumentNullException(nameof(lot));
    
    this.productCode = productCode;
    this.branch = branch;
    this.lot = lot;
  }
  
  public override string ToString()
  {
    return productCode + "-" + branch + "-" + lot;
  }
}

比較すると上のプリミティブな値の場合では、実際にデバックしないとどんな値が入っているのかはわかりませんが、値オブジェクトで表現するとプロダクトコード、枝番、ロットで構成されていることがわかります。
ここは読んでいて「あ、こういうモチベーションもあるのか!」と3回目でハッとさせられました。。。
他にも以下のようなモチベーションが本書では紹介してありますが、ここでは割愛させていただきます。
2. 不正な値を存在させない
3. 誤った代入を防ぐ
4. ロジックの散財を防ぐ

可能な限りドメインサービスは避ける

ドメインサービスの濫用はデータとふるまいを断絶させ、ロジックの点在を促す行為です。ロジックの点在はソフトウェアの変化を阻害し、深刻に停滞させます。

データとふるまいをもったオブジェクトを作成し、それを組み合わせてユースケースを実現する所謂オブジェクト指向プログラミング的な開発に不慣れなだとこれやっちゃいがちだと思います。前のプロダクトでも気づいたらドメインサービスにメソッドがいっぱいになっていました。。
これ放置しちゃうと共通化ライブラリの問題のように重複したロジックが散在したり、表現力に乏しいアプリケーションサービスの実装になるので気をつけないといけませんね。

ドメインルールの流出

アプリケーションサービスはあくまでもドメインオブジェクトのタスク調整に徹するべきです。アプリケーションサービスにはドメインのルールは記述されるべきではありません。もしもドメインのルールをアプリケーションサービスに記述してしまうと、同じようなコードを点在させることになります。

これもあるあるだと思います。アプリケーションサービスにちょっとif文追加したり、for文追加したりしてとりあえず動くようになりましたー的なPR投げていないですか?
これもドメインサービス濫用問題と同じような問題が発生するので避けるべきです。
if文であれば判定用のメソッドをもつドメインオブジェクトにロジックを定義し、for文とかであればファーストクラスコレクションなどが使えないかなってとこから考え始めるのでもいいかと思います。

まとめ

以上、簡単ですが改めて大事だなと思った部分についてつらつらと書いてみました!
本当に何回読んでも価値がある本だと思うので、ドメイン駆動設計やオブジェクト指向プログラミングを学びたいと思ってる方にはとてもお勧めの本です。コード例もたくさん載っているので結構助かります。
これからも技術書についての感想などをアップしていくつもりですのでよろしくお願いします!

Discussion