「関数型ドメインモデリング」の日本語訳が出たので読んでみた(前編)
1ヶ月ほど前にこんなツイ……ポストを見かけました。
ドメインモデリングをF#でやるとは興味深い……、ってこの著者めっちゃ知ってるわ(昔からフォローしてる人)、と思ったので、発売を楽しみにしてました。
で、先日のこのツイート:
という訳で、「関数型ドメインモデリング」読み始めたので感想書いていきます。今日は第2部「ドメインのモデリング」まで読みました。メモ書きみたいな感想ですが、本当に読んで思ったことをメモ書きしてました。
感想
推薦のことば、日本語版へ寄せて、訳者まえがき
ドンちゃん、マイケル・フェザーズなど原著に向けた推薦、著者であるスコット・ヴラシン氏からのメッセージ、訳者前書き。
はじめに
本書の目的(対象者、内容)を示している。関数型プログラミング、ドメイン駆動設計については本書内で説明していくので、馴染みがなくても大丈夫だと安心させてくれる(F#初心者の感想です)。ここまで読んで、第2部「ドメインのモデリング」の内容に興味が深まってきました。
避けて通りたくなる「モナド」
モナド, コワクナイヨ...
太陽が昇るのと同じくらい確実に、要件は変化します。
「コーラを飲んだらゲップが出るっていうくらい」確実なことですね。
Twitterの“#fsharp”タグをフォロー
Twi ... Xの #fsharp タグは便利なので、眺めてみるのはオススメ。
- プログラミングの「腰袋」?原著の記載が分からないけど"waist bag"?あるいは"tool belt"の意訳かな。
- 少し後に「ツールキット」って出てきているので、tool belt <-> tool kitの対応はありそう。
第1部 ドメインの理解
第1章 ドメイン駆動設計の紹介
「ゴミを入れれば、ゴミが出てくる」
耳が、胸が、痛い。。。
入力(要件)に対する「ゴミを入れる」部分を最小限にするやり方として、ドメイン駆動設計を用いるという流れ。
ドメインをイベントベースで探索し、イベントの端までイベントとワークフローを見出す作業。そのあとイベントがコマンドを引き起こし、コマンドによりワークフローが実行され、結果が新たなイベントとしてつながる、という関連を見えるようにする。
コンテキストを区別する(境界づけられたコンテキスト)。1つのコンテキストに別ドメインのエキスパートが複数関わっている場合、コンテキストを分けた方が良さそう。同様にワークフローが複数のコンテキストと相互に作用して、場合によってはブロッキング(待ち)があるなら、設計面の整然性よりビジネス面のスムーズさを優先する。また、コンテキスト(ドメイン)には優先順位(重要度)をつけよう。
- 血圧降下剤?
第2章 ドメインの理解
ドメイン駆動設計では、データベースのスキーマではなく、ドメインから設計を導き出します。
ドメインをもとに設計を始め、特定のストレージの実装を考慮せずにモデル化するのが良いのです。
ここの表現好き(永続性非依存)。
クラス駆動の設計は、データベース駆動の設計と同じくらい危険です。
これは僕もやりがちなので気をつけたい。
あなた:「数量は整数ですか、それとも浮動小数ですか?」
著者も職業病かな?普通こんな聞き方(浮動小数)しないでしょw
ドメインをプログラミング等の既存技術に依存しない言語(擬似コード)で記述する。制約条件(数量など)やライフサイクルも表現する。
data PlacedOrderAcknkowledgment =
PricedOrder
AND AcknowledgmentLetter
Placed と Priced が乱立してて目が泳ぐ。。。
第3章 関数型アーキテクチャ
マイクロサービスの1つを停止したら他のものが失敗する場合、それは本当のマイクロサービスアーキテクチャではなく、分散モノリスにすぎません!
この言い回しも好き。
コンテキスト間は「イベント」でやり取りし合う、という内容、この先まだ読んでいないけど、いわゆるpub/sub的なアプローチを意図しているわけではない(何らかの非同期なコミュニケーション)、ということかな?
信頼の境界線と検証の話は、DDDに限らず大事。入力も出力も、外の世界は信用しない。入ってきてよいか/出してよいか、ゲートが必要。
これと少し関連する「腐敗防止層」の話もあり。こっちは検証というよりも、外からの入力(DTO)を自コンテキストの語彙(ドメインオブジェクト)に変換するイメージ。
オニオンアーキテクチャについても取り上げてるけど、この項で直接説明はせず、次の「I/Oを端に追いやる」で意図を示してる。
- 「開始する必要がよくあります」、あまりしない言い回し。「必要がある」は制限(restriction)や強制(restraint)で、「よくある」は頻度(frequency)や可能性(probability)なので、おなじ「ある」だからといって共起させない方が良いかも。「開始しなければならないことがよくあります」とまで言っても問題ない気がします。
第2部 ドメインのモデリング
第4章 型の理解
F#の「代数的な型システム」
判別共用体(discriminated union)かな?期待。
「関数の理解」の章で、図に唐突に線路(railway)が出てきたので期待が高まる。
'Person'という型
東北と中国がない……(どうでも良いコメント)。
「代数的な型システム」=すべての複合型が、より小さな方をAND(レコード型)またはOR(判別共用体)で合成してできているもの。なるほど、これは良い答え合わせ。
let anOrderQtyInKG = KilogramQUantity 2.5
ここ、 2.5
が float
と推論されるから、 2.5M
ってやった方が良いよね。
let printQuantity aOrderQty =
match aOrderQty with
| UnitQuantity uQty ->
printfn "%i units" uQty
| KilogramQuantity kgQty ->
printfn "%g kg" kgQty
ここ、よく以下のようにやりがち(match
式を省略)。
let printQuantity = function
| UnitQUantity uQty ->
printfn "%i units" uQty
| KilogramQuantity kgQty ->
printfn "%g kg" kgQty
型の合成によるドメインモデルの構築、F#の型の良いところをサラリと紹介してる。関数(引数と戻り値のシグネチャ)も型に落とし込んでいる(この後に紹介されてるエイリアスである型略称を使っている)ので、これを今後どう使うのか楽しみ。
この章で Option
型や Result
型などを紹介しているのも良いですね。
最後の module rec
の話、単に定義順序の面で楽をしているだけなら後で依存関係順に並べることもできるけど、相互依存関係の型があると rec
は外せないことも気をつけておきたいですね(参考)。
第5章 型によるドメインモデリング
どちらも int で表されているからといって、互換性があるわけではありません。
そうなのよね。それを防ぐために、型で名前をつける(型略称も含む)やり方は F# でよくやるイメージ。
type ValidateOrder = UnvalidatedOrder -> ValidatedOrder
来ました、関数の型表現。ワークフローもモデリングの対象。
「本当の」入力ではなく依存関係にある場合、別々のパラメーターによるアプローチを使用したいと思います。
この考え方良いなぁ。すごく参考になる。
関数型プログラミングの人々は、エフェクトという言葉を使って、関数が主な出力以外に行うことを説明します。
え、そうなんだ(初耳)。ここのエフェクトって side effect とかのエフェクト(つまり作用)よね。そうすると「主な出力」もエフェクトの1つだと思うんだけど。
集約は単なるエンティティの集まりではありません。
集約の話が出てきた。「トップレベルエンティティを集約ルートに」「集約は整合性の境界」は大事な概念。
あなたが開発者ではない人だと想像してみてください。このコードをドキュメントとして理解するためには、何を学ばなければならないでしょうか。
ここに挙げられている、単純型、AND型、OR型、「プロセス」と、あと英語かな……。
第6章 ドメインの完全性と整合性
スマートコンストラクタは、この名前を使うかどうかは別として、使ってるのは関数型プログラミングの界隈だけじゃない気もしますね。とはいえ、「ちゃんとした」コンストラクタが使える言語ではそもそも意識しないところかもしれないですが。
完全性に関する話題では、 VerifiedEmailAddress
の導入ももちろん良かったんですが、 ContractInfo
を持ってくるくだりは F# (または関数型プログラミング)の良いところが滲み出てますね。
1その代わりに、
あっ、これは脱字かな。。。(P.110)
第7章 パイプラインによるワークフローのモデリング
本書で一貫して取り組まれているのでこの章でもそうなんだけど、「設計上の困りごとは型で解決」というのが本当に良いですね。とかく「フラグ」を使いたがる人も多いんですが、状態を型で簡単に表現できる(かつ不正な型は実行時ではなくコンパイル時に弾いてくれる)ところがF#(または関数型プログラミング言語)の良いところの1つかと。
Resultがどこかで使われると、それが触れるものすべてを「汚染」してしまうので、それを処理するトップレベルの関数にたどり着くまで、「Result型を扱うこと」を引き継ぐ必要があります。
この先、モナドで解決しそうな雰囲気(また楽しみが増えたぞ)。
7章で一気に型が雄弁になりましたね。定義やシグネチャで喋らせて、「こういう意図があるんだ」というのを読み手に強く伝えられる型がたくさん出来上がったと思います。これが「ドメインを伝達できるコード」だというのがよく分かる章だったと思います。
前編のまとめ
第2部までざっと読み進めましたが、難解な内容はほぼ無くて、F#についても本書に必要な文法的な説明もされながら話が進んでいくので、読みやすい内容だと思います。ドメインモデリングの書籍としても説明ポイントを押さえているので、分かりやすいです。
ただ、感想の中でちょっと期待してた「鉄道志向プログラミング」に触れられてなかった(第2部まで)のが残念……w
いずれにせよ、残る第3部に期待が高まる素敵な訳書です。(続きは来週かな)
Discussion