アーキテクチャは疎↔密を繰り返す

歴史は繰り返しでアナロジーがあるから面白い。ソフトウェアのアーキテクチャの流行りを調べてみると同じようなことを言葉を変えて繰り返している。切り口はいろいろあると思うが、今日はアーキテクチャという切り口から見てみる。

ソフトウェアのアーキテクチャコンポーネントとかモジュールが疎結合になったり密結合になったりを繰り返している。

一般にソフトウェアの部品は疎結合な方が保守性が高い。理解しやすいし、テストもしやすいから品質も高い。再利用性も高いので、生産性も高まる。それに、美しい。人間の頭に合わせて行くと、ソフトウェアは疎な方向に向かっていく。小さく分割されて整理されていなければ人間は理解できない。ソフトウェアは保守にとにかくコストがかかるということは経験として知られている。ソフトウェアを人間が理解できなければ保守できないが、人間の理解というものは非常にコストがかかることだ。コストを抑えたいという考えで、ソフトウェアは疎結合となっていく。また、これは私の考えだが、頭の良い人というのは難しいことを理解できるのではなくて、分割して整理して理解できる形にするのが上手いのである。だから、頭の良い人ほど疎結合にしたがるように思う。

しかしながら、部品同士の結合度が弱くしていくと性能が悪くなっていく傾向がある。部品同士の通信に計算コストがかかるからである。部品に綺麗に分かれていなくて、ひとつの塊になっているようなモノリシックといわれる形体の方が性能は良い。巨大な塊で触れないけど性能は良いコードってないですか。また、最初は綺麗に分かれていたけれども、チューニングのための最適化をしていくと部品がくっついて密結合になっていくということもある。

最初は小さい塊だったのが、どんどん巨大な塊になっていき、人間の限界を超える。そのため、分割したいという考えが出てきて、部品が小さくなる。そのうち、部品が巨大化していったり、部品同士がくっついていったりして、再び限界を超える。そして、また分割する。ソフトウェアのアーキテクチャはこの繰り返しだ。


OSがないころはプログラムは完全にモノリシックだった。ハードウェアを動かす部分とやりたい計算の部分は分けたほうが便利だということでOSができる。

やりたい計算も部品に分かれていないと整理しきれないということで、構造化プログラミングが発案される。それでも、足りないとオブジェクト指向プログラミングが発明される。

OSの方も部品化されてた方が良いとマイクロカーネルという考えが出てきたが、思ったほど部品化の効果がなかったようで、結局モノリシックなLinuxがもっとも普及している。しかし、Linuxカーネルモジュールという部品に分かれていたりする。

UNIXの哲学は疎結合を良しとする考え方の代表だろう。小さいプログラムを作って、シェルスクリプトとプレーンテキストでゆるく結合させようという考えだ。しかし、一部のPOSIXシェルはechoといったよく使コマンドは組み込みコマンドにしてして効率化をはかったりしている。また、シェルスクリプト自体が巨大化して手に終えなくなったりというのもよくある話だ。

マルチプロセスの方がコンポーネント疎結合だけれども、同期が大変だとかプロセスの生成コストが大きいとかで、メモリ空間を共通にしているという意味で密なマルチスレッドになって、でもスレッド同士は疎な方が良いよねってことでGoみたいになったりとよう分からん。

あるいは、最近ではシステムが巨大してしまったので、マイクロサービスなどといって小さく切り分けるのが流行っている。


疎結合・密結合は、どちらが良いとも言えず、いずれを選択されるかは設計思想の問題で、その選択はソフトウェアの性質やその時々の計算機の性能や他のソフトウェアの状況や流行りで決まってくる。

それでも、アーキテクトが必要になるような大きな設計は除いて、ちょっとした設計ぐらいの小さい話なら極力疎結合にしようとした方がよいと思う。関数呼び出しを一回削って節約できるユーザーの時間と、それによって発生するテストや保守の時間を比べたら、きっとほとんどの場合後者の方が大きい。それに、放っておいたらすぐにモジュールの結合度は高くなっていく。疎結合にしようと踏ん張っても、塊になるのを少しゆるやかにするのがいいところだ。疎なものを密にするのは簡単だが、密なものを疎にするのは不可能だ。密結合とスパゲッティは紙一重である。ソフトウェアを延命させたかったら、疎にした方がよい。ソフトウェア危機は計算機が発明されて以来ずっと続いているのだから。