ドメイン駆動設計入門を読んで

junichi_y
·
公開:2023/12/18

ドメイン駆動設計入門を読了しました。

控えめに言って最高でした。

エヴァンス本に心を折られた過去

張り切ってDDDを学ぼうとしたころが私にもありました。どうせやるなら原書でしょということでエヴァンス本を買い、想像以上の分厚さに読み始める前から心折れそうになりながらも一生懸命読みました。

わからないことはないんです。非常に難解で難しい概念が出てくるわけではないので。ただただ抽象的すぎてイメージがわかないんです。これは設計関係の技術書全般にいえる。

読みかけで放置が性格的にできないので斜め読みで最後まで駆け抜けました。

単体テストの考え方/使い方を読んで

最近読みました。超良かったです。まじで。

この本読んで良い単体テストを書くには「ドメインの扱い」と「関数型」の知識が必要だと思い、ドメイン駆動設計入門の購入にいたりました。

関数型は最近Elmに入門して少し仲良くなりました。

ドメイン駆動設計入門の感想

値オブジェクトから始まりエンティティ、リポジトリ、サービスといったDDDで登場する用語を丁寧にわかりやすく解説してくれます。これでもかというくらい丁寧に解説してくれます。きっと、著者もDDDが難解だということはわかっていて読み手を置いてけぼりにしないようにひとつひとつ解説してくれてる感じがしました。

加えて、サンプルコードがわかりやすい。設計関係の技術書に載ってるサンプルコードってあんまりピンとこなくて読み飛ばしちゃうことも多かったんですがこの本のコードは非常にわかりやすかったです。

案の定集約の話で少しむむっとなったけどなんとなく理解しました。ただ、集約の区切り方みたいなのが難しそうと思いました。実際のプロダクトでビジネスロジックをちゃんと適切な単位で集約に分けられるか微妙だなと。これはたぶんやるしかないんだろうな。モデリングの練習したい。。

アーキテクチャについて

今までのアーキテクチャについての苦悩の流れ。

→ クリーンアーキテクチャ読む

→あんまりピンとこない

→ オニオンアーキテクチャでわかたった気になる

→ 単体テストの考え方読む

→ インターフェースいらない!レイヤーも最低限でいい!クリーンじゃなくてもいい!

→ ドメイン駆動設計入門読む

→ DDDでいうところのアプリケーションサービスでロジックを書かない。リポジトリとドメイン知識の結合をやる。これができてればアーキテクチャは何でも良いという気持ちになる。 ←今ココ

どうしてもこの類の話になるとパッケージ構成を気にしてしまう。これは使ってる言語やフレームワークにもよるので気にしすぎないことにした。たぶん正解はない。各々俺が考えた最強の...を考えて実践しているんだろう。(わたしもそうです。)

三層アーキテクチャの呪縛

わたしはJava + Springが母国語なのでController, Service, Repository, Entityといったクラスを作ることでアプリケーションを開発してきました。JavaやSpringが悪いわけではないけどビジネスロジックはServiceに全部突っ込むというスタイルが染み付いてしまった。

入口Controllerはまあいい。永続層をRepositoryもまあ大丈夫。Entityという用語がややこしい。ORMとしてのEntityとクリーンで出てくるEntitiesとDDDのEntityが全部違うのに用語がいっしょだから困惑する。まじでなんでこうなった。もはやクリーンアーキテクチャやDDDについて学んだ人とじゃないと同じものを指して会話ができる自信がない。

Service層に全部突っ込むスタイルは本当に悪。まじでテスト書けなくなる。これが辛すぎてUserServiceからUserComponentみたいなものを呼び出すスタイルでやったりもしたけどこれは結局DDDとかでいうアプリケーションサービスとしてUserServiceを機能させたんだなと今なら思う。

単体テストの考え方とドメイン駆動設計入門は2冊ともアプリケーションサービスの部分の実装を具体的なコードで書いてくれてるので、やっとなんで今までのスタイルが辛かったのかピンときた。

三層アーキテクチャが悪いわけではなくテストが書けないfat service状態が悪なんだけど三層アーキテクチャがServiceクラスに全部実装しろと言ってるわけでもなく普通にドメインオブジェクトを作って使いなさいよと言われればそうなので結局自分の無知さが1番悪い。

GoとDDD

Goはオブジェクト指向言語として認知はされてないけどオブジェクト指向言語っぽいことはGoでもできるってたしかかとじゅんさんが言ってた。

オブジェクト指向をオブジェクト指向たらしめているのが継承とカプセル化とあと一つなんだっけ...っておっしゃられていた。

なんでGoでDDDはできるはず。で、実際読みながらコードは全部Goで書いた。

書けるけどむずい。終始Goっぽくないことをやらなきゃいけなくなる。パッケージの切り方もむずい。関数や構造体の命名もむずい。Goのパッケージに意味を持たせるみたいなやつがむずくさせる。user.New()みたいなこと。userパッケージのNew関数の呼び出し。こういうのがGoの文化として認知されてるのがGo特有だよなと思う。

DDDやるなら素直にKotlinとかクラスベースの言語の方がやりやすいだろうなと思う。

でも、最近のトレンドとして需要的にも供給的にもGoの勢いはダントツなのでKotlinとかScalaとかがGoに迫ることはないだろうなと思う。

そうなると、Goでプロダクト作るのが合理的、採用的に考えると。Rustがワンチャン次のGoだと思ってるけどRustもクラスベースの言語ではない。RustでDDDがやりやすいのかはまったくわからない。

今から本気でDDD取り組むぞという組織がどれだけいるかという話にもなるがもし本気でDDDやってきますっていうのならKotlinとかのほうが無駄に悩まなくて良さそうだなと思った。

(採用技術にDDDって書いてるスタートアップとかみるとまじで?ってなる)

軽量DDDについて

アンチらしい。ただ、形だけDDD適用させてDDDやった気になってるのがアンチなんだと思う。そこでDDD終わりじゃないから!!みたいな

ドメインエキスパートとの密なモデリングは最初から捨てて、とにかくドメイン層の実装方針としてDDDのテクニックを使うのはありなんじゃないかなーと思う。

そうしないと結局fat Serviceが生まれることになり、テストも書きづらくなる。ただ、ドメインオブジェクト作り出すとどこまでちゃんとやるんですか?みたいになりそうで難しいなーと思う。

ここらへん実際のプロダクトで試行錯誤するしかないからすぐ答えが出せないよね。

まとめ

ドメイン駆動設計入門読んでよかった。めっちゃよかった。あとは読んだだけで終わらないように実際の開発で試行錯誤して自分のスタイルに昇華させていきたいなと思います。

@junichi_y
エンジニアしてます。