理系ジョーク
こんな小噺がある。
「あんたは整理整頓できない人だね。なんで、自分の部屋のものを片付けて整理できないかね。」
「しょうがないじゃないか。エントロピーは増大しかしないんだから、勝手に部屋が乱雑になっても仕方ないことなんだよ。」
概ね理系が部屋を片付けられない理由として、エントロピー増大則をあげられることがある。例えば、コーヒーとミルクを混ぜてカフェオレを作ったとする。このカフェオレは、時間が経っても、コーヒーとミルクに分離することはない。逆に、コーヒーとミルクを静かに注いで、最初は分離されたような状態に見えても、次第に混ざって、カフェオレ状態になってしまう。このようにコーヒーとミルクのように分離した秩序だった状態は不安定で長く存在できず、カフェオレのように混ざった混濁した状態の方が安定であるため、そのように変化してしまうことをエントロピー増大則として説明されることがある。部屋の中で整理整頓された状態はエントロピーが低い状態であり、ものが散らかった汚い状態というエントロピーが高い状態であり、そのように遷移することは、自然の摂理である。と強弁するためのロジックとして使われることがある。
本棚のアナロジー
例えば、あなたが新しくオフィスを借り、そこに1冊の本を持ち込んだとしよう。その本は自分の机の上にでも置けばいいし、適当な棚へ置いてもいい。そこから、本が10冊に増えた。さすがに、ちょっと量が多い。机の上に置くには少し邪魔な量であろう。本棚に適当に並べておけばいい。そこから、100冊に本が増えた。さて、どうしようか。今まで通り、とりあえず本棚に置く。というだけでは、使い勝手が悪そうだ。辞書は辞書でまとめるべきか、小説は小説でまとめるべきか、雑誌は雑誌でまとめるべきか。
たくさん本がある。この本をどのようにすれば正しく整理整頓できるであろうか。本をたくさん置いてある場所といえば、図書館や書店であろう。これらはどのような整理の仕方をしているだろうか。図書館においては、図書分類法というものがあり、一般には日本十進分類法というもので書籍が基本的に分類されている。また、私の地元だけかもしれないが、夏休みの時期は「小学生のための課題図書」のようなコーナーが設置されている。そういった、時期による特設コーナーも存在することがある。一方で、書店ではどうだろうか。漫画や小説、雑誌など、図書館と似たようなくくりで分類されているものも多い。しかし、一方では、最近、ドラマ化された原作の小説がピックアップされたコーナーであったり、年末年始であれば、年賀状の作り方。のような素材集が特設コーナーに設置されていたりするだろう。
本がたくさんある。という視点で、図書館と書店を観察してみた。そして、その中で本はどのように整理されているのか。ということを考えた。しかし、どうやら先ほど話題に上がった「正しく整理整頓する唯一の方法」というものはないらしく、それぞれの場所によって整理方法が異なった。これは何を意味するのであろうか。
銀の弾丸は存在しない
これらの話は、ソフトウェアアーキテクチャの話と何か関係があるのだろうか。まず私は初めに「本が1冊しかないとき、適当な机の上にでもおいておけばいい」と書いた。また、「本が10冊の時は、本棚に並べておけばよい」と言った。これは、「小規模なソフトウェア開発において設計はそれほど重要でない」ということを意味している。本=モジュール(クラスや関数、機能)と考えてもらえばよい。例えば、「Hello World」のような簡単なプログラムは特に設計という概念を意識せず、関数などもほぼ使わずに書ける。また、「フィボナッチ数列を計算する」程度のプログラムもほぼ設計は要らず、せいぜい関数を1つ作る程度であろう。このように、小規模なソフトウェア開発において、ソフトウェアの設計というものは必要ない。
では、本が100冊ある場合の整理術の結論はどうなっただろうか?結論としては、「正しく整理整頓する唯一の方法」というものはないらしい。図書館と書店では、ある程度、似たように本を分類しているようにみえるが、前者は、夏休みの課題図書コーナーがあるが、後者では、ドラマ化された小説コーナーがある。この違いは何だったのだろうか?これは
サービスするユーザーや便益が異なること
に帰結する。図書館の例であれば、「小学生が夏休みの課題図書を調べやすくする」というある意味、地域の公益を目標にしたコーナーの設計である。一方で、書店の場合は、「今、話題のドラマ化された書籍を売りたい」という目標にしたコーナーの設計である。こういった、表立っては見えない「目標」に応じたコーナーの設置を行っている。
これをソフトウェアの設計に当てはめると何にあてはまるだろうか?これが、いわゆる「ドメイン」の話になる。
まずは、DDDとは何か、から始めましょう。そもそも「ドメイン」とは、アプリケーションが対象とする業務領域のことです。本書では、ドメインを「知識、影響力、活動の一領域」と定義しています。業務アプリケーションでは、アプリケーションをプレゼンテーション層、ドメイン層、データソース層の3層に分けるアーキテクチャが主流ですが、このドメイン層がユーザの業務に直接的に関わる部分になるわけです。したがって、ドメイン層を正しく構築できるかどうかが、そのままアプリケーションの成否に影響します。
DDD難民に捧げる Domain-Driven Designのエッセンス 第1回 ドメイン駆動設計とは
本が1冊、本が10冊の例で表したような、小さな規模のプログラムであれば、その用途や機能が非常に限定されており、しかも、全体を読んでもそれほど工数がかからないので、どのような影響があるのか。ということがとても分かりやすくなっています。しかし、本が100冊の例で示したような、大規模のプログラムになると、用途や機能が細分化・複雑化しており、それぞれのモジュールの存在意義というものが曖昧になってきます。そこで重要になってくるのが「ドメイン」、上記の言葉でいえば、そのプログラムが実現しようとしている「目標」をどれだけ精緻にプログラムに記述できるかが重要になってきます。なぜ、そんなことが重要になるか。ということを、先ほどの本の例に翻って考えてみたい。例えば、図書館が「話題のドラマ化された書籍のコーナーを作る」というのは、間違ってはないが、的確ではない。という見方ができる。課題図書というのは、ある意味で、教育上効果があると考えて設定された書籍であろう。では、それを差し置いてまで、「話題のドラマ化された書籍のコーナー」を作る意味はあるのだろうか?概ね図書館というのは税金によって成り立っていることを考えれば、地域の教育に対し、投資をするべきであり、話題の書籍より、教育効果の高いと思われる課題図書を置くべきではないか。という立場も考えらえるだろう。
(ここでは、かなり一面的な見方をしている。例えば、日本図書館協会においては、
図書館とは、日本の「図書館法」によれば、「図書、記録その他必要な資料を収集し、整理し、保存して一般公衆の利用に供し、その教養、調査研究、レクリエーション等に資することを目的とする施設」とされています。
としているため、図書館において、話題のドラマ化された書籍コーナーを作ることは「レクリエーション等に資することを目的」ととらえることができるので、間違いではない。ただ、ここではロジックの都合上、そのような表現をしている。)
一方で、書店において、「小学生の課題図書コーナー」を置く場合はどうだろうか。これも本当に意味があるかは、難しいかもしれない。例えば、図書館において上記のような課題図書コーナーを作られていた場合、そちらを利用すれば無料である。そういった本をわざわざ書店で買う必要はあるだろうか?書店というのは基本的には利益を追求する企業であるので、そんな図書館により書籍価格の公的なダンピングが行われているものより、別の利益になりそうな書籍を店内に置く方が、利益最大化においては合理的ではないだろうか。
このように「目標」の取り違えにより、施策を間違うと、図書館や書店の存続が危ぶまれる。これは、同様で、ソフトウェアの設計に対しても、何を目標にしているのか。を取り違えて設計してしまうと、効果が最大化できなくなる。もっというと害すらある。上記の例でいえば、「図書館の職員が特設コーナーを作る際の選書は、現在放映中のドラマから行う。というフロー」を作ってしまう。そうした目的とずれたフローを設計してしまうと、後に「課題図書コーナー」を作ろうとすると、フローの見直しから入ってしまい、とても工数のかかる作業になってしまう。これはエンジニアにも覚えがあるだろう。ある新機能を作りたいと思っても、それが簡単に作れるようなシステム設計、クラス設計になっていないため、とても苦しい思いをする。といったことは、二度三度ではないだろう。このように「目標」に対する解釈を間違え、それを支えるモジュール設計を間違えると、後の変更に苦しい思いをしてしまう。
本棚とソフトウェアの相違
このアナロジーにはソフトウェア開発における複雑さを簡単化しすぎている部分がある。ソフトウェアのモジュールは本ほど簡単ではない。本は1つ1つが完結しており、それらを別の本棚に移し変えること、分類を変えることにそれほどコストはかからない。しかし、モジュールの場合は、難しい。それぞれのモジュールが依存関係を持ち、ほかのモジュールと数珠つなぎになっている。そのため、本のように本棚を移動するように、他のパッケージにモジュールを移動する。といったことがとても行いにくい。それを行うためには、モジュールをリファクタリングする必要があるかもしれない。本のたとえでいうと、本を分冊し、それぞれを再編集して、それぞれが1冊の本として読める状態にしたうえで、本棚に移し替えるような所業である。そして、その逆もある。モジュールの粒度感が小さすぎる場合は、モジュールを統合し、パッケージを移動する場合もある。本で言えば、6巻の漫画を再編集し、上下巻にしたうえで、別の棚に移動するようなものである。とても高コストであることが分かるだろう。この話、もう少し深入りすると闇が深いものがある。今まで"本"という単位でしか、物事を扱っていなかった。しかし、この話は、整理を進めていくにつれ、"本の中身"すら変えなければならない場合がある。ということを言っている。これは、現実世界では到底行われないが、ソフトウェアの世界では起こりうる。そうした場合、"本"以上の解像度が必要となり、その"本"の中身がどのように構成されているか、"本"とはどのように作られるべきであるか。という別の思考が必要になる。ソフトウェアの側に話を戻すと、モジュールがどのような機能を提供してるか、どのように動いているか、外部のモジュールとどう連携しているか。それらを把握しなければ、モジュールの分割や統合は難しい。これが、ソフトウェアにおけるモジュールの整理や再構成が難しい一面を表している。
そんな状況下ではあるが、さらに厳しい話があり、それは変更が激しいことである。世の中のエリートと呼ばれる人材は、一日に複数回のリリースを行っている。書籍であれば、毎日、本棚の位置や特設コーナーを変えるような話である。また、先述したような、本の分冊や、再編集を毎日、しかも複数回行うような話である。このあたりの速度感は圧倒的に異なる。
あと1つは歴史である。Wikipediaの図書分類法の歴史を見ると、日本において、日本独自の最古の図書分類法は1287年、鎌倉時代後期の「本朝書籍目録」が最初である。現在、国立国会図書館において使われている「国立国会図書館部類表」は1968年に成立したものである。このように本の分類。というだけでも、700年の歳月をかけて作られている。しかし、プログラミングの歴史はどうだろうか。FORTRANのようなかなり古めの言語であっても、その登場は1956年である。まだ100年経っていない程度である。その中で、モジュールの分割や分類というものがうまくいかない。というのは、まだ進化の途中であり、うまくいかないというのもある意味で不思議なことではないかもしれない。逆に言えば、時が解決する問題であるかもしれない。
ひよこミキサー
ポール・ワイスの思考実験というものがある。
ひよこを一匹とりだし、ミキサーにかける。その時、ミキサーにはひよこ由来の液体が残る。では、最初のひよこと、ミキサーにかけられた液体ひよこの間で失われたものは何か?よく考えてみよう。理想的なミキサーを想定した場合、ミキサーにかけられる前と後で、ひよこの原子は1つも失われない。したがって、液体ひよこはひよこに違いない。しかし、液体ひよこをひよこと言う人間はおそらくいない。では、何が失われたのか?この答えには、ネットを調べればいくつか回答があるが、私なりの回答を出すとすると、構造である。羽を構成する原子もあれば、目を構成する原子もある。それぞれがなぜ羽や目の機能を宿すか?というと、羽や目に特有の原子の並びがあるからである。その並び、原子の結合があるがために、目は目の機能を発揮し、羽は羽の機能を発揮する。
なぜこのようなグロテスクな例を出してきたかというと、ソフトウェア開発もこのような側面があるように思えたからだ。モジュールはモジュールとして機能を発現しているように考えているが、その実、液体ひよこのようなものではないか。と感じている。実は、モジュールはモジュール単体の機能も重要視されるべきではあるが、それ以上に、どのようにソフトウェアに組み込まれ、他のモジュールとどのように連携しているか。ということを重要視しなければ、ソフトウェアという大きな構造を作ることはできないのではないだろうか。
液体ひよこという状態は、最初の章に書いたエントロピーの高い状態である。この状態では何の機能も発現しない。これを機能を発現するためには、原子同士の構造を持ち、エントロピーの低い状態を保たなければならない。それは、ソフトウェアも同じで、モジュールをただ作り、乱雑にモジュール同士を連携してしまうと、エントロピーの高い状態になり、崩壊が進んでしまう。秩序立って機能を発現するためには、構造を持ち(設計を行い)、特定のモジュール同士の連携をデザインし制御しなければならないであろう。
感想
この話はとどのつまり、
大規模なソフトウェア開発は難しい
というだけの内容である。小規模なソフトウェア開発は簡単である。それは、本が1冊、本が10冊程度の管理を任された程度の話である。しかし、本が100冊程度の大規模な管理になった場合、問題が発生する。そこには、何を「目標」に管理しているのか。ということを明確にとらえなければならない。ソフトウェアが解こうとしている目標に対し、間違った認知をして、モジュールを構成してしまうと、その構成に首を絞められ、変更がしにくい体質になってしまう。ということを言っているだけに過ぎない。
前々から、なぜソフトウェア設計は難しい。という感想はあるが、その言語化にとても難しさを感じていた。それをどうにかして伝える方法がないか。と考えていた時に思いついたのが、本棚の下りであった。章のタイトルが「銀の弾丸は存在しない」であるように、ソフトウェアの設計に関して素晴らしいたった1つの冴えた解決策というものは存在しない。あるとすれば、「現状のドメインをよく表したプログラムを作る」程度の言葉になる。その話が、「図書館や書店における大量の本を扱うときの本棚の管理方法」になる。図書館や書店において行う業務や、サービスをする顧客が異なる。それにより、本の管理方法が異なる。プログラムもそのように自分が行ってる事業ドメインに合わせてソフトウェアのモジュール構成を考えるべきである。ということしか言っていない。ただ、ここが分かっていない場合もある。いわゆるクリーンアーキテクチャで作れば・・・ドメイン駆動をすれば・・・デザインパターンを使えば・・・のような話である。そういう技術方面の話ではないよ。ということである。
しかし、この話において私自身まだ消化できていない話はある。それはひよこの話である。このひよこの思考実験は生物の分野では割と使い古されたネタであるが、実際のところ、それをソフトウェアに適用した場合、どうすればよいのか。には私に答えはない。ここで言っている話は、液体ひよこのように、秩序のないモジュールの連携は人間はおそらく制御できず、ソフトウェア全体が崩壊してしまうだろう。という予測に過ぎない。では、秩序だったモジュールの連携とは何か。どのようなものであれば、秩序だったモジュールの連携であり、どのように構成すべきか。というところに言及はしていない。ここで個人的に気になっている概念は、求心性結合と遠心性結合である。クリーンアーキテクチャにおいては、主系列や不安定度の説明に出てきた概念ではあり、これらの概念自体はソフトウェア設計の良さを表す指標として利用されている。これらの概念と、エントロピーの概念は結合して説明ができそうな予感がしている。しかし、これも完ぺきではなく、これ以上は人間の認知しやすいモジュール構造とは何か。という生理学的なものも交じってくるであろう。という予感もしている。この辺りになってくるととても難しいであろう。
そして、この話をしてしまうと、難しい面があるのだが、あえて書くとするならば、メッセージ指向のオブジェクト指向につながる話ではないか。ということも感じている。無秩序な呼び出しをするのではなく、モジュールとモジュールの連携をどのようにデザインするか。という話。これは、もともとメッセージ指向のオブジェクト指向がすでに行っていた境地ではないか。と思う側面がある。
最後はとりとめのない話になってしまったが、この文章では、本棚のアナロジーによりソフトウェア設計の難しさを説明しようと試みた。