Pattern (1) パターンとは
ソフトウェア分野で設計(design)とアーキテクチャ(architecture)はよく登場する単語で、家を設計することを例にとってみれば家の形態、外観、立面度、空間や部屋の配置などを意味します。 建築家が設計した図面を見ると、前述のような高水準の設計事項とコンセント、配線、ドアのいずれもどこに位置するべきかといった詳細事項も一緒に含まれます。 ソフトウェア設計もこれと同様に、高水準の設計と低水準の設計の両方を含み、結局一つのソフトウェアは高水準から低水準に数多くの設計と決定事項で構成されています。
パターンとは
各デザインパターンは、既存の環境内で繰り返し起こる問題を説明した後、その問題に対する解決策の核心を説明してくれます。 同じ方法で2回もしないで、この解決策を100万回以上再利用できるようにですね。 [クリストファー·アレクサンダー]
ソフトウェア開発者は、常にさまざまな問題に直面して生きています。 同じ問題状況を繰り返して経験すれば、これに対する解決法を整理しておいたりします。 ある問題に対する情況(context)と問題(problem)、そして解法(solution)を一緒に整理して記述すると、これを「パターン」といいます。 つまり、パターンとは、「ある状況で特定の問題が発生したときに解決する方法」を意味します。 ソフトウェアの開発者が経験するほとんどの問題状況は、すでに以前の開発者によって扱われ、解決された確率が非常に高いです。 それなら、開発者がこのようなパターンをよく学習した後、自分の問題状況を最も効率的に解決できるパターンを見つけることができれば、問題を解決するのに費用を非常に節約することができるでしょう。
世界を変えた創造は模倣から始まった [デヴィッド·マレー]
パターンは一般的に、パターン記述スキーマによって問題が発生した情況、そして問題の要求事項(requirements)、制約条件(constraint)、特性(property)と期待する結果の影響力(forces)を一緒に記述し、解決策を提示します。 繰り返しの問題状況で、パターンは「経験豊富な専門家が得た設計知識の精髄を集めて再利用できる方法を提供したもの[GHJV93]」で、パターンを進化(evolution)させ、変形(trasformation)して新しいパターンを作り出したり、パラダイムの転換を通じて解決法の基本的な構造から再設計することができます。 技術が発展するにつれて、さまざまなパターンが生まれ、消えることを繰り返し、時代と状況に合った適切な解決策が求められます。
Pattern(2) それなら正しい解決法とは何か?
ソフトウェアの価値は、行為(behavior)と構造(structure)からなる[マーティン]
ソフトウェア エンジニアリングでは、ソフトウェアを機能要件と非機能要件に分けます。 マーティンが言う行為は機能的要求事項に該当し、非機能要求は構造に該当します。 機能的要求事項だけに集中すると、ソフトウェアの拡張性(Exstensibility)、適応性(Adaptability)、パフォーマンス(Performance)などが大きく低下し、メンテナンスが不可能なソフトウェアが誕生する可能性があります。 非機能要求だけに集中すると、ソフトウェアはユーザーに配信(delivery)するのに遅延を生じさせる可能性があり、これは企業の価値/収益創出に害を及ぼす可能性があります。
クリーンアーキテクチャーでは、上記のような状況のヒューリスティックモデルとして、配布(Release)による生産性(Producivity)モデルを提示します。 開発者の人数が増えた分、平行になり、製品は大きくなる必要があります。 しかし、人員が増えたにもかかわらず、製品のライフサイクルとボリュームが期待したほど増えていなかったら、現在の製品と組織が正しい方向に進んでいるのか疑ってみるに値する現象であることは明らかです。
アイゼンハワー マトリックスは、これらの意思決定が必要なときに良いモデルを提案します。 アイゼンハワーマトリックスは、アメリカの大統領ドワイト·D·アイゼンハワーが考案した緊急性と重要性に関する意思決定モデルで、次のような優先順位を持ちます。
- 緊急で重要なこと
- 重要だが緊急でないもの
- 緊急だが重要でないもの
- 緊急でも重要でもないこと
ソフトウェアの非機能要求、構造、設計などは、重要だが緊急ではないものに該当する可能性があります。 ソフトウェアの機能的要求事項、行為などは緊急ですが重要ではない場合があります。 もちろん、あることは緊急で重要なこともあります。
結局、完璧な解決策は存在しないことであり、正しい解決策とは現在の状況(context)と問題(problem)に合うように「適正な生産性」を維持し、「収益創出」が可能なソフトウェアをユーザーに持続的に伝達できるようにすることです。
Pattern (3) 重要なことと重要でないこと
アイゼンハワーマトリックスで見たように、まず、何らかの要求事項を重要なものと重要でないものに分けることができなければなりません。 お金や時間のような資源は有限であるため、どこにこれらの費用を費やすかについての決定は必然的です。 企業は結局利益のための集団である点から見て、ソフトウェアは結局顧客に渡される一種のサービス(Service)で、顧客に与える核心価値(Core Value)が最も重要なものであり、核心価値は産業、ライバル会社から競争優位(Edge)を占めることができます。 有限な資源を投入するなら、核心価値を保存し、拡張し、高めることに集中するのが合理的です。
Eric EvansはDDDで上記のように製品のコア価値を保存することをCore Domain(コアドメイン)と呼び、次のように述べています。
CORE DOMAINに最も才能のある人材を割り当て、それに応じて人材を採用せよ。 システムのビジョンを遂行するのに十分な時層モデルを探し、柔軟な設計を開発できるようCOREに努力を傾け、他の部分への投資は、その部分がどのようにCOREを補助できるかに正当化せよ[エリック·エヴァンス]
Pattern (4) ソフトウェア開発の適正な生産性を維持する方法
クリーン·アーキテクチャーが提案したヒューリスティック·モデルのように、なぜ開発が進むほど生産性が落ちるのかを調べる必要があります。 ソフトウェアは、開発が進むにつれてコードが長くなり、さまざまなビジネスロジックが生まれます。 これをドメイン複雑度(Complexity)が増えると表現します。 また、ソフトウェアと組織の規模が大きくなるほど利害関係者が多くなり、ソフトウェアの最初の設計意図とは異なる方向に開発がさらに進む可能性があります。 この過程でヒストリーと脈絡がよく共有されず、既存の設計意図を把握できないまま開発が進行されたりします。 つまり、開発者が理解しなければならないことが多くなるほど、生産性が低下します。 チームトポロジー[メツスケルトン]では、このような状況を認知負荷理論を例に挙げて説明しています。
認知負荷理論[Sweller,1988]は、内的認知負荷、外的認知負荷、そして本質的認知負荷(germanecoginitive load)に分けられますが、内的認知負荷(intrinsic cognitive load)とは、課題と問題の難易度による認知負荷で、例えば、Java開発だけをしてきた開発者が急にPython開発をしなければならない状況での認知負荷を意味します。 このような場合には、教育を通じて内的認知負荷を解消することができます。 外的認知負荷(extraneous cognitive load)とは、課題や問題の難易度ではなく外的に来る認知負荷を意味します。 開発を完了した後、サーバーに配布する必要がありますが、サーバーの配布に特定のスクリプトやルールが必要な場合を例に挙げられます。 チーム トポロジでは、このような状況で自動化を通じて一部解消できると説明します。
そして最後に、本質的な認知負荷(germanecognitive load)は、実際の課題と問題に対して解決しようとする認知負荷で、もしオンラインバンキングシステムを開発しているなら、どのようにしてユーザーの口座に財貨を振り込んでくれるのか、もしソーシャルネットワークサービスを開発しているなら、どのようなコンテンツをユーザーに見せるのかに対する悩みを例に挙げることができます。
つまり、会社と製品の核心価値を上げることは本質的な認知負荷に該当する悩みと考えで、ソフトウェア開発に参加する人々の内的認知負荷と外的認知負荷が少なく、本質的認知負荷の比率が高い時にソフトウェア開発の生産性を高い状態で維持することができます。
Pattern(5)アーキテクチャとパターンの分類
ソフトウェアでよく言われるアーキテクチャ(Architecture)は、よく大規模なシステムあるいはソフトウェア構造を意味するものとして描かれますが、アーキテクチャの語源を見てみると、アーキテクチャパターン(Architectural Pattern)の略です。 パターンは、解決する問題の規模によって3つの分類に分けられますが、アーキテクチャパターン、デザインパターン、イディアムがその例です。 Posa1で紹介された3つの分類の定義を一緒に見てみましょう。
- アーキテクチャパターン(Architectural Pattern):ソフトウェアシステムの基本構造を構成するためのスキーマ、このパターンはあらかじめ定義されたサブシステムを提供し、各サブシステムの責任を定義し、サブシステム間の関係を組織化する規則とガイドラインを提供
- デザインパターン(Design Pattern):(1)ソフトウェアシステムのサブシステムやコンポーネント、あるいは(2)それらの関係を定義するためのスキーマを提供し、デザインパターンは特定の状況内で一般的な設計問題を解決し、通信するコンポーネント間の反復的に発生する構造を記述
- イディアム(Idiom):特定プログラミング言語に限定された下位レベルパターン(low-level pattern)イディアムは、与えられた言語の機能を使用してコンポーネントまたはコンポーネント間の関係の特定の側面を具現する方法を記述
アーキテクチャパターンの例としては、レイヤed Architecture[Posa1]、Hexagonal Architecture[Cockburn]、Onion Architecutre[Clean Architecture]、最近有名なMicro Service Architectureなどがあり、デザインパターンの例としては有名なGang of Fourがあるでしょう。 イディアムの例としては、Advanced C++ Programming Styles and Idioms[Coplien92]のように特定の言語とともに描写されます。