Comparators―比べてみればわかること

第4回Layered vs.Connected

あるとき休憩室で、私は同僚にたずねました。⁠分散ファイルシステムに載った分散データベースにクローラがインデックスを保存、インデックスの隣にはキャッシュサーバが並んでいる。そんな検索エンジンのシステムを図に描くとどうなりそう? チームの新入りにレクチャーする感じで教えてよ」

部屋の壁にかけられたホワイトボードに向かい、同僚は箱を積み上げる図を描きました図1左側⁠⁠。同じ質問を受けた別の同僚は、丸を矢印でつないだ図を描きました(図1右側⁠⁠。

図1 LayeredとConnected
図1 LayeredとConnected
どちらの図も現実の検索エンジンを反映したものではありません

同僚4人に質問を続けたところ、結果は2対2の引き分け。決着をつけようと声をかけた5人目には「それは……、場合によるよ」と言葉を濁されてしまいました。

箱を積み上げた1つ目の図を、ここではLayeredと呼ぶことにしましょう。丸を矢印でつないだ2つ目の図は、Connectedと呼びましょう。検索エンジンのシステムとして正しい図は、LayeredConnectedのどちらでしょうか。

ビューとスタイル

正解は言葉を濁した5人目。望ましい図の描き方は「場合による」のです。文書化用語では、システムの概観をとらえる図1のような図をビューArchitectural Viewsと呼びます。図は関係が薄いものを省き、説明が伝わるよう要所要所を強調します。同じソフトウェアに対して、ビューはいくつも存在します。伝えたい相手や目的によって、必要となるビューが異なるからです。

カレーライスの例で考えてみましょう。

神保町でカレー屋に入りました。メニューを開けば、チキンキーマカレーの盛り付け、辛さ、値段がわかります。メニューはカレーに対するビューの一つです。顧客の食事選びを助ける役割があります。

もう一つのビューは厨房のレシピです。肉、野菜、調味料の分量、調理手順や味付けがわかります。料理人の調理を助ける役割を持つビューだと言えます。

メニューやレシピにはさまざまな見せ方があります。見せ方によるビューの分類をスタイルと呼びます。LayeredやConnectedもスタイルの一種です。書籍『ソフトウェアアーキテクチャドキュメント』注1には、広く利用されているビューのスタイルが紹介されています。LayeredスタイルとConnectedスタイルは、よく見かけるスタイルの代表格です。

静的な構造を扱うLayered

Layeredスタイルはソフトウェアの静的な構造を描くのに向いています。ソースコードに現れるような構造、たとえばクラスやパッケージ、名前空間などが静的な構造です。

Layeredスタイルでは、積み上げた箱をモジュールと呼びます。モジュールは、クラスやパッケージといった何らかの論理単位です。Layeredスタイルでは、上に積まれたモジュールが下側に依存する一方向の依存だけを持ちます。

動的な構造を扱うConnected

Connectedスタイルはソフトウェアの動的な構造を表すのが得意です。実行時、デプロイ後に見られるプロセスやサーバ同士の関係が動的な構造です。プロセスやサーバはコンポーネントと呼ばれます。Connectedスタイルではコンポーネントを円で表し、メッセージを表す矢印で円同士をつなぎます。矢印の種類を描き分ければメッセージの種類を区別できます。

お気に入りのスタイル

静的な構造にLayered、動的な構造はConnected。どちらを選ぶかは目的次第です。冒頭の雑談中、Layeredスタイルのビューを描いた同僚はコード上での静的な構造を、Connectedスタイルのビューを描いた同僚は実行時の動的な構造を伝えたかった。そう考えることができます。

けれど、日々の議論で私たちはそんな風に図を使い分けているでしょうか。いつも同じビューばかり描いていませんか。筆者の観察によれば、使われるスタイルは仕事の分野による偏りがあります。

クライアントサイドに中心を置く組込みシステムモバイルアプリの世界では、Layeredスタイルに人気があるようです。⁠Android Architecture」⁠Qt Architecture」などと検索すれば、Layeredスタイルで描かれたビューをいくつも見つけることができます。

分散システムを伴うWebの世界ではConnectedスタイルが優勢です。High Scalabilityに代表されるWebアプリケーションのアーキテクチャ解説サイトは、いつもConnectedスタイルのビューで賑わっています。

こうした偏りには事情もあります。クライアント主体のシステムは、プログラムの大部分がプロセスやマシン境界をまたがずに動きます。代わりにプログラム一つ一つが大きく複雑で、静的な理解の出番が多くなります。

一方、Webのシステムは個々のコンポーネントが比較的単純。代わりに複数のコンポーネントがプロセスをまたいで動作します。デプロイ後のトラブルシュートにも多くの時間を費やすこうしたシステムでは、実行時の関係を注視するConnectedスタイルが当てになります。

スタイルの支配

このように、スタイル選びはシステムの性質を反映します。とはいえ1つのスタイルに慣れ過ぎるのも危険です。説明の道具にすぎないビューのスタイルが、デザインに滲み出してしまうからです。

Connectedスタイルの支配するチームで、あるとき新しいプロジェクトが始まりました。プロジェクト序盤のある日、あなたはミーティングに出席します。プロジェクトに参加する開発チームが集まり、担当の割り当てを議論するためです。ホワイトボードには想定されるシステムのビューがConnectedスタイルで描かれています。クライアント、フロントエンドサーバが1つずつ、バックエンドが複数、そしてモニタリング用ノードです図2⁠。

図2 とあるシステム
図2 とあるシステム

会議は紛糾します。どのチームもフロントエンドサーバを開発したがらないのです。アプリケーションロジックの多くを担うフロントエンドサーバは、開発規模が大きい貧乏くじ。下手に引き受けるとデスマーチが待っています。長い押し付け合いの末にデザインの折衷案が現れました。

支配下のデザインたち

折衷案は2つ。第一案のオプションAは新しいバックエンドサーバを導入し、フロントエンドの一部を新しいバックエンドに切り出そうと提案しています図3⁠。第二案のオプションBはプロキシサーバを導入し、ロジック単位で分離されたフロントエンドに処理をリダイレクトします図4⁠。

図3 オプションA
図3 オプションA
図4 オプションB
図4 オプションB

どちらの提案も一見それらしく見えます。しかしシステムの複雑さが増している点に変わりはありません。よく知られた分散システムの第一法則「分散するな」と説いています。可用性や性能に問題がない限り、システムのコンポーネントを増やすなというのです。このプロジェクトでは第一法則を破り、チームの担当を区切るためにコンポーネントを増やそうとしています。なぜでしょう。組織が構造を規定するConwayの法則が働いたのでしょうか。

Conwayの法則を無視はできないものの、問題をこじらせたのはスタイルの支配です。議論はホワイトボードに描かれたConnectedスタイルのビューを中心に進み、参加者はシステムの動的な構造をチームに合わせようとしました。誰かがLayeredスタイルの視点で静的な構造に目を向ければ別の展開があったはずです。フロントエンドの機能は、静的な構造の上でなら簡単に分割できました。役割分担の余地はあったのです図5⁠。

図5 フロントエンドのLayeredビュー
図5 フロントエンドのLayeredビュー

静的な構造、コードの中で役割を分担できれば、実行時の複雑さは増えません。しかしConnectedスタイルに縛られたチームの面々がLayeredスタイルに目を向けることはありませんでした。

自由度としてのビュー

ここでの教訓はなんでしょう。複数のスタイルを意識すること? 同じシステムをさまざまなビューで描いてみること? スタイルの支配はプロジェクトの始まりだけでなく、そのライフサイクルを通じて続きます。どうすればそれから逃れられるのでしょう。変わり続けるシステムの成長を後押しするものは何なのでしょうか。

今回の主題、スタイルとビューに沿って考えてみましょう。将来の議論に備え、さまざまなスタイルでとらえたシステムのビューを記録に残しておくことはできるかもしれません。開発者はそれらのビューを通じて多面的にシステムを理解し、最も意味のあるビューに沿ってデザインを育てていくことができるでしょう。このとき、ビューはデザインの次元、自由度として機能しています。

権威としてのビュー

一方で、選択肢をもたらすはずのビューが自由を阻むこともあります。一度記録されたビューは、まるで意図された決定であるように見えるからです。必要のない細部が記録されると、瑣末(さまつ)なものに意味が与えられてしまいます。

こんな場面を想像してみましょう。あるとき、プロジェクトはメトリクス集計用データベースの性能問題に突き当たりました。あなたはそれを解決しなければなりません。資料を片手にソースコードとログを漁ったあなたは、ある中間レイヤのボトルネックを突き止めました。このレイヤをバイパスすればだいぶ速度を稼げそうです。

「でもなあ……」あなたは資料のLayeredビューに目をやります。ほかのモジュールは漏れなく階層構造を守っており、階層破りはあなたが最初のようです。秩序から踏み出す苦労が頭をよぎります。フレームワークのチームにメールを書き、担当者を捕まえて説得し、規律にうるさいレビュアが満足するまで何度もコードの抽象を組み直して……、考えるだけでため息が出ます。気をとり直したあなたが一連の強敵を退治し終えたのは1ヵ月後のことでした。

その少しあと、あなたはたまたまあるエンジニアと同席しました。システムの初期デザインを担当し、今は忙しい別プロジェクトを率いている働き者です。近況報告を兼ね、ここ1ヵ月の戦いを語るあなた。すると彼はきまりが悪そうにこう打ち明けました。⁠あのデータベース、運用チームも違うからストレージのレイヤに描く必要はなかったなあ」

「どういうことですか?」思わず聞き返すあなた。⁠システムで使ってる以上、あのデータベースもビューに描かなきゃと思って押し込んだだけで、場所はどこでもよかったんだよ。図の上ではストレージレイヤだけど、僕がいたころはレイヤへのアクセスを抽象化するコードなんて全然なし。データベースのHTTP APIを直接叩いていたはず。君が1週間がかりで直したっていうクラス、誰かがビューとコードの階層をそろえるためだけにあとから足したものかもね。ストレージレイヤの面倒を見てる彼、細かいところにうるさいからレビュー大変だったでしょ」

暗闇に目を慣らす

ビューが権威を持ってしまうのは避けがたいことです。ビジュアルが持つわかりやすさには、自然言語やソースコードが語る退屈な真実よりずっと説得力があります。しかしそれが単なるハッタリにすぎないこともあります。そんな口八丁のビューをのさばらせないために何ができるでしょう。

オープンソースソフトウェアの多くは、ビューも含めて十分なドキュメントがありません。開発者はコードを読んで中身を調べます。調査をもとに書いたコードはベテラン開発者のレビューを受けます。バグ1つないコードが、⁠これは階層破りだ」と素っ気なく断られたりします。理不尽な言い分です。何しろ階層構造の説明なんてどこにもないのです。

それでもコードベースに慣れるにつれて構造が見えてきます。同時に構造のほころびも目につき始めます。ためしにほころびを直してレビューを求めると、すぐに返事がきました。⁠そうそう、ここが前から気になってたんだよ!」ほころび直しのパッチは即座にチェックインされていきます。ビューがない世界の権威は、コード自身、そしてコードを読み書きする開発者に宿るのです。

議論の中で描かれるビューは論点を絞る役に立つでしょう。入り組んだ細部のビューもコード書きを助けることがあります。魔が宿りやすいのは個別の議論に伴うビューではなく、むしろシステム全体を収めた青写真。包括的な保存版のビューです。そしてソフトウェアの名を笠に着たい権威主義者や野次馬ほどそうした「全体像」を知りたがるのです。

冒頭の場面に戻りましょう。チームの新しいメンバーに、あなたは何を描いてみせますか。Layeredスタイル、あるいはConnectedスタイルのビューでしょうか。複数のビューを交えた1時間の入門講座を開きますか。それとも頼みは聞き流し、代わりに手ごろなバグ修正をいくつか、新しいメンバーに押 付けますか。ソフトウェアの姿を、あなたはどのように思い描いているのでしょうか。

おすすめ記事

記事・ニュース一覧