👴🏼ボブおじさんの最新作, なんと📝Clojureだ!

Robert C. Martin. Functional Design: Principles, Patterns, and Practices.

第一部: 関数型の基礎

  • 不変性
  • 永続的データ
  • 再帰と反復

  • ここはかんたんな関数型プログラミング, というよりもClojureの基本的な特徴を説明.
  • しかもClojureのコードはでてこなくて概念的な説明なのであまり面白くないかな.
  • 状態遷移を例に関数型を説明するものの, 実際にClojureでFSMをやろうとすると貧弱すぎて困る.

🔦関数型プログラミングとは代入文のないプログラミング - Uncle Bob

まず第一の主張.

  • 不変性: 代入はしない.
  • 参照透過性: 関数プログラムは数学的な意味での関数.
  • 状態遷移は古い状態を変更せずにその都度状態を生成する.
    • スタック領域を食いつぶさないようにTCOが大事.

人生は難しい、ソフトウェアはさらに難しい

なにいってるんだ…

第二部: 比較分析

伝統的なOOとFPの比較分析.

ここはClean CraftmanshipのコードをJavaで書いたらこう, Clojureで書いたらこうみたない説明の部分.

関数型デザインのアーキテクチャの境界線は名前空間

p161, defmultiの「さらに下」にdefmethodが定義されていることが強調されてる. ??強調するところはそこなのか?!斬新だ. さらに, defmethodが別ファイルに各ことで「アーキテクチャの境界線」のような用語もでてきた. 斬新だ, わたしはそんなことは意識したことすらなかった…

defmethodがdefmultiのファイルを参照する. ソースコードの依存関係の逆転. defmultiは実装がかかれたdefmethodのファイルに依存していない. この関係はJavaにおけるHogeとHogeImplのClassではないか?

defmultiとは抽象クラスのような機能であり, 従ってpayroll-interfaceという名前空間の名前にしてしまおう.

Clojureの名前空間はクラスのようなもの

Clojureでは名前空間とソースファイルが深く結びついている. Clojureの名前空間はクラスのようなものである必要ではないが, このような見方はわるくない.

p166

第三部: 関数型デザイン

📐SOLID update. 関数型におけるSOLIDとは?


SOLID原則というと, オブジェクト指向設計, SOLIDしらないOO中はモグりだ!的な雰囲気を勝手に感じていた. しかし, 結局SOLIDの原則をFPでやるとこうなる的な事例を紹介していいたかったこは, SOLIDとは保守性の高いきれいな設計ための原則であり, それはOOでもFPでも適用できるということか? LSPだとそもそも定義からサブタイプが前提なので, LSPのようなものとなる.

関数型プログラミングやClojureだとクラスが出てこなていので, 抽象クラス/サブクラスというものはないんだけど, じゃあ設計モデルに対する抽象/具体がないかというとそんなことはない. 設計の抽象/具体をコードで整理して記述するというのはOOに限らない.

変更可能な言語では振る舞いかオブジェクトを流れていく。関数型言語ではオブジェクトが振る舞いを流れていく

データフロー、配管の比喩. パイプ処理.

第四部: 関数型の実践

  • TDD
  • モック
  • プロパティベーステスト

  • <2024-06-15 Sat 17:45> やたらとTDD推しだ. REPLがあったとしてもTDDでテストを書く. これはもはや老害の信念.
  • <2024-06-15 Sat 17:49> ただ私自身は大規模プロダクト開発でClojureをつかったわけではなく趣味個人開発なので, そのあたりの知識が開発対象に対してオーバースペックいうのもある.

第五部: デザインパターン

🎨GoF

  • <2024-06-16 Sun 13:27> なんか今までにあまりみたことがないようなmultimethodやファイル分割が展開されていく. ここまで厳密にClojureでOCPやDIPを意識して開発した事例をしらない. プロダクト開発では実施されているのだろうか?

🔦Clojureはソースファイルを分割し名前空間で依存関係を管理すればオブジェクト指向だ

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

まじか!わたしももっと使おう. p401.

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

そうだったのか!

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

関数型プログラミング影響は副作用の排除, 可変オブジェクトではなく不変オブジェクトを好むこと. しかし, オブジェクトであることに変わりはなく、インターフェイスを実装するクラスとしてて表現や構成が可能である。

🔦デザインパターンとは特定のコンテクストにおける共通の問題に対するソリューションに名前をつけたもの - Uncle Bob

  • デザインパターンとは特定のコンテクストにおける共通の問題に対するソリューションに名前をつけたもの(p329).
  • 「デザインパターンはOO言語の問題を回避するハック」であり関数型言語では必要ない?そんなわけねえだろ!

Abstract server(抽象サーバ)を例にした説明. これはGoFに含まれているわけではない. しかし, 別にソリューションに名前をつけたものというならば, OOとかFPとか, そういう限定的なものではないのだ.

Abstract Server

🎨Abstract Server pattern, 抽象と実装を分離する. 手段はいろいろある.

  • 関数形式: 関数を引数で渡す.
  • 仮想テーブル形式: 複数の関数をMapで渡す.
  • マルチスレッド形式
  • レコード/プロトコル形式

Adapter

🔌Adapter Pattern

  • 雑にやればcondで分岐でいいけどCloure流にやるならマルチメソッド式Adapter.
    • さらにnamespaceをわけてdefmultiを別ファイルにすればよりよい.
  • OOでいうオブジェクト形式のAdapterがClojure流. クラス形式はClojureでは実装できない(継承がない).
    • オブジェクト形式?すると名前空間はオブジェクトのようなもの?
    • GOFのAdapterパターンの目的からいえば名前空間で責務を分離することはオブジェクトに近い.

Command

🎨Command Pattern

Clojureでは「関数はオブジェクト」(この表現はややこしいな)なので, わざわざCommandクラスを定義する必要はない. 関数をわたすだけ.

undoの実装で, multimethodで関数をassocするのははじめてみるパターンだな.

いや, でもこれはintegrantに近い?integrantは生成と終了を定義する. 状態はimmutableに受け渡される.

Composite

さっきのcommand patternもそうだけど, オブジェクトの代わりにtypeを指定したものを生成してdefmethodで関数を呼びわけはわたしの辞書にはない新しい書き方だ, 覚えておきたい.

integrantのサンプルコードに似たような処理はみかけたものの, 理解して使いこなせなかった. 関数型っぽいベストプラクティスしならいわたしは雑で気軽にatomを多様してなにも関数型ではなかったな… i

mmutableなMapを更新してそれを受け渡すんだ!

Decorator

🎨Decorator Pattern

Visitor

🎨Visitor Pattern, ダブルディスパッチなんてJavaやC++のような閉鎖クラスちは必要だがClojureのようなオープンクラスでは必要ない.

Abstract Factroy

factory methodをatomにおいておいてグローバルにつかう?斬新だ.

第六部: ケーススタディ

シンプルなアプリケーションでは、徹底的にファイルを分割する必要はないだろう。我々はこれが大規模エンタープライズアプリケーションである「ふり」をしている。

https://github.com/unclebob/wator

  • <2024-06-16 Sun 14:08> そうか, 「こんなにファイル分割しまくる必要あるのか?」というわたしの心の中の小さな声は想像力が足りなかった. 実際は複雑怪奇なジャングルスパゲッティなんだ.
  • <2024-06-16 Sun 14:25> この章は写経してもいいかも.

Opinions

Clojureこそ最後にして最強の言語だ!

The Last Programming Language - YouTube

Insights

  • <2024-06-15 Sat 14:46> 人気のないClojure界隈に英雄ガープ中将がきた感じ.
  • <2024-06-15 Sat 16:32> 今までやってきたことがいろいろ結合されていく感覚がある. Java/UML/GoFとOO/Clojure… Clojureを勉強しながら, これってUMLとかデザインパターンだとどうなる?的な疑問は常に抱えながら学んできたが, そういう個人での回答に対する答え合わせみたいな感覚.
  • <2024-06-15 Sat 16:45> 結局今日本語で読めるClojureの書籍はJavaが活躍するような大規模システム開発向けにはかかれてない. ただClojureはスクリプト言語のような気軽さはない, JVMが重すぎるから. デザインを語るClojure本は新しい.
  • <2024-06-15 Sat 17:08>
    • わたしはClojureのmultimethodがそこそこ理解に苦しんだ思い出がある. Protocolとの違いなど. なので, いきなりこの書籍からClojureを学び始めてmultimethodが主題のように来ると難しいきもした.
    • しかしJavaとの比較で説明されると理解しやすくもある.
    • Javaの継承とinterface/Clojureのmultimethodとprotocolの関係. 一番むずかしいところにぶっ込む系.
    • というよりdefmulti/defmethod実践例としてとてもよいな. いまいちClojure公式docやProgramming Clojure読んでもピンとこなかった. 依存関係を整理する目的のマルチメソッド大活躍.
  • <2024-06-15 Sat 18:56> そうか, 依存関係云々はintegrantがよろしく処理していたが, そもそもわたしがintegrantの仕組みを理解してなかっただけだった.
  • <2024-06-16 Sun 14:15> そもそもエンタープライズJavaをおきかえるようなClojureの書籍はあっただろうか?日本語ではなさそう.

✨ボブおじさんがエレガントなClojureにきたのには必然だ

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

Clojureの自力なFSMよりもOSSのFSMをつかいたい

やたらと有限状態マシンがでてきて, loop/recurをつかったエレガンスが強調される. しかし, そもそも自力でそれを書くよりもフレームワークをつかったほうがいい.

しかしClojureにおいてけっこう絶望的なのはFSMのフレームワークの情報か少ない, 限定的だ.

🔗References

Journals

  • <2024-06-15 Sat 15:09> なんかカタカナを英語でそのまま書いてくれたほうがわかりやすい. デッドリーエンブラス?
  • <2024-06-14 Fri 08:10> PDFが購入したい. 6/10にカドカワ公式ショップからの発売を待っていたのだが, カドカワがサイバー攻撃を受けてdownしてる. ただ結局book walkerサイトにリンクが貼られてPDFではないかもしれない. 過去のボブおじさんの書籍はアスキードワンゴが出していて達人出版会経由だとPDFで発売されてるのでそれを待つか.
  • <2024-06-14 Fri 21:54> 待てないのでbookwalkerで購入した.
  • <2024-06-17 Mon 21:11> 関数型デザインを読んだ感想 - オブジェクト指向設計の英雄ボブおじさんが放ったClojure本! | Futurismo