目次
問題設定:「アーキテクチャ」の意味論
もともと建築学の用語であった「アーキテクチャ(Architecture)」という概念は、多方面で参照されて再記述されたことにより、抽象性の度合いを高めることになった。今やアーキテクチャという概念の「定義」に関する統一された認識は得られない。この概念に言及するには、何らかの形容詞を付加させることで意味を限定する必要がある。
ソフトウェア・エンジニアやアーキテクトが「ソフトウェア・アーキテクチャ(Software architecuture)」と呼んだ場合、それによって指し示されるのは、専らエンジニアが開発するソフトウェアやコンポーネントのアーキテクチャとなる。だがソフトウェア工学との関連では、この他にも無数のアーキテクチャ概念が遍在している。ソフトウェア・アーキテクチャがソフトウェア・アーキテクチャとしての意味を保持するには、他のアーキテクチャ概念との「差異」が如何にして成り立つのかを確認しておかなければならない。
ソフトウェア・アーキテクチャに関して、カーネギーメロン大学ソフトウェア工学研究所からは次のような定義が提示されている。
「プログラムやコンピュータ・システムのソフトウェア・アーキテクチャは、システムの単一あるいは複数の構造を表す。そうしたシステムは、ソフトウェアの諸要素、その諸要素の外部から視認可能な属性、及びその諸要素の諸関連によって成り立つ。」
Bass, L. (2007). Software architecture in practice. Pearson Education India. p.18.
ここでいうソフトウェアの諸要素とは、コード、データ、クラス、オブジェクト、プロセス、スレッド、タスクなどといったアーキテクチャを構成するコンポーネントを意味する。
外部から視認可能な属性とは、外部環境から観察した場合に認識できる当該システムの振る舞いと関わる。この属性という概念は、システムの諸要素と境界に割り当てられた「責任」を言い表している。この属性には、他の諸要素に提供するサービスやデータ、他の諸要素から参照されるサービスやデータなどといった機能としてのプロパティも含まれる。この機能としての責任は、特定の諸要素に割り当てられることが多い。だが場合によっては、諸要素の区別の仕方によって満たされる責任も多い。これについては後述する。
最後に、諸要素の諸関連とは、諸要素間の相互作用を意味する。諸関連には、データフローや制御フロー、使用や依存、イベントや割り当てなどが含まれる。尤も、こうした関連は外部環境から観察する観察者の観点によって左右される。これについても後述する。
問題解決策:ソフトウェア・アーキテクチャ概念の抽象化
アンソニー・J・ラタンゼは、このソフトウェア工学研究所によるソフトウェア・アーキテクチャ概念の定義を「権威に訴える論証」としてではなく、概念の抽象化と一般化によって、「エンタープライズ・アーキテクチャ(Enterprise architecture)」や「システム・アーキテクチャ(System architecture)」を説明する概念として拡張している。ラタンゼに倣い、まずはこれらのアーキテクチャ概念の区別を導入しよう。そして、区別された各アーキテクチャ概念を横断的に観察することで、上述したアーキテクチャ概念の一般化を試みたい。
エンタープライズ・アーキテクチャ
エンタープライズ・アーキテクチャは、ビジネスモデルやビジネスプロセスと関係している。このアーキテクチャが参照するのは専らビジネスデータだ。そしてこのアーキテクチャは、組織システムの構造や組織間の各関連と関わりを持つ。位置付けとしては超上流に該当する。設計対象となるシステムの抽象度は比較的高い。
システム・アーキテクチャ
システム・アーキテクチャは、システムの文脈と関係している。このアーキテクチャの設計においては、専らハードウェアやインフラストラクチャが焦点となる。システム・アーキテクチャの設計者に求められるのは、ソフトウェア要求の抽出だ。言い換えれば、システムの結合テストの主題となり得るシステム全体の機能要求を定義することが、システム・アーキテクチャとの関連から重視されることになる。そのため、設計対象となるシステムの粒度はエンタープライズ・アーキテクチャに比して抽象度は比較的低い。
ソフトウェア・アーキテクチャ
ソフトウェア・アーキテクチャは、設計の全体と横断的に関わっている。焦点となるのはソフトウェアの機能要求と、ソフトウェア・アプリケーションの分割だ。これらの設計は、後のソフトウェアの統合とそのテストにおいて主題となる。
設計階層
エンタープライズ・アーキテクチャ、システム・アーキテクチャ、そしてソフトウェア・アーキテクチャとの間には、階層的な関係が生じている。エンタープライズ・アーキテクチャの設計はシステム・アーキテクチャの設計を制約する。システム・アーキテクチャの設計はソフトウェア・アーキテクチャの設計を制約する。ラタンゼはこれを「設計階層(design hierarchy)」と呼ぶ。ただし現実のシステム開発ではこうした単純明快な序列関係が形成されている訳ではない。ラタンゼは、あくまでもこれらのアーキテクチャ間に伴っている抽象化の粒度の「差異」を明示するために、この階層概念をある種の思考実験として記述している。
エンタープライズ・アーキテクチャ、システム・アーキテクチャ、そしてソフトウェア・アーキテクチャの共通点は、全体を構成する諸要素を抽象化していることになる。これらのアーキテクチャは参照する抽象性の水準や関心の対象に「差異」があるものの、「構造」や「属性」、「諸要素」や「諸関連」といった性質には共通性がある。
構造概念との関連で言えば、エンタープライズ・アーキテクチャ、システム・アーキテクチャ、そしてソフトウェア・アーキテクチャは、様々な構造で構成されている。決してこれらのアーキテクチャは単一の構造で成り立っている訳ではない。この点では共通している。
要素概念との関連で言えば、各アーキテクチャの諸要素は、より細分化して管理することが可能なコンポーネントとなっている点で共通している。これらの諸要素を別のあり方でもあり得る諸関連で管理することにより、アーキテクチャの複合性をある程度制御することができる。
外部から視認可能な属性という概念との関連で言えば、それぞれのアーキテクチャは外部環境に対してある条件を供給すると共に、幾つかの前提を要求するという点において共通している。ここで想定されているのは、入力情報や物理的な接続、ステークホルダなどによって求められるサービスなどの条件や前提となる。
諸要素の諸関連という概念との関連で言えば、それぞれのアーキテクチャには諸要素間の諸関連が構成されている点で共通している。関連の種類は諸要素に依存することもあれば、特定の観点で表現された構造に依存することもある。
ソフトウェア集中型システムの射程範囲
以上のような抽象化によって、ラタンゼは上述したソフトウェア工学研究所のソフトウェア・アーキテクチャ概念の定義をソフトウェア・アーキテクチャに限定せずに、少なからずエンタープライズ・アーキテクチャとシステム・アーキテクチャにおいても一般化して適用できると考えた。この抽象化と一般化によるアーキテクチャ概念の再利用は、設計者が複合性に対して反復的に対処することを支援するという。複合的なシステムを前にして、抽象化の利点は、機能性に関する根拠を提供することに限られたことではない。より重要な抽象化のメリットは、より実装に近い位置付けにある「詳細設計(Detailed design)」において全体的に幅広い属性に関する根拠を提供することにある。
上述した設計階層の思考実験を前提とすれば、ソフトウェア・アーキテクチャはエンタープライズ・アーキテクチャの設計とシステム・アーキテクチャの設計の双方から制約を受ける。一見してソフトウェア・アーキテクチャの設計の規制要因は多いように見受けられる。しかしながらラタンゼは、それでも尚自身のアーキテクチャ設計理論が「ソフトウェア集中型システム(software-intensive system)」を主題にしていると述べている。
「ソフトウェア集中型システムとは、ソフトウェアに密に依存しているシステムを意味する。このシステムは、コンピュータ・ハードウェア、オペレーティング・システム、データ、そしてステークホルダにサービスを提供するシステムを指している。」
Lattanze, A. J. (2008). Architecting Software Intensive Systems: A Practitioners Guide. CRC Press. p4.
ソフトウェア集中型システムの射程範囲は広い。Webやインターネット、情報テクノロジーは無論ソフトウェアに密に依存しているだろう。しかしIoT(Internet of Things)を背景に考えて観ても明らかなように、自動車や冷蔵庫、飛行機など、様々なシステムがソフトウェアと無関係ではいられなくなっている。ソフトウェアは、これらのシステムの中核に位置する。そして、サービスにおいて最重要な責任を担うのもまたソフトウェアだ。
この関連からラタンゼは、自身が取り纏める「アーキテクチャ中心設計(Architecture Centric Design)」を様々な領域のアーキテクチャを設計する上での汎用的な設計方法として提唱することになる。その著書であるArchitecting Software Intensive Systems: A Practitioners Guide.では、そのためアーキテクチャに関連する高度に抽象化された諸概念を前提として、極めて実践的な手続きが網羅されている。
問題再設定:人工知能の研究開発における「アーキテクチャ」の意味論
アラン・チューリングに始まる人工知能の研究史は、既に人工知能がソフトウェア的に理解されなければならないということを指し示している。チューリングは、人工知能がどのような場合に完成したと見做して良いのかという基準を設定するために、「模倣ゲーム」を提唱している。模倣ゲームは、男性(A)と女性(B)、そして別室の彼らとは無関係な質問者の三人で行なわれる。
- 質問者は、別室にいる二人のうちどちらが女性であるのかをタイプライターを介した会話で確定する。
- 女性は女性らしく振る舞う。男性は可能な限り女性を模倣して良い。
- 一定時間後、質問者がどの程度判定を誤るのかが、如何に男性が女性を巧く模倣できたのかという指標になる。これが人工知能の達成度基準となる。
このゲームにおいて、男性すなわちAをコンピュータにして、女性すなわちBを人間にするというのが、チューリング・テストとなる。このチューリング・テストでは、モデルを構築する部分で一人称的な心の見方を反映し、それをコンピュータに実装してモデルの実効性を検証していく。この検証段階では、二人称的な心の見方に基づいて評価される。
しかしながら、チューリング・テストが検証しようとしていたのは「思考」でも「志向」でもない。この検証が目指していたのは、純粋に「実用性」に他ならない。「機械が人間と同じように思考できるか否か」という問いは、チューリングにとっては端から些末な問題であった。実際、チューリングが1930年代に提唱していたあの「万能計算機(universal computing machine)」は、人間精神の原理的構築というよりは、むしろ人間精神の機能的な模倣でしかない。故にその主題はソフトウェアの問題として設定され、この意味で研究アプローチは機能主義的でもあった。
この万能計算機は文字を一列に書き込める非常に長いテープと、テープ上を左右に移動してその文字を一つずつ読み取ってはそれを消したり新たに追記したりできる装置から成る。装置の内部には「状態」がある。今「P状態にある」とか「Q状態にある」と決められている。装置には機能表が格納されている。そこにはP状態の時に文字Aを読みとったら、と言った具合の場合分けと命令が記されている。この状態遷移関係と出力文字を図式的にあらわしたものを、現代人は「オートマトン(automaton)」と呼んでいる。
この万能計算機、すなわちチューリング・マシンは、単純な仕組みだが、論理学における形式的な推論が漏れなくチューリング・マシンで実現できるという万能性を証明した。これにより、論理学における一連の理論的成果が文字の書き換え、つまり<数学的>な「計算(compute)」という形式を前提に、<工学的>に実現できると結論付けられることとなった。
こうしてチューリングの研究史まで歴史を遡ることで、我々は人工知能もまた「ソフトウェア集中型システム」の一種であることに気付くことになる。だとすると、人工知能の開発においても、ソフトウェア・アーキテクチャの工学で培われてきたアーキテクチャ設計のノウハウを活かせるのかもしれない。
しかしながら、アーキテクチャ概念が幅広い分野で言及されているというのは、人工知能の研究分野においても例外ではない。実際、機械学習(Machine Learning)の領域でもこのアーキテクチャは無視することのできない重要なキー概念として記述されている。ソフトウェア・アーキテクチャの分野から機械学習の分野にアーキテクチャ概念を輸入するのならば、機械学習の分野における既存のアーキテクチャ概念との比較が必要になる。そうすることで、双方の概念の差異と同一性を区別できるようにしておかなければ、アーキテクチャ設計のノウハウの再利用が無用な概念的重複による冗長的な提案となってしまう恐れがある。
問題解決策:深層学習における「深層アーキテクチャ」
人工知能研究の領域でも、とりわけ機械学習の一種である「深層学習(Deep Learning)」の研究領域では、「深層アーキテクチャ(Deep Architectures)」という概念が取り沙汰にされている。その内部のアルゴリズムが「制限ボルツマンマシン(Restricted Boltzmann Machine)」や「自己符号化器(auto-encoder)」のようなデータサイエンス特有の様々な仕様で記述されている分、それぞれの層の入出力インターフェイスが未定義で可変的であるという差異はあれど、複数の階層分化した水準の各層における命令フェッチや命令デコードをはじめとしたベクトル演算処理がパイプラインとして結合されているCPUとしてイメージできる点では、深層アーキテクチャはコンピュータ・アーキテクチャと概念的によく似ている。
こうした深層アーキテクチャは、入力情報の諸要素の抽象的な表現とその再利用を実現してくれる。例えばこの技術は猫の画像のみならず人の顔や手書き文字の識別においても機能する。こうして表現された情報を更に学習すれば、相互に関連する諸概念の集合の学習も可能になる。これにより、人間が行なっているような概念の汎化をも可能になるとされる。
こうして人工知能の研究分野で言及されてきた深層アーキテクチャは、コンピュータ・アーキテクチャの派生であるばかりか、ソフトウェア・エンジニアやアーキテクトが設計してきたソフトウェア・アーキテクチャの一種として位置付けることができる。深層アーキテクチャは、まず階層分化した「構造」として設計されている。各層の複合性を観れば明らかなように、深層アーキテクチャの構造は単一ではない。加えて、深層学習の各ニューロンにおける「重み」や「バイアス」、あるいは活性化関数に入力されるパラメタなどのような諸要素は、外部から視認可能な属性としての様相を呈している。そして、「逆伝播(Backpropagation)」によるニューラルネットワークの構成は、まさしく諸要素の関連の一種を指している。これらの要因から、深層学習の深層アーキテクチャをソフトウェア・アーキテクチャとして見立てることに差し支えは無いだろう。
問題解決策:強化学習問題の枠組みにおける「強化学習アーキテクチャ」
ロボット工学や広告配信の領域で頻繁に言及される強化学習問題の枠組みにおいても、「強化学習アーキテクチャ(Reinforcement Learning Architecture)」がアルゴリズム設計と同様に重要な位置付けとなっている。この用語自体は、リチャード・S・サットンが1992年に掲載した論文のタイトルとして掲げられている。しかし、このアーキテクチャ概念は、強化学習の構成要素を纏め上げる際のパッケージ程度の意味しか成していない。深層学習における深層アーキテクチャに比して、強化学習における強化学習アーキテクチャには統一的な定義は与えられていないようだ。
その一つの証拠になるだろうが、強化学習を包括的に取り上げた数少ない書籍であるリチャード・S・サットンとアンドリュー・G・バートのReinforcement Learning: An Introductionでは、アーキテクチャという用語はアクター・クリティック・メソッド(Actor-Critic-Method)やDynaエージェント(Dyna agent)を「図示」する文脈で使用されている。そして、ここが重要となるのだが、いずれの文脈においても、「機能(function)」や「関数(function)」との兼ね合いからそれぞれのアルゴリズムが解説されている。文献中で明示されている訳ではないが、誤解を恐れずに言えば、「強化学習アーキテクチャ」という概念は強化学習アルゴリズムを「ブラックボックス化」することで簡略化し、全体像を把握できるようにする解説の技術であると言えるだろう。
実際、強化学習アーキテクチャは、文脈的には「強化学習(Reinforcement Learning)」のアルゴリズムを構造化する概念として記述されている。そしてこのアルゴリズムは一言では語り尽すことのできない複合的な構成要素から成り立っている。
元来、強化学習アルゴリズムは「強化学習問題(Reinforcement Learning Problem)」と呼ばれている問題設定に対する問題解決策に他ならない。この問題設定は、目的を達成するための相互作用(interaction)から学習していくエージェント(agent)が直面する問題の枠組み(framing of the problem)を意味する。
学習者や意思決定者が、ここではエージェント(agent)と呼ばれている。このエージェントの外部のあらゆる諸要素から構成されて、エージェントとの相互作用対象となり得る概念の全ては、「環境(environment)」と呼ばれる。環境はまた、報酬(reward)の発生源でもある。エージェントは、この報酬獲得を最大化することを目指して行動(action)を選択していく。エージェントの行動選択可能性は、環境の状態(state)に左右される。状態は、エージェントが利用可能な情報を意味する抽象的な概念だ。それは環境の一部の情報が前処理されることによって得られる。強化学習問題の枠組みでは、エージェントが状態から選択可能な行動を決定する確率の写像(map)の計算処理が実装される。この写像を特にエージェントの方策(policy)と呼ぶ。強化学習問題ではこの方策の最適化が目指される。
こうした基礎的な概念を整理するだけでも、強化学習アルゴリズムが複合的な構成要素から成り立っていることがわかるだろう。そして、これらの概念を簡潔に纏め上げた上で説明するには概念の抽象化が必要になる。強化学習を「図示」する際に「機能(function)」や「関数(function)」という用語と共に「アーキテクチャ」という用語が使用されていたのは、この概念の抽象化の兆候であったのだろう。
しかしながら、ソフトウェア・アーキテクチャを記述するラタンゼも注意を促しているように、「図」はアーキテクチャではない。確かに設計されたアーキテクチャは「図」を含めた文書によって表現されることはある。と言うより、そうした「図」によって表現されない限り、アーキテクチャ設計の成果物が認識されることは中々無い。しかし実際のアーキテクチャは現実的な諸要素の現実的な諸関連によって構造化されている。アーキテクチャ設計の分析上の最終的な到達地点があるとするならば、それはむしろ実装されたシステムが要求通りにサービスを提供すると共に、要求された属性を有していることが確認される段階にある。
尤も、このラタンゼのアーキテクチャ概念で想定されるのは、アーキテクチャ設計を成功させれば、それによって実装されたソフトウェア集中型システムを要求された通りに動作させることが可能になるという前提だ。これが時に予測不可能な作動を繰り広げる強化学習アルゴリズムに対しても言えるかどうかは、検討の余地がある。
派生問題:アーキテクチャ中心設計は如何にして可能になるのか
「アーキテクチャ中心設計(Architecture Centric Design)」の担い手は、アーキテクチャ概念を含めた様々な概念の抽象化を前提とした上で、アーキテクチャ設計を敢行していかなければならない。アーキテクチャ中心設計の特徴は、「アーキテクチャ設計(Architectural Design, Architecture Design)」と「詳細設計(Detailed design)」の区別を導入することで浮き彫りになってくる。
「簡潔に答えるなら、あらゆる設計上の問題が本質的にアーキテクチャの問題である訳ではない。アーキテクチャ設計は、要求事項からエンジニアの設計活動を中継する場所に位置する。ソフトウェアのアーキテクチャ設計は、詳細設計や実装を実施するための踏み切り台の役目を担うべきであって、下流工程の設計担当者や実装担当者のために明確な境界を定義するべきである。」
Lattanze, A. J. (2008). Architecting Software Intensive Systems: A Practitioners Guide. CRC Press. p4.
言い換えれば、アーキテクチャ設計の機能は、要求定義から詳細設計や実装をブリッジするインターフェイスのようなものになる。
「パフォーマンス、可用性、変更容易性、セキュリティなどのような属性は、システムのみならず、システムを利用し、購入し、保守するステークホルダの要求を満たすように設計されるべきだ。(略)如何なるシステムであっても、これらの属性を詳細水準の設計で達成することはできない。何故なら、これらの要求を満たすには、システムの広範囲の、あるいは全体の諸要素を対象とした調整を必要とするからだ。」
Lattanze, A. J. (2008). Architecting Software Intensive Systems: A Practitioners Guide. CRC Press. p4.
詳細設計はコードの品質に注力する。だがそれだけではステークホルダの要求を満たしたことにはならない。アーキテクチャ設計は、こうしたコードの詳細設計事項が、公開インターフェイス仕様や顧客の要求との関連を見失っていないか否かの検証を可能にする。
「アーキテクチャ設計によってフレームワークの構造が提示されていない状態で多数のソフトウェア・エンジニアたちがシステムの小さなコンポーネントを設計した場合、システムの全体像は、システムが完成するまで把握することができない。設計されたアーキテクチャによって、システムを諸要素に区別するための方法を手にすることができる。そうした諸要素は、後から詳細にまた設計することができる。アーキテクチャがあれば、諸要素の詳細設計と実装を実施する前に、当該アーキテクチャの弱点が明らかになる。最終的に、アーキテクチャは諸要素を如何にして組み立てられるのかを提示することで、システム全体の構築を方向付けるために利用される。こうして、計画通りの振る舞いと属性を有したシステムが制作される。」
Lattanze, A. J. (2008). Architecting Software Intensive Systems: A Practitioners Guide. CRC Press. p5.
アーキテクチャ設計は、まず要求されたシステムを諸要素へと区別する方法を提供すると共に、そうして区別された諸要素を如何にして組み立てられるのかを提示する。言い換えれば、アーキテクチャ設計は要求されたシステム概念に対して区別を導入すると共に、その区別された諸要素のコンポーネント間結合を実現するためのインターフェイス仕様を提示する。
総じて、アーキテクチャ設計は要求事項と実装内容の差異を、ギャップを埋め合わせて補完する役目を持つ。複合的で複雑で、尚且つ未だ実在していないシステム概念を仕様化し、実装を方向付ける枠組みを提供するのが、アーキテクチャ設計の狙いとなる。
問題解決策:アーキテクチャ・ドライバ
要求抽出の対象になる顧客などのようなステークホルダは、大抵の場合、自身が何を欲しているのかを明確に説明することができない。システムで「何ができるのか」についての専門知識は少なく、またそもそもビジネスで「何がしたいのか」も不確定な状態で要求を提示してくる場合もある。これは、例えば人工知能を用いたサービスのように、高度に専門的なテクノロジーやデータサイエンスの知識が背景知識として求められる場合には、特に言えることだ。
アーキテクチャ設計者は、こうしたステークホルダとのコミュニケーションの中で、「アーキテクチャ・ドライバ(Architecture Driver)」を設定することによって、要求を発見し、洗練させ、そして問題として設定する術を手にしなければならない。
アーキテクチャのライフサイクルは、ビジネスとステークホルダによって始まる。ビジネスを構成しているのは、市場、組織システム、予算、スケジュール、利用可能なテクノロジーなどのような諸要素だ。この関連で言えば、ステークホルダは単なる「ユーザー」ではない。ビジネスに関わる広汎なコミュニティを予測できる。
そうしたステークホルダは、ビジネスの文脈で、十分に整理されていない要求を提示してくる。アーキテクチャは、ステークホルダが抱えている問題に対する解決策として機能する。しかしながら、ビジネスの文脈が複合的で複雑であるのならば、それだけステークホルダの抱えている課題を解決すべき問題として設定することが困難となる。考慮すべき諸要素が膨大にあり得るために、迂闊に狭い範囲で問題を設定してしまえば、派生問題に打ちのめされる。逆に初めから風呂敷を広げ過ぎれば、今度は何も解決できない難易度になってしまう。
アーキテクチャ・ドライバとしての要求
アーキテクチャ設計を開始する際、まず真っ先に特定するべきなのは、実装の基盤となり得る構造に最も大きな影響を及ぼす可能性のある要求だ。そうした主要な要求事項が、システムの構造を決定付ける。「アーキテクチャ中心設計(Architecture Centric Design)」では、この主要な要求を特に「アーキテクチャ・ドライバ(Architecture Driver)」と呼ぶ。
アーキテクチャ・ドライバを分析して定義することによって、アーキテクトは適切なタイミングと適切な詳細度で設計に注意を注ぐことができるようになる。
アーキテクチャ・ドライバは、次の4つの要素から構成されている。
- 高水準の機能性(high-level functionality)
- 技術的制約(technical constraints)
- ビジネス上の制約(business constraints)
- 品質特性要求(quality attribute requirements)
これらは皆アーキテクトの設計上の意思決定に影響を与える。その影響の様相はそれぞれ全く異なっている。場合によっては、各要求が矛盾し、対立することもあり得る。
以下では、これら4つの要素について順を追って説明していく。
高水準の機能性
高水準の機能性の要求が意味するのは、そのシステムが可能にする必要のある事柄についての要求だ。ここでいう高水準(high level)というのは、抽象性の度合いが高いということを意味している。文書で高水準の機能性を記述する際には、一般的な用語で、一般的な機能について記述しなければならない。
また、機能性(functionality)という概念が指し示しているのは、単純に可能性に他ならない。したがって文書でこの高水準の機能性が論じられる場合には、基本的に「できること」が表現される。ただし、それは具体的過ぎてもならず、詳細過ぎてもならない。言い換えれば、高水準の機能性を記述した段階では、まだ未加工の要求が残存していても良い。<表面的>であっても、曖昧性を持った要求を俯瞰することが先決だ。それ故高水準の機能性を記述する際に目指すべきなのは、あくまでもアーキテクチャ設計の出発点を明確にすることになる。
高水準の機能性の要求を記述する上では、ユースケース・モデリングが有用となる。ユースケース図はステークホルダの運用視点での要求を可視化する。ユースケース図を観察することで、その要求に関する議論と初期分析が容易になる。詳細な要求をモデル化することが困難な段階であっても、ユースケース図は、アーキテクチャ設計に必要な機能要求の文書化、分析、発見などにおいて有用となる。
ユースケース・モデルはユーザーとシステムの関連だけを可視化できる訳ではない。このモデルはより汎用的な相互作用の観点においても効果を発揮する。例えばアーキテクチャ設計では、実際の生物学的なエンティティや技術的なエンティティとしてアクターを広義に表現することができる。そのため、ユーザーの相互作用のみならず、センサやアクチュエータ、周辺機器などのようなシステムの相互作用においても、ユースケースでモデル化することができる。
ただし、ユースケース・モデルは機能分割のためのモデルではない。そのため、システムがサービスを提供する方法を表現するためにユースケース・モデルを実践するのは誤りとなる。設計の初期段階では特に、システムはブラックボックスとして参照される。だから、システムが「如何にして(How)」サービスを提供し得るのかではなく、「何が(What)」必要なのかという要求を表現することが求められる。言い換えれば、ユースケース・モデルが表現すべきなのは、システムの文脈やスコープにおいて、設計対象の中には「何が」含まれていて、「何が」含まれていないのかという、システム境界である。それは、システムと外部環境の差異を可能な限り明確化することを意味する。これがアーキテクチャ設計の最初の重要な出発点となる。
こうしてユースケース・モデルは、システムによるサービス提供が「如何にして」可能になるのかについての探究を保留にしておくことによって、エンジニアと非エンジニアのコミュニケーション・メディアとして機能する。それはシステム境界を明示することによって、「何が」必要なのかという共通の問題を設定する。このモデルは、その共通の主題に基づいて、コミュニケーションを成り立たせている。
しかしながら、ユースケースを作画しただけで済ませてしまえば、設計は失敗する。図は、千の単語よりも価値がある。だが、誰もが同じ図から同じ千の単語を読み取る訳ではない。図の解釈は偶発的だ。故に、一度ユースケースによって「何が」必要なのかを設定したのならば、次に実施すべきなのは、技術的制約やビジネス上の制約を確認することによって、高水準の機能性が指し示す様々な可能性の制約条件を特定していかなければならない。
技術的制約
技術的制約は、設計との直接的な関連から、事前に決定済みの制約を指す。様々なハードウェア、ソフトウェア製品、OS、レガシーシステム、そして未実装の新たなシステムなどが、こうした制約を生み出している。例えば単純な話、Google Cloud Platform上でプログラムを実装する場合ならば、Googleが決定したAPI仕様に準拠してアーキテクチャを設計せざるを得ないだろう。この時点で、アーキテクトの選択可能な選択肢は大幅に制約されているはずだ。この既存技術による選択肢の制約要因こそが、技術的制約を意味する。
技術的制約は、後述する品質特性要求から区別されている。例えばパフォーマンスのような要求は、品質特性要求に該当する。この要求は、どのようなAPIやプラットフォームを利用しなければならないのかを指し示してはいない。パフォーマンス要求は、あくまでもシステムによって何が可能にならなければならないのかを指し示している。それはシステムの能力に関する制約事項だ。こうした品質特性要求は、Google Cloud PlatformであろうがAmazon AWSであろうが、当の要求さえ満たせば、利用する技術に制約を加える訳ではない。しかし、もし既存サービスの改修プロジェクトで、既にそのシステムがGoogle Cloud Platformを利用していたのならば、Google Cloud Platformを利用することは技術的制約の一つになり得る。
アーキテクチャ設計の担当者が危惧するべきなのは、技術的制約が強固であるが故に、高水準の機能性要求や品質特性要求を満たし得ない状況だ。あまりにもレガシーなコードで実装されている既存システムを改修する場合、もし改修によって実現すべき要求事項と技術的制約が指し示す不可能性との競合が激しければ、開発プロジェクト全体が不安定化してしまう。そのため、技術的制約によって許容範囲となる設計の自由度は、プロジェクトの早い段階で明確化しておかなければならない。さもなければ、技術的に実現不可能なことを安請負してしまう。
一見深刻な技術的制約が見当たらない場合でも、注意を怠ってはならない。何故なら、アーキテクトの設計それ自体が技術的制約を派生させる場合もあるからだ。例えばスキーマレスであるという理由からMongoDBのようなデータストアを採用してしまうと、それだけで、もはや「正規化」や「直交性」のようなリレーショナルデータベース特有の恩恵に浸ることができなくなる。それが危険な状態を招くのは、大方そのアーキテクチャを再利用する場合であろう。その扱い次第でアーキテクチャ設計は、当該プロジェクトのみならず、後続のプロジェクトに対しても、技術的制約を強いる可能性がある。
ビジネス上の制約
ビジネス上の制約とは、設計が始まる前にある既存の意志決定から成る要求だ。それは技術的制約とは区別される。技術的制約がアーキテクト自身の意思決定によって派生し得る制約条件であるのに対して、ビジネス上の制約は主にアーキテクト以外のステークホルダの意思決定から間接的に生じる制約条件である。
ビジネス上の制約は、技術的制約に比して明示的ではない。例えば、システム開発に投資する立場のステークホルダから観れば、全くの新規開発よりも、既存のシステムの再利用や改修の方が、コストが低くて済むかもしれない。いわゆる「横展開」が要求されることは、その技術が如何にレガシーで、如何に技術的負債を招いていようとも、回避するのは困難だ。余程明白かつ深刻な技術的リスクでも無い限り、再利用や改修で済む開発プロジェクトを新規開発プロジェクトに持ち運ぶには、投資対効果を巡る相当の交渉力と心理誘導技術が必要になる。
品質特性要求
品質特性要求は、パフォーマンス、可用性、セキュリティなどのようなシステムの属性に関する要求事項を意味する。これらは、いわゆる「非機能要求(nonfunctional requirements)」に対応している。言葉通り、品質特性要求は上述した「高水準の機能性」とは対照を成す。
しかしながら、この機能要求と非機能要求の区別を導入すると、双方の関連性が盲点となってしまう場合が多い。大抵の場合、品質特性要求と高水準の機能性要求は密接に関連付いている。例えばWebページのレスポンスタイムはパフォーマンス要求やサーバ負荷対策と関連した品質特性要求の一種となるだろう。だが一方でこの指標は「ユーザー・エクスペリエンス(User experience)」を計る上でも言及される。「非」機能要求という消極的な概念規定では、機能性の要求以外の「何か」というところまでしか深追いできない。そのため、アーキテクチャ中心設計においては、これを明示化できるように、「非機能要求」という用語ではなく「品質特性要求」という用語を利用する。
ユースケース・モデルで描写された高水準の機能性の要求は、「何が」必要なのかを主題としていた。これに対して、品質特性要求は「如何にして」システムを実現しなければならないのかを追求する。この意味で品質特性要求はユースケース・モデルでは言及され得ない。この要求をモデル化するのならば、クラス図や相互作用図などのような他の記法が必要になる。尤も、「何が」が定まらなければ「如何にして」も探索し難いだろう。だから、高水準の機能性要求と品質特性要求は相互に関連していると考えるべきだ。
以下では、品質特性要求の一例を取り上げたい。
変更容易性
これは、システムの改修によって得られる機能性や失われる機能性や能力を意味する。
パフォーマンス
これは、一定の期間の間で提供しなければならないサービスを意味する。様々な条件下におけるデータの転送量などが指標となる。
セキュリティ
これは、危険に曝されてはならないデータあサービスを意味する。この対策の文書では、特にサニタイジングなどのような脆弱性対策が明文化されている必要がある。
安全性
これは、例えばフェールセーフなシステムに関する記述となる。
品質特性シナリオ
品質特性要求は高水準の機能性、技術的制約、そしてビジネス上の制約によって左右される。そのためこの要求は、とりわけ当該プロジェクトの文脈から特定していかなければならない。その上でのガイドラインとなるのが、「品質特性シナリオ」だ。
品質特性シナリオは、品質特性要求の表現形式に他ならない。それは次のような概念で要求を形式的に表現することを手助けしてくれる。
刺激
刺激とは、アーキテクチャに影響を与える条件を意味する。あるイベント、ユーザーによるデータ要求、サービスの開始、システム改修の提案などがこれに該当する。
刺激の発生源
刺激の発生源とは、文字通り上記の刺激の発生源となるエンティティを意味する。ユーザー、組織、システムなどが、これに該当する。
発生源は、一つあるいは複数個の場合がある。
関連する環境条件
関連する環境条件とは、アーキテクチャが刺激を受信している最中にシステムが運用されている環境で発生している条件を意味する。この概念を理解する上ではシーケンスが肝となる。例えば、以下のようなシーケンスで環境条件は異なってくる。
- 実行開始時
- 実行中
- 初期開発の期間
- リリース後
- サーバ負荷がピークになっている時
- 700人のユーザーがログインしている状態の時
このように、様々なシーケンスによって関連する環境条件も左右されてくる。
アーキテクチャ要素
アーキテクチャ要素とは、刺激によって直接的あるいは間接的に影響を受けるアーキテクチャの諸要素を意味する。
無論、アーキテクチャ設計初期においては、まだ十分なコンポーネントの区別は導入されていないはずだ。この区別は、プロセスを進めていく上で徐々に洗練化させていくしかない。したがってこの情報は、アーキテクチャ設計の進捗と共に徐々に追求していく必要がある。
システムの応答
ここでいう応答が意味するのは、アーキテクチャやシステムのユーザーとなるステークホルダが期待している応答の詳細だ。これは後述する「応答測定」に関連している。
応答測定
応答測定は如何にしてシステムが応答するのかを測定した概念だ。刺激のレパートリーによって、この応答の種類も増えていく。
ここでいう測定というのは、単にインターフェイスに対する入力から結果的に得られた出力を機能的に把握することを意味する訳ではない。例えばパフォーマンス要求に対応した測定もあり得る。だがそれだけではない。例えば「システムの改修」を一個の既存アーキテクチャに対する刺激と捉えるならば、その結果として得られる出力内容は「成果物」となる。こうした「成果物」に関しては、例えば人的リソースや金銭的リソースの投資対効果などによって測定される。
品質特性シナリオの機能
品質特性シナリオは、パフォーマンスやセキュリティや可用性などのような概念を刺激から応答までの「物語」として把握することを手助けしてくれる。この表現形式によって、設計者はアーキテクチャを巡る入力と出力の機能的な関係のみならず、その内部の処理や周辺環境についても、アーキテクチャの要素や環境条件といった表現形式によって記述することが可能になる。
更に言えば、この表現形式は、ユースケース・モデル以外の統一モデリング言語(Unified Modeling Language: UML)によって補完することができる。環境条件下の刺激から応答までの流れを追求するのならばアクティビティ図やシーケンス図やコミュニケーション図が、アーキテクチャの諸要素を特定していくのならば概念クラス図やオブジェクト図やコンポーネント図が、応答測定を明確化したいのならばステートマシン図などが、それぞれ有用となるだろう。
問題解決策:プロセスとしてのアーキテクチャ設計
以上のように、高水準の機能性要求と品質特性要求が「何を」「如何にして」実現するべきなのかを指し示すのに対して、技術的制約とビジネス上の制約はその可能性の諸条件を指し示す。無論、双方は競合するのが常だろう。まさにこの矛盾を明確化することこそが、アーキテクチャ・ドライバの大きな存在意義となる。完全な設計を追求するのは非現実的だ。完全な折衷案を追求することこそが現実的になる。このことは、とりわけ人工知能開発のように、高度に専門的なテクノロジーやデータサイエンスの背景知識が求められる場合には、特に言えることだろう。全てのステークホルダが技術や科学を理解できている訳ではないからだ。
概念の前処理:未加工な情報から加工された情報へ
ステークホルダの要求事項やシステム要件が記述された文書も、場合によっては得られるだろう。しかしそうした文書は大抵の場合不正確であるか、鮮度が無い。最初の要求抽出の成果物は、未加工の要求を対象としている。未加工であるというのは、そうした要求にはステークホルダや代理者や開発チームによるブレーンストーミングや思い付き、閃きも含まれているからだ。これらは構造化されていない要求やニーズを指し示している。
アーキテクトの最初の仕事は、こうした未加工の情報を分析して整理することとなる。そうすることで、未加工の要求事項を設計プロセスを円滑に進めていけるような形式に加工していかなければならない。ステークホルダとの交渉と調整を交えながらその加工整理した情報からアーキテクチャ・ドライバとして抽出することが、アーキテクチャ設計の出発点となる。
問題解決策としての問題再設定
プロジェクトが進むにつれて、新たなステークホルダが発見される。それにより、また新たなアーキテクチャ・ドライバが発見されるだろう。アーキテクチャ・ドライバを理解する上での最良の方法は、反復的にアーキテクチャを探索して、設計の探索を通じて学習した知識に基づき、計画的かつ規律に従った方法でアーキテクチャ・ドライバを洗練させていくことである。
設計初期から、潜在化している技術的な問題と更なる要求やニーズを可視化していくことが求められる。要求抽出、設計、アーキテクチャ・ドライバの洗練化は、密接に絡み合っている。
このことから言えるのは、アーキテクチャ設計は単発のイベントではなく、プロセスに他ならないということだ。アーキテクチャ・ドライバは要求の全てを物語る概念ではない。それは設計に最も影響を与える要素を意味する。そしてこの影響の度合いは、重点の置き方次第で偶発的に変異し得る度合いだ。どのような機能要求、技術的制約、ビジネス上の制約、そして品質特性要求を重く受け止めるのかによって、アーキテクチャ・ドライバは別のあり方でもあり得る。だからアーキテクトは、反復的にアーキテクチャ・ドライバを記述し続けて、洗練化させていかなければならない。
これを前提として言えば、アーキテクチャ・ドライバは何度も再記述されるべきだ。そしてこの再記述によって、高水準の機能性要求や品質特性要求が指し示す理想や目的と、技術的制約やビジネス上の制約が指し示す現実や方法が、「乖離」として、「競合」として、「矛盾」として、再認できるようになる。そしてこの「差異」の記述によって、問題を再設定する意識が芽生える。それに応じて、また新たな問題解決策を設計していくことになる。かくしてアーキテクチャ設計は、問題を設定してはまた再設定し、そのプロセスの中で解決策を探索し続ける絶え間無い「循環」の中に根を下ろす。
問題解決策:静的視点と動的視点と物理的視点の区別
アーキテクチャ・ドライバは、以上のような循環的なアーキテクチャ設計の営みによって、言わば変異性が高い。だが変異性の高いアーキテクチャ概念を目にしては、その複合性や不確実性が増大していくに連れて、次第に視野狭窄に陥ってしまう。
そこで、アーキテクチャを観察した場合に冗長的に発現している属性を把握することが必要になる。アーキテクチャに対する一種のパターン認識によって、アーキテクチャを認知していくことが求められる。
アーキテクチャ設計ではシステムの構造も明確化しなければならない。だが、直ぐに構造とは「何か(What)」に対する回答を与えるよりは、その構造の観察による認識が「如何にして(How)」可能になるのかを考えた方が良い。何故なら、構造は当該プロジェクトの要求事項によって左右されるからだ。その一方で、構造の観察を可能にする視点は、各プロジェクトに左右されず、抽象化できるほどに共通点がある。故にアーキテクトやソフトウェア・エンジニアは、安易に「構造とは何か」を考察するのではなく、その観察による認識が如何にして可能になるのかを追究した方が良いだろう。
私の知る限り最も示唆に富むアーキテクチャ設計の実用書の一つであるArchitecting Software Intensive Systems: A Practitioners Guideでは、アーキテクチャ設計で言及すべき「構造」は次の3つの視点によって観察し得ることが説明されている。
- 静的視点
- 動的視点
- 物理的視点
勿論、この区別を採用することには必然性は無い。ただし、ある種のベストプラクティスとして機能する有用なノウハウとしては、選択可能であろう。まずはこの「静的視点」と「動的視点」と「物理的視点」の区別を導入するところから始めてみよう。
静的視点
概念の具体例
例えば次の項目が該当する。
静的視点では次のような関連に着目することになる。
- 使用
- 継承
- 拡張
- 注意点
アーキテクチャ設計では、クラスやプロシージャや関数をコードの構造として捉える訳ではない。アーキテクチャ設計では、より粒度の粗い構造として関連概念をグルーピングする。アーキテクチャ設計では、これらのクラスや関数を抽象化して、細かな各構造を束ねて纏め上げる。アーキテクチャ設計の担当者はあえて粗い粒度で構造を定義する。そして、その構造内部に隠蔽された諸要素の責任を明確化していく。各構造内部のより詳細度の高い実装水準の諸要素に関しては、よりコードに近接している下流工程の担当エンジニアに委ねることになる。
しかしながら、静的視点としてコードを追うだけでは、不十分な部分が残る。例えばコンパイルされたプログラムは、コンパイル前とは異なる構造になる。だとすると、静的のみならず動的な視点からも構造を分析していかなければならない。
動的視点
動的視点はプログラムの実行時の構造に向けられる。計算を処理する場所に向けられる視点とも言える。
概念の具体例
以下のような概念が相当する。
関連の具体例
動的視点では以下の視点に着目する。
動的視点の重要性
動的視点は、パフォーマンス、負荷対策、動作の並行性、リソースの活用状況、可用性、異常性検出などといった属性を分析する上で必須となる。
物理的視点
物理的視点では、システムの「実物」そのものに対する観点となる。必要不可欠なインフラを調達する際には、この視点が求められる。
概念の具体例
要素と関連の差異
これら3つの視点の機能は、諸要素(elements)と諸関連(relations)の区別を導入することで、より明確化するだろう。
設計初期段階のアーキテクチャは、諸要素と諸要素間の様々な諸関連による全体的な調和の産物として記述される。しかしながら、要素という概念は、アーキテクチャの構造に関して、視点に関わり無く論じる際に利用される。要素は、ある視点から観た場合のアーキテクチャのある構造に対する一般的な言及によって認識される。そして、そうして認識された要素をある視点と関連付けると、それがモジュールなどに向けられる静的視点である場合や、プロセスなどに向けられる動的視点である場合や、コンピュータなどに向けられる物理的視点である場合など、多聞に及ぶ。一方、ある関連を視点に関連付けた場合は、使用概念のような静的視点、データフローのような動的視点、ネットワークケーブルのような物理的視点など、別の様々な関連概念を特定することになる。
初めに区別ありき
したがって、アーキテクトがその設計内容を理由付けするには、特定の構造を識別しなければならない。このことが意味するのは、まず視点を特定しなければ、構造も特定し得ないということだ。視点を特定して初めて、特定の諸要素と諸関連が視えてくる。それが構造として把握できるようになる。アーキテクトがシステムを分析する際には、その分析のために、最初にどの視点が最適であるのかについて、意思決定を実践することになる。
このためアーキテクチャ設計では、構造の定義に先立って、まず視点の区別が導入される。しかもこの区別は二重に導入される。つまり、<諸要素に対する視点>と<諸関連に対する視点>の区別が導入されると共に、静的視点と動的視点と物理的視点の区別が導入されることによって、その境界線が言わば構造の輪郭と化し、その観察と認識を可能にする。
静的ビューと動的ビューと物理的ビューの差異
こうして区別された視点から認識された構造は、アーキテクチャ設計書に記述される。各視点に対応した記述項目を特に「ビュー(View)」と呼ぶ。つまり、静的ビュー、動的ビュー、物理的ビューなどのような様々なビューが設計書に盛り込まれることになる。
しかし、上述した区別の導入によって差異が明確となったビューを、1枚の図で網羅的に表現しようとすることは、避けた方が良いだろう。キュビズム的な多元的で複眼的な表現は芸術の鑑賞でこそ機能するが、実務では誤解を招く恐れがある。基本的にビューごとに文書の項目を分けるべきだろう。その上で、各ビューの関連を改めて記述した方が良い。
文書化はアーキテクチャ設計における重要な成果物の一つとなる。様々なビューに関する情報を収集して記述した文書は、アーキテクチャ設計の表現形式として整頓された一種の「モザイク画」となる。アーキテクチャ設計の表現が、実装で実現しようとしている構造とその関連を忠実に指し示すことで、アーキテクチャ設計の段階で約束された機能性と属性をシステムに備えさせることが可能になる。こうしたアーキテクチャ設計書は、重要なシステムの構造に視点を定め、アーキテクチャ・ドライバの影響をより高い精度で再記述する上での助けとなる。
問題解決策:<品質特性の促進>と<品質特性の抑制>の区別
静的視点と動的視点と物理的視点の区別を導入することで、アーキテクチャの設計者は様々な構造を発見することができる。だが、構造の概念規定は別のあり方でもあり得る。最終的には、発見された複数の構造の候補の中から特定の構造を選択しなければならない。
アーキテクチャ設計におけるアーキテクトの構造選択は、直近の開発のみならず、システム、エンタープライズ、アプリケーション、そしてプロダクト・ライフサイクルを通じて、品質特定のプロパティに強い影響を与える。逆に品質特性要求のようなプロパティは、後続のアーキテクチャ設計やその実装に強い影響を与える。
この影響の度合いは、<品質特性の促進>と<品質特性の抑制>の区別を導入することで、より明確になるだろう。アーキテクチャ設計における構造の選択は、一部の品質特性を促進する一方で、その他の品質特性を抑制する。そのため、品質特性は構造化を意図するアーキテクトの意思決定にも左右される。
アーキテクトは品質特性のプロパティと構造とを天秤に掛けなければならない。アーキテクトがシステムの一部の組み合わせとして選択した構造は、システム全体の品質特性を促進あるいは抑制する。アーキテクトは、諸々の構造と諸々の品質特性の関連を見極めるために、複数の視点から構造を比較検討しなければならない。そうしなければ、予測可能な形で要求される品質特性を保有する製品やシステムを実現するのは困難になる。
品質特性への影響力
アーキテクトによる構造選択と品質特性が相互に影響を与え得るのならば、その影響の与え方を明確に留意しておくことによって、アーキテクチャ設計におけるある構造の選択が品質特性の各プロパティにどのような影響を及ぼすのかを推論することが可能になる。つまり、予め予期した品質特性から逆算する形で構造を選択することもできるようになる。この逆算を上手く進められれば、品質特性要求に見合うアーキテクチャの構造を選択することも不可能ではなくなる。これが最終的にはアーキテクチャのサービス価値や顧客満足度に結び付いていく。
様々な品質特性に影響を与えることを可能にする設計技術の原則として、分離、結合、凝集、リソースの集約、リソースの分散、冗長化などを挙げられる。これらは言わばベストプラクティスやノウハウのようなもので、選択することに必然性は無い。だがこれらの設計技術は方法として抽象化されているために、どのようなアーキテクチャの設計においても選択可能であるだろう。これらの原則は意思決定を求められたアーキテクトがその設計の方向性を見出す上でも有用となる。
いずれの原則も、開発プロジェクトに対して、<品質特性の促進>と<品質特性の抑制>の差異を前提としたトレードオフの影響を与える。アーキテクチャ設計の担当者は、このトレードオフを前提とした上で、最終的には意思決定者として判断しなければならない。
アーキテクチャの分離
アーキテクチャの「分離(decoupling)」は、あるシステムを独立して自足可能な諸要素や構造に区別する設計技術だ。基本的に分離されたアーキテクチャは、サービスを提供する上で、他の諸要素や構造、情報源には依存しない。アーキテクチャの分離は、スケーラビリティ、拡張性、柔軟性、メンテナンス性など、様々な変更容易性と再利用可能性を高める。
アーキテクチャの分離を実現するには、諸要素の関連を単純かつ最少に留めることが必要となる。しかし、この類の関連は分離を促進するものの、一般的にはスループット、待ち時間、応答時間などのパフォーマンスを抑制する。
分離は、あらゆる視点から可視化できる。ただし、ある視点において分離しているアーキテクチャが、他の視点でも分離していることになるとは限らない。例えば分離されている静的な構造も、コンパイル後の動的な視点として眺めて観れば、緊密に結合している場合は多々ある。
ある視点での分離が、他の視点での分離との依存関係を形成することもあり得るだろう。例えば、分散処理要求が実現するためには、物理的構造と動的構造の双方が強調して設計されていなければならない。
アーキテクチャの結合
アーキテクチャの「結合(coupling)」は、諸要素間の高度な相互依存関係を意味する。これは分離と対照を成す。この意味で結合は分離によって得られるメリットを否定している。むしろそのメリットは抑制されるだろう。
しかし、密結合なアーキテクチャが選択されることは、理由の無いことではない。分離はパフォーマンスを抑制するのであった。これに対して結合は、結果的にシステムの実行時のメモリのフットプリントを小さくする。とりわけこのメリットは組み込み系で重視されている。
アーキテクチャの凝集
アーキテクチャにおける「凝集(cohesion)」は、簡単に言ってしまえば、「単一責任の原則(Single Responsibility Principle: SRP)」が意識された時の設計技術となる。
アーキテクチャ上では、諸要素が単一の構成で、それが明確なタスクやサービス、データの集合を提供するような場合に、凝集度は高いと認識される。凝集を実現するには、関連性のある責任を一つのアーキテクチャの諸要素として割り当てるべきである。
凝集度の高いシステムでは、サービスを提供する要素において、その欠陥を発見し、変更や拡張を行なうべき諸要素を特定することが容易になる。ただし凝集は、その一方で、諸要素の複合性を高める。それは諸要素の関連を増加させる。そうなると抽象の度合いは高くなる。結果的に、実行時のメモリのフットプリントを高めることによるパフォーマンスの低下を招いてしまう。
確かに凝集度の低いシステムは、変更容易性やメンテナンス性を抑制する。だが上述した凝集の高さ故のデメリットは回避できるため、相対的にパフォーマンスは向上する。
アーキテクチャにおけるリソースの集約
アーキテクチャにおけるリソースの「集約(consolidation)」と述べた場合、そこで言及されるリソースというのは、データ、メモリ、周辺機器、プロセス帯域などのシステム上のリソースを意味する。リソースの集約という設計技術は、こうしたリソースのユースケースを管理する技法であると言える。
通常、ユーザーによるリソースへのアクセスは、インターフェイスやミドルウェアなどによって制御される。それらのアクセス機構は、リソースの可視性やアクセサビリティを管理する。
リソースの集約によって得られるメリットは、スケーラビリティや拡張性などのような変更容易性が促進されることだ。リソースが集約されているのならば、ユーザーと当該リソースの接点は最小限に留まる。結果、ユーザーは共通化された方法でリソースにアクセスできるようになる。通信プロトコルやデータ構造に変更が加えられる予定であっても、リソースが一元管理されていれば、その変更のトレーサビリティも容易になる。
しかし、リソースを集約すると、集約した周辺機器やリソースをプールした箇所にボトルネックを生成することになる。結果としてそれはパフォーマンスを抑制することにつながる。
リソースやそれらを格納した構造や諸要素は、システムの感覚のポイントとなる。プロトコル、データ構造、データモデルなどが変更される時、それを参照している全てのシステムの諸要素が影響を受ける。そうした影響範囲を可能な限り小さく留めるために、場合によっては、古いプロトコル、データ構造、データモデルを維持するための中継地点が要求される。
データ構造やデータモデルは、静的な構造として把握される場合もあるだろう。しかしながら、リソースの集約によって得られるメリットとデメリットは、そうしたリソースへのアクセスを実行する処理フローに関する動的視点や物理的視点も求められる。実際には、動的な構造や物理的な構造が明らかとならない場合には、まだリソースの集約の可否を判断するべきではない。
アーキテクチャにおけるリソースの分散
リソースの「分散(scattering)」は、リソースの集約と対照を成す概念だ。リソースの分散とは、一つ以上の諸要素が二つ以上のリソースに対して論理的あるいは物理的に異なるプロトコルや異なるデータ構造を用いてアクセスすることを意味する。
データベースサーバとWebAPサーバに分散される場合など、分散したリソースはパフォーマンスを促進する。そして、複数の諸要素が一つのリソースにアクセスする場合の複雑性や問題を解決することが可能になる。
しかし、分散したリソースは慎重に管理しなければ、スパゲッティコードの如く、無駄に複合性の高い依存関係を生み出してしまう。複数の同一のデータを複数の異なる諸要素に提供するようなアーキテクチャを設計する際には、特に気を付けなければならない。例えば分散しているリソース同士を「同期」させて一貫性を維持するためには、複雑なメカニズムが必要になるからだ。
もし適切な設計や管理が行き届いていない場合、大量の無関係なファイルが散乱し、気付いた頃には無数の設定ファイルが散在してしまうことになる。慎重に考慮されて設計されて管理された分散は、可用性とパフォーマンスの点において、有用な設計技術となる。
しかし場当たり的な分散は変更容易性とメンテナンス性を抑制する。パフォーマンスを予測不可能にする。そしてシステムの複合性を増大させてしまう。リソースの集約とリソースの分散の区別は、この観点からも慎重に導入されなければならない。
アーキテクチャの冗長化
冗長性(redundancy)は、一般的に可用性を促進する。そしてそれはパフォーマンスを改善する。ただし、そうした冗長化の機能は、その問題設定において区別されている。例えば、可用性を促進するための冗長性の設計技術がパフォーマンスを改善するとは限らない。逆に同時並行プロセスを可能にすることでパフォーマンスを促進する設計技術が実現しても、それそのものが可用性を促進するとは限らない。冗長化は解決すべき問題のプロパティに応じて選択するべきである。
別の言い方をするなら、冗長化の設計技術は問題志向型で選択する必要がある。設定した問題の解決に有用でないのならば、選択するべきではない。不用意な冗長化は、可用性とパフォーマンスを向上させるが、同時にシステムをより複合化する。それは、メンテナンスと変更に伴うコストを増大させるという意味で、経営的にも危機を招く。
問題解決策:構造推論のフレームワーク
マイクロサービス同士の疎結合や他社のAPIとのマッシュアップ、フルマネージド・サービスの援用、あるいは既存システムを改修する場合でも、既成のアーキテクチャの構造を再利用することが求められることは、間々ある。全てをゼロから内製することは、現実味が無くなっている。このことは「アーキテクチャ中心設計(Architecture Centric Design)」においても同様に該当する。アーキテクチャ設計は、既存のアーキテクチャを組み合わせることによって成立する場合も往々にしてあり得るだろう。
しかし、既存のアーキテクチャを再利用する場合の前提となるのは、そのアーキテクチャの構造を利用可能な程度に、最低限「機能」的に把握していることだ。言い換えれば、ここで求められるのはアーキテクチャのHow to use it.で、すなわち「使い方」に関する機能知であると言える。そして、そのアーキテクチャの構造を分析できているということが、この「機能」的な把握の前提に当たる。
デザイン・パターン、アーキテクチャ・パターン、スタイル、イディオムなどのように、既知の構造は多数散見される。しかしながら、それらがそれ自体として一貫性を維持している訳ではない。これらのノウハウは「共通言語」として記述されている。だがその共通性は<反事実的>に、規範であるかのように、期待されているに過ぎない。と言うのも、これらの「共通言語」はそれ自体として共通化されている訳ではないからだ。例えばデザイン・パターンを提唱しているのはGoF(Gang of Four)だけではない。この「共通言語」は別のあり方でもあり得る。
こうした背景から、我々は標準化団体による標準化やデファクトスタンダード化によって形式化されているノウハウや「共通言語」を安易に鵜呑みにする訳にはいかない。このことはアーキテクチャ中心設計においても該当する。既存のアーキテクチャを再利用して結合させようとしているアーキテクチャ設計者は、既知の構造がどのような視点や設計技術によって記述されているのかを注意深く区別して観察しなければならない。
アーキテクチャの構造が文書化される場合、その粒度は文書次第で区々だ。それは、アーキテクチャ設計における「視点」に依存している場合もあれば、アーキテクチャの構造選択における設計技術にも依存している場合もある。
それ故、抽象性の度合いという点においても、アーキテクチャ設計者はその分析に注力しなければならない。
分析には文書が必要になる。だがあらゆるアーキテクチャの構造が文書化されている訳ではない。例えばデザイン・パターンで記述されている構造は、今でこそ明示的に語られるようになっている。だが、これらのノウハウは、元々は熟練者たちの暗黙のうちに語られていた経験則であった。デザイン・パターンは、こうした暗黙裡のノウハウを形式化させたからこそ明示的になっている。
個別具体的な開発チームの各現場では、それぞれのメンバーたちによるそれぞれの経験則が蓄積されているだろう。それはアーキテクチャの構造を主題とした場合にも該当する。それら全ての構造に関する知がこうした形式化の対象となっている保証は何処にも無い。
最も重要な問題は、現実のシステムが同時に共存する複数の構造によって成り立っているということだ。現場で保守されているシステムは、単一のアーキテクチャ・パターンやスタイルによって綺麗に纏まっているとは限らない。それは大規模なシステムであればあるほど、複合的な構造として実現している。
マイクロサービス同士の疎結合や他社のAPIとのマッシュアップ、フルマネージド・サービスの援用などを見据えてアーキテクチャを設計するのならば、この問題は既存システムの変更時のみの問題ではないということがわかるだろう。現実のシステムは複数の構造の集合体に他ならない。
構造推論のフレームワークの機能
アーキテクチャ中心設計では、この構造の分析に活用できるフレームワークが提供されている。ここでは、このフレームワークである「構造推論のフレームワーク(Structural Reasoning Framework)」を取り上げておこう。
構造推論のフレームワークの機能は、大別して以下の5項目で纏め上げることができる。
- 設計の出発点を提供する。
- 特定の品質特性要求を促進させる構造選択を負担軽減する。
- 既存の構造を体系化し、分析し、複数の構造を組み合わせる。
- 知識の再利用を促進させ、他の設計者の経験を活用する。
- 設計者に対して、構造や設計内容を表現する上での「共通言語」を提供する。
\4. の知識というのは、一般的な知識のみならず、組織に固有の知識や、ある領域に特化した知識も含まれる。5. の「共通言語」とは、これによって表現された設計内容や構造に関して、そのプロパティやメトリクス、あるいは所与の文脈において伴っている盲点を埋め合わせる「議論」を可能にするという意味での「共通言語」となる。
フレームワークの記述形式
このフレームワークでは、アーキテクチャの構造の関連概念を以下の9項目でテーブルに纏めるか、箇条書きすることになる。
構造名あるいは参照
関連するシステム
視点
構造を視覚化する視点を明示する。例えば静的視点と動的視点と物理的視点の区別を導入するならば、そのいずれかの視点を明記する。
諸要素と諸関連
構造に含まれている諸要素と諸関連を記述する。各要素の責任を可能な限り明示する。また、諸関連の責任範疇についても言及する。
トポロジー
諸要素や諸関連の図示形式を明記する。ダイアグラムが諸要素や諸関連を通じて一貫性があるか否かを確認する。
しばしば設計者は「箱」を「線」で繋いだだけで設計図を記述しようとする。それはシステムの標準化された抽象表現として機能している。それが「統一モデリング言語(Unified Modeling Language: UML)」で表現されているのか、Data flow diagram(DFD)で表現されているのかによって、読み手の構造に対する認識は大きく左右される場合もある。こうした表現形式を、ここではトポロジーと呼んでいる。
トポロジーは、設計の始まりに過ぎない。トポロジーを図示すれば設計が終わる訳ではない。トポロジーは構造の分析の負担軽減としては機能するだろうが、分析それ自体ではない。
したがって、既存の文書化されているトポロジーを観察するだけでも、その構造に関する推論が可能になる。例えば詳細クラス図やコンポーネント図が存在している一方で、ステートマシン図や相互作用図が存在しないシステムであれば、そのシステムには、静的視点よりも動的視点において構造的な問題が潜在化していると推理することもできるだろう。また、静的視点に問題が孕んでいる可能性が低いか否かは、その入手できているクラス図やコンポーネント図から概観することはできる。
意味論
ある構造を利用する際の制約や規則を記述する。その制約や規則に十分な根拠があるか否かも確認しておく。
意味論(Semantics)は、言わば構造を利用する際の規則(rule)のようなものだ。例えばLayers Patternは、いずれの階層も直下の階層のサービスのみを呼び出すことができる。そしていずれの階層も、直上の階層に対してサービスを提供する。あるいはより身近なパターンとして、Template Method Patternに準拠した初歩的な抽象クラス設計ならば、当該抽象クラスを継承したサブクラスでは高い確率で抽象メソッドを具象的に再記述していると推論できるだろう。
意味論を把握していれば、その構造に起因する品質特性が実装されていることを知ることができる。無論、抽象の度合いが高い意味論ならば、それが具象的に破られる可能性はある。例えば根幹となるメソッドの機能が不用意なオーバーライドによって変更されている場合など、スパテゲティコード化しているアーキテクチャの構造においては、意味論は機能不全に陥っている場合もあり得るだろう。とはいえ、そうした意味論に対する期待外れな状況に関する情報もまた、そのアーキテクチャを利用する上では重要な要素となる。つまり、知っておいて損は無い。
品質特性に対する影響度
品質特性に対する影響を<品質特性の促進>と<品質特性の抑制>の区別を導入することで記述する。可能ならば、促進や抑制の理由も明記した方が良い。何故なら、アーキテクトが選択した構造によって、品質特性が左右されるからだ。例えば上述したLayers Patternならば、変更容易性は促進されるが、パフォーマンスは抑制される。こうした品質特性の促進と抑制は、主に顧客満足度やユーザー・エクスペリエンスを背景としたトレードオフの関係を形成している。故にその構造を再利用する際には、既存の意味論を踏襲するか、あるいはあえて破り変更するかを検討する必要があるだろう。
利用される文脈
当該構造の共通の利用方法や、その構造が現われる領域や粒度を記述する。可能ならば、関連する方法論や方式も明示する。それがオブジェクト指向設計なのか構造化設計なのかがわかるだけでも、構造が利用される文脈に関する有用な情報になり得る。
構造の派生
可能な限りその構造の派生を記述する。そしてその派生が品質特性に影響を与えるのならば、その影響度や影響内容も明記しておく。
参考文献
- D.E. Rumelhart, G.E. Hinton, and R.J. Williams, “Learning representations of back-propagation errors,” Nature, 323, 533-536, 1986.
- Lattanze, A. J. (2008). Architecting Software Intensive Systems: A Practitioners Guide. CRC Press.
- Sutton, R. S. (1992). Reinforcement learning architectures. Proceedings ISKIT,92.
- Sutton, R. S., & Barto, A. G. (1998). Reinforcement learning: An introduction. MIT press.
- Turing, Alan Mathison. (1936). On computable numbers, with an application to the Entscheidungsproblem. J. of Math, 58(345-363), 5.
- Turing, Alan Mathison. (1950). Computing machinery and intelligence. Mind, 59(236), 433-460.