TL;DR

  • 関数型プログラミングを学んで、低レベルのコードから設計やアーキテクチャまで、プログラミングのやり方がすべて変わった。
  • 継承やインターフェースの代わりに関数を引数に取り、パイプラインで小さな関数を組み合わせ、エラーは値で返し、I/O は端に寄せる。

内容

録画された講演で、日本語字幕の書き起こしをもとにまとめた。

関数型プログラミングの 5 つの考え方

Scott Wlaschin の定義では、関数型プログラミングの要点は 5 つある。関数は文字列や整数と同じように扱えるものであること、関数はルックアップテーブルのように決定的でデータは不変であること、小さな関数を合成して大きなものを作ること、型はクラスではなく値の集合であること、小さな型を and と or で組み合わせて大きな型を作ることである。

関数を引数にする

ハードコードした処理を関数の引数に変えれば、汎用的になり、各ケースの違いも見えやすくなる。関数型はそのままインターフェースとして働き、型が合う関数なら何でも渡せる。そのため継承はほぼ使わず、インターフェースもあまり使わない。

パイプライン指向

F# の |> のように、関数の出力を次の関数に渡してつなぐ。データが一方向に流れるので、オブジェクト同士が呼び合うより理解しやすい。ローマ数字の変換では、置換関数を「関数を返す関数」にしてパイプラインに収める。後から処理を足しても既存のコードを変えずに済み、オープン・クローズドの原則も自然に満たせる。

ドメインモデリング

レコード型(and)と選択型(or、判別共用体)を組み合わせてドメインを作る。支払い方法の例では、OOP ならインターフェースと 3 つのサブクラスになるところを、数行の型で書ける。型はコードとして実行できるドキュメントにもなる。

エラー処理

メールアドレスなどはラッパー型にし、コンストラクタで検証すれば、後で何度も検証しなくて済む。失敗し得る関数は null や例外ではなく option や Result を返す。Result を返す関数は bind でつなぎ、これを Wlaschin は鉄道指向プログラミングと呼んでいる。

テストとアーキテクチャ

すべての関数に入力と出力を持たせ、ビジネスロジックは決定的に書く。I/O はパイプラインの端に寄せるので、中心はモックなしで単体テストでき、全体は統合テストで確かめる。関数型コア・命令型シェル(Functional core, imperative shell)の考え方と同じく、ビジネスロジックを中心に置き I/O を外側に置く構成を、Wlaschin はドメイン中心アーキテクチャと呼ぶ。

キーワード

関連