関数型デザイン 原則、パターン、実践 | Robert C.Martin, 角 征典

近頃のボブおじさんはClojureにハマっていた

まずこの書籍で話題となる点は、この書籍がClojureをサンプルコードに使っているところ. 書籍ではJava/Clojureの両方の言語がでてきて、それらのコードを比較しながらオブジェクト指向プログラミングと関数型プログラミングを比較していく. 以下ポエム.

オブジェクト指向設計の英雄ガープ中将みたいなボブおじさんがClojureにきたぞ?

わたしはClojureについてたまにネットで情報収集をしているのだが, 日本語でClojureの情報を探してもイマイチなことは気になっている. Qiitaの投稿も最近なんか減ってる気がする1. 英語圏はどうなんだろう, そこまでアンテナを貼ってない. ただ, 若干の下火トレンドを感じている今日この頃, なんとオブジェクト指向設計界隈を牽引したレジェンドRobert C. martin(通称ボブおじさん)がClojureの書籍を発売した.

これにはとても驚いた. かつてのAgile/オブジェクト指向設計のレジェンドボブおじさんがClojureをアピールすることで, PythonやTypeScriptに比べて圧倒的に人気のないClojureはここからライジングするかもしれない. これを喩えるならば, いきなりワンピースに出てくるかつての海軍の英雄ガープ中将2が戦力に加わって百人力を得たようなものだ.

Clojureは最後の言語だ、Clean な言語とはClojureだ!

昔からボブおじさんのファンだったので, 最近の彼はなにをしているのか数年前に調べてみたところ, 愉快なYoutuberを目指しているような活動に笑ってしまった. もうなんかプログラミングを楽しみながら好きなことをしているようだった. しかし, 動画の中身をみてみると, なんとやたらとClojureばっかり推していることは知ってた.

たとえばこの動画. なんでカーボーイの帽子?と誰もがまず突っ込むかもしれない. 動画のなかでは1時間かけていろんな言語の特性を比較しつつ, 最後の結論でClojureが素晴らしい!となっている. The Last Programming Languageとは, いろんな言語を経験したボブおじさんが最後にたどり着いた言語, という意味だろう.

また, この3分くらいの動画3では, Clean Languageとはなんですか?という質問にClojureだといっている.

Clean Codeを愛するボブおじさんがエレガントなClojureに魅了された

また, 今から10年前にClean Codeという書籍を読んで, まだ未熟だったわたしは感銘を受けたことを過去の記事4を読んで思い出した. Clean Codeとは具体的になんなのだ?と思い, ボブおじさんのGitHubをみてFitnesseのコードを読んだ思い出. さらに, 書籍のなかでエレガントなセンスという言葉に引っかかったことも思い出した. 以下Clean Codeからの引用.

洗練したコードを書くプログラマというのは、まっさらな画面に変形を加えていくことで、エレガントにコーディングされたシステムを造りあげる芸術家なのです。

エレガント. 今思えば, この言葉はClojureの文脈でも思い出すことがある. それは, 日本語訳されているClojureの書籍だと定番の書籍, Programming Clojure5のまえがきの一番初めの有名な言葉がある.

Clojure はエレガントだ。明快で慎重な設計により、余計なオマジナイや儀式抜きで、問題の確信を直接プログラムとして記述できるようになる。

勝手な結びつけかもしれないが, Clean Codeを愛するボブおじさんがClojureにやってくることはもやは必然だったかもしれない. 過去記事を読み返してそんなことを思った.

関数型デザインとはオブジェクト指向設計か

読書感想文を書くにあたって, タイトルの「関数型デザインとはXである」みたいな文章は書籍内にあったかな?と見返してみたのだが, みあたらない. 見落としているだけかもしれないが. しかし, この書籍の目的は、序文にある.

多くの人たちが、オブジェクト指向プログラミングと関数型プログラミングには互換性がないと主張している。本書では「そうではない」ことを証明したい。(中略)私の経験からすれば、この2つのスタイルは完全に互換性がある。(p23).

そして, その証明のために, SOLIDの原則やデザインパターンが章を割かれて詳しく説明されている. また、TDDだったりUMLだったり、オブジェクト指向言語っぽいプラクティスもJava開発のように導入される。

ということで要約すると, 「関数型デザインとはオブジェクト指向設計だ」のようにわたしは解釈した.

デザインパターンはOO言語のハックでないことを証明する

デザインパターンというとGoFデザインパターン6が有名でオブジェクト指向設計のものというイメージが強い. それをまず, デザインパターンという言葉の定義から違うという.

これがデザインパターンだ。特定のコンテクストにおける共通の問題に対するソリューションに名前をつけたものである。(p329)

さらに, Abstract server patternというGoFにはない例を引用する.

さらにさらに, Javaで実装する類のGoFデザインパターンはClojureでも同じように, 場合によってはClojureのほうがシンプルに実装できることを, GoFパターンを次々引用しながら説明していく. Adapter, Command, Composite, Decorator, Visitor, Abstract Factory… ほらね、ほらね、みんな互換可能だ!ここで紹介しなかったパターンは演習問題だ!みたいな.

Clojureでのオブジェクト指向設計の実現方法

ここからはClojureも絡めた感想.

マルチメソッド使いまくりにマルチメソッド弱者の私は驚いた

驚いたポイントは, サンプルコードでマルチメソッド使いまくりだったこと. 逆にプロトコルは一度も出てこなかったこと.

Clojureのプログラマーは、ポリモーフィズムを表現するためにdefmultiとdefmethodを頻繁に使用する。(p402)

なぬ、そうだったのか!!というのも, わたしの愛用書Programming Clojureには, 「8.5いつマルチメソッドを使うべきか」というトピックで,

一番目についたのは、マルチメソッドは滅多に使われない。

という言葉を信じマルチメソッドを使わないどころか、あまり深く理解もしてなかった…真逆じゃないか.

ClojureにはExpression problemのための操作抽象としてプロトコルとマルチメソッドの2つの手段があり7, Clojure初学者のときここの理解に苦労した.

同じような疑問の記事はStackoverflowにもあり8, 基本方針としてはたいていはprotocolsでいい, multimethodはより表現力があるもののコストがかかるので必要なときに限りmultimethodを選ぶのような理解だった.

Protocols provide efficient polymorphic dispatch based on the type of the first argument. Because the is able to exploit some very efficient JVM features, protocols give you the best performance.

Multimethods enable very flexible polymorphism which can dispatch based on any function of the method’s arguments. Multimethods are slower but very flexible.

In general, my advice is to use protocols unless you have a specific case that requires multimethods.

Clojureは名前空間で依存関係を管理すればオブジェクト指向だ

驚いたポイントその2は, ソースファイル分割して名前空間分割しまくりだったところ. Clojureのデータ抽象には素のMapや, better Mapであるレコードがあり, レコードとプロトコルを組み合わせるとJavaのクラスっぽいものが書けるという理解だった.

しかし、この書籍における最大の主張は「Clojureは名前空間で依存関係を管理すればオブジェクト指向だ」ということだ. このことについては, 第16章「追記:オブジェクト指向は有害?」という章で議論されているが, 追記どころかここが書籍の主題な気がした. ここに一番感動した. 以下, 少し引用.

カプセル化されたデータ構造(つまり、オブジェクト)を表現するためにマップを使用する。オブジェクトのコンストラクターも構築する。彼らは気づいていないかもしれないが、オブジェクト指向のプログラムを書いているのである。

雰囲気でClojureを書いていたわたしはオブジェクト指向プログラムを書いていた.

一部の関数プログラマー(さらには一部のClojureプロクラマー)が「普通でない」と思うのは、ソースファイルと名前空間の構成方法だろう。この構成は, Java, C++, C#, Ruby, さらにはPythonを思い出させる. 大昔にオブジェクト指向を忘れた人たちに「オブジェクト指向」と叫んでいる。 ClojureはJava, C++, C#, Python, Rubyと同じくらいオブジェクト指向的である。

書籍を読みながらJavaのオブジェクト指向プログラミングみたいだと思ったが, やはりここはみんなJavaっぽい思うだろうとボブおじさんがあえて狙って主張している気がした.

関数型プログラムは、インターフェースやクラス、型やサブタイプで記述することもできる。堅牢で、独立してデプロイ可能であり、独立して開発可能なアーキテクチャを実現するために、ソースファイルを分割して、 依存関係を管理することもできる。こうした点においては、なにも変わっていない。

つまり, 依存関係を名前空間でコントロールすることで, Clean Archtectureは可能であるということか? と, ここまで読んで, 似たような話題をどこかで読んだ気がして, 再度みつけたのがt_yanoさんのこの日本語のスライド資料9. 関数型デザインの書籍とスライドを合わせて読むと理解がより深まる, とても感謝.

関数型デサインとは大前提としてエンタープライズ大規模アプリケーションのためのもの

しかしそれにしても, マルチメソッドを使う使わないの議論や, ソースファイル分割しまくりなところは違和感もある. ここにつついて, 最終章ケーススタディで大事なポイントが強調される.

Wa-Torのようなシンプルなアプリケーションでは、徹底的にファイルを分割する必要はないだろう。実際、プログラム全体をひとつのファイルに書けばいいと悪魔がささやく。だが、我々はこれが大規模エンタープライズアプリケーションである「ふり」をしている。

「こんなにファイル分割しまくる必要あるのか?」というわたしの心の中の小さな声は想像力が足りなかった. 実際は, なにも考えなければ摩訶不思議ジャングルスパゲッティうんコードデスマーチが待っている炎上プロジェクトなんだ.

この視点はある意味, 書籍を読むときに念頭においておくべきところだと思う. もしこの読書感想文の記事を読んでから書籍を購入するならば「関数型デサインとは大前提としてエンタープライズ大規模アプリケーションのためのもの」ということを頭にいれておくべきかもしれない. そしてClojure大規模エンタープライズ開発とは実際世の中にそんなにあるのか?という現実もある. 人月の神話のためにはたくさんのClojureが書ける人が必要なのか?10 実際のところ, わたしがClojureが好きな理由はREPLであり型が無いところだったりする. そしてプロダクト開発ではなく趣味開発だ. わたしにとって関数型デザインは必要ないし、むしろやらないほうがいい.

See Also


  1. https://qiita.com/tags/clojure ↩︎

  2. モンキー・D・ガープ (もんきーでぃーがーぷ)とは【ピクシブ百科事典】 ↩︎

  3. Clean Code - Robert Martin (Uncle Bob), North Fireside Chat - YouTube ↩︎

  4. 散文的ブログラミングの哲学につら抜かれたCleanCodeでカルチャーショック体験 | Futurismo ↩︎

  5. プログラミング Clojure 第2版を読んだ | Futurismo, 読書感想文. ↩︎

  6. Gof デザインパターンの勉強メモ記事とブックマークまとめ | Futurismo, 駆け出しエンジニアだったころにGoFをJavaで全部実装して勉強したことを思い出して懐かしかった. いやむしろいろいろ忘れていて悲しかった. ↩︎

  7. ちなみに他の言語だとパターンマッチという機能かあるがClojureはパターンマッチよりもポリモーフィズムを好むのは設計思想らしい. Clojure Rationaleにある. Clojure - Rationale ↩︎

  8. Clojure multimethods vs. protocols - Stack Overflow ↩︎

  9. プログラミング言語とシステムデザイン | PPT ↩︎

  10. Nubankという大成功事例はある. Nubankについてあまり知らなかったのでこの機会に調べてみたらなかなか起業エピソードがエモーショナルだった. 記事にはClojureの単語がでてこないがClojureによる大規模マイクロサービス開発事例という驚きポイント. Nubank : 不可能への挑戦|Go ↩︎