「関数型ドメインモデリング」の日本語訳が出たので読んでみた(後編)
(続きは来週かな?)
さて、前編を公開したのっていつでしたっけ……?
すみません、いろいろ立て込んでる間に2週間くらい経っていました。「関数型ドメインモデリング」、続きである第3部を読み終えたので、その感想を書きなぐっていきます。
ヒエッ
感想
第3部 モデルの実装
第8章 関数の理解
この章では、関数と関数合成について説明。関数プログラミングとは、「関数が非常に重要であるかのようにプログラミングすること」。
関数型とオブジェクト指向でのアプローチの違い:
- オブジェクト指向
- プログラムのパーツは、クラスやオブジェクト
- パラメータ化には、インタフェースや依存関係の注入を使用
- 再利用には、継承やデザインパターンを使う
- 関数型
- プログラムのパーツは、関数
- パラメータ化には、関数を使用
- 再利用には、再利用可能なコードを関数にまとめ、関数合成を使う
『8.2 「もの」としての関数』で、再び線路のメタファーが出てきた!あと、ここでようやく「カリー化」「部分適用」に言及。『8.3 全域関数』ではある関数で、すべての入力を有効にする、またはすべての出力を有効にする、2つのアプローチを確認。
第9章 実装:パイプラインの合成
第2部までに作った型を使って実装していく。型(関数シグネチャのエイリアス)を使用するため、実装はラムダ式で作ってる。『9.3.3 関数アダプターの作成』では、今回用のチェック関数を作っていたはずなのに、いつの間にか一般の状況に使える関数になっていたという、話の運び方が上手いですね。そして、こういう関数は実際けっこう作っちゃうというのもリアルな話。
- 「今では」すべて同じ型、とは?
ここで使っている「持ち上げ」(liftのことかな)はよくやるテクニックなので、こういうのが出てくるのは良いですね。『9.6 依存関係の注入』で、どのように依存関係を外から持ってくるかの指針を出しているのは良いポイント。あとサラッと Suave も紹介してるw
第10章 実装:エラーの扱い
エラーの種類を3つに分ける(ドメインエラー、パニック、インフラストラクチャエラー)。多くのインフラストラクチャエラーは、エラー時の動作を考える必要がある点で、ドメインエラーと同じように扱う方が良い。
そして、ここでようやく線路が枝分かれした!!(歓喜w)文中にもちゃんと「鉄道指向プログラミング」(日本語訳 by yukitosさん)の文言も出てきて一安心w それにしても、すごくすんなり bind
や flatMap
を持ってきたのは本当に上手い。
この章(10.6)で、きっと出てくるだろうと思っていた「コンピュテーション式」も紹介されましたね。10.7でモナドについても軽く説明していましたが、まさかアプリカティブ(Applicative)にまで触れると思っていなかったのでびっくりしました。この本、思った以上に関数型のいろいろを取り込んでますね。
第11章 シリアライズ
ワークフローの入出力(ドメインの外部とのやりとり)にシリアライズや永続化が必要。ドメインオブジェクトをそのままシリアライズするのは難しいので、DTOをシリアライズすることを考える。
JSONのシリアライズに Newtonsoft.Json
を使っているのは時代を感じる。(左記ライブラリが無くなった訳じゃないけど、本丸の.NET Coreに System.Text.Json
が来て、デファクトではなくなったので)
第12章 永続化
永続化などのI/Oは、ドメイン中心的なビジネスロジックの外側に追い出す(ビジネスロジックは純粋な関数にする)。リポジトリパターンは出てこなくて良い(オブジェクト指向におけるデザインパターンなので)。
クエリ(読み取り)とコマンド(書き込み)のコードを分けるCQS(コマンドクエリ分離の原則)。データストアを入力にとって、何らかの変更を施して新しいデータストアを返すというの、この前勉強してた Flux パターンみがありますね(この後、データストアは返さずにユニット型に変わっちゃうけどw)。クエリとコマンドのモデルを分けることで、CQSはCQRS(コマンドクエリ責務分離の原則)に。
データベースにおける集合指向の操作(SELECT、WHERE)は、関数型言語におけるリスト指向の操作(map、filter)と似ています
これはまさにLINQなのだよねぇ。
この章で、タイププロバイダ(型プロバイダ)が出てきました。上手く使えば便利なのかもしれないけれど、僕はあまり型プロバイダは使いたくない派ですね。
第13章 設計を進化させ、きれいに保つ
この章では、場合分け(条件分岐)の作成にアクティブパターンを使いました。ホント、F#(または関数型)のいろいろを、必要な場面で使ってくれますね。
いくつかの「仕様変更」(本文中では「要件変更」)に対するドメインの変更を見ていますが、簡単なものから実は面倒くさいものまであり、考え方や変更の仕方の参考になります。また、依存関係を外部から注入するための関数を差し替えられるよう、ファクトリ関数(引数を取って関数を返す関数)を導入したのもよくやる形かと思います。
まとめ
前後編を通して、ドメイン駆動設計とF#(および関数型プログラミング)をみっちり使った、非常に読み応えのある書籍でした。それなのに最後の章まで、DDDとF#の両方とも知らなかったとしても問題ない程度にそれぞれの説明も行われており、本書を読み終えることでこれらの知識を底上げできるというのも推したいポイントです。もちろん、知っている人にも「あぁ、これはそうだよね」とニヤリとさせるようなポイントが多くあるので、幅広い層にオススメできる一冊だと思います。
ドメイン駆動設計も関数型プログラミングも、今やどちらも「基本の1つ」としてソフトウェア開発の世界に馴染んでいます。そうでなかった時代を知っている者からすれば感慨深いわけですが、だからこそ「ドメイン駆動設計と関数型プログラミング、両方使ったって良いよね?」という時代が来るのも必然なのかもしれません。本書で紹介されているのはあくまで架空のソフトウェアシステムですが、設計の考え方やソフトウェアが成長していく様は実世界の私たちのソフトウェア開発と幾ばくも変わらないと感じます。
素晴らしい本を書いてくれた Scott Wlaschin 氏(ずっと前からF#の発展に携わってくださった御仁)と、本書を日本語読者にやさしい形でつなげてくれた猪股健太郎氏(@matarilloさん)に大きな感謝を示して、この拙い感想文の締めとさせていただきます。
Discussion