技術選定/アーキテクチャ設計で後悔しないためのガイドライン


## はじめに
本稿は、ソフトウェア開発を進める際に直面する様々な技術的な意思決定やライブラリ・フレームワーク・XaaS等を選択し正しく活用していくのかについての考え方をサポートすることを目的としています。「すべてにおいてこのようなワークフローを通じて検討すべきである」という主張ではありません。読者の抱える問題領域に応じて、必要な箇所を取捨選択するための１種の考え方を提供するものです。

## そもそもアーキテクチャ・技術選定に時間をかけるべきか
まず第一に伝えておきたいことは、技術選定やアーキテクチャ設計に常に慎重であるべきではないということです。ソフトウェアの規模やライフサイクルに応じて、そもそも時間をさく必要がないということも多くあります。書き捨てのシェルスクリプトにも読みやすいコードを求めて書くことは非常に重要ですが、だからといって組織だって議論・検討するようなものでもないのです。一方で、５年も１０年も拡張が続くことが十分に想定されている巨大なシステムであれば、必要に応じてアップデートがしやすいような設計を十分な時間をかけても価値があるでしょう。

ここで、バリーベームの「アーキテクティング：いつ、どれだけ？」[Making Software](https://amzn.to/3mSXbjK)を参考にそれらに対する定量的な調査を紹介しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/e1703d40-9b6d-ebb9-9c67-73262fdf1b28.png)


具体的な手法についての言及は割愛しますが、アーキテクチャとリスク解決に使った具体的な時間の割合をソースコード行数規模で一定のモデル化を行い比較したものです。1万行(実際には空行やコメントを除いた実行行数で１万行)程度のソフトウェアであれば、リスク解決に用いる時間の割合や手戻りなどはかなり小さいことがわかります。

一方で、1000万行に及ぶ巨大プロジェクトでは全体の半分近くの時間を設計の検討に費やしてもお釣りが来るというのがこのモデルから見てとれます。逆に言えばプロジェクトが巨大になればなるほど、アーキテクティングに費やすコストは大きくなってしまいます。

このことからもわかるように、私達がどの程度時間を割くべきかということについては対象となるソフトウェアやそれをつくる組織、解決したいビジネス課題などによって変化していくため、技術選定やアーキテクティングは熟練したエンジニアの職人芸的な要素が絡んできます。そして大まかな傾向があるにしても、たとえばプロダクトが市場に受け入れられるかわからないタイミングでの過剰な将来設計は無駄になりやすいですし、プロダクトマーケットフィットが確かめられたあとには、発展に向けた強烈なアーキテクチャが必要になっていきます。あるタイミングのサービス企業にとってモノリシックなWebアプリケーションフレームワークが蛇蝎のごとく嫌われ始めるのには、このようなフェーズの違いによる副作用といえます。

また、技術選定・技術的意思決定のもたらした副作用(あるいは時間とともに実装とドメイン/ビジネス知識の差分が生じた状態)のことを技術的負債と呼ぶのであれば、将来のどのタイミングでこの副作用を解決したらよいのか、どのようにすればその悪影響を限定的にできるのかを常に考えるプロセスや組織的アプローチのほうが重要であるとも考えています。間違った(かもしれない)意思決定があったとき、それ自体が責められるべきではなく、間違った意思決定を修正できないことのほうが問題なのです。

ですので本稿は技術的意思決定の副作用を認識したり、後悔したりすることを「失敗」とカッコつきで表現しますが、実のところ意思決定そのものに失敗や間違いはなく、その意思決定の後悔に伴う学びをいかに効率よく得るかということがエンジニアとしての技術選定の審美眼につながるのでしょう。

また、それらを修正するためには開発組織、ビジネス組織に一定の能力が求められます。アーキテクチャの再設計が必要なタイミングに、転換を実現する十分なリソースが存在しないのであれば、本当の失敗に向かってシステムが動くことになります。アーキテクチャの再設計とはこれまでの累積工数を短い工期で再構築する組織能力を必要とするのです。


##あなたの技術的モチベーションをどの程度考慮したほうがいいのか。
新しい技術やフレームワークを使ってみたいと思うエンジニアの気持ちは非常に重要です。自分が信じるところの美しさや審美眼を持って技術を選定していくことは、開発のモチベーションに繋がりますし、また功罪ありますがキャリア開発にも繋がります。新しくそしていずれ主流になるソリューションに早くから関わりコミュニティに参加していることで第一人者になったり、発表登壇などを通じて知名度が上がったりしていきます。

このような状況を多くの若手のエンジニアは見ていますから、エンジニアコミュニティの中で「イケてる」技術を使ってみたいというモチベーションは高くなりますし、そのようなバイアスがある中であっても正しい技術選定ができていると思い込んでしまうことも一度手痛い「失敗」をしない限り難しいでしょう。

実際のところ、新しいイケてる技術に飛び込んで、それを実ソリューションにいかせている人というのは内部実装も深く理解し、必要に応じて実アプリケーションの設計やコミュニティへのコントリビューションを通じて改善していくことにコミットしてきたことが評価されていることが多く、単に「使っているだけ」というわけではないのです。そこには多くの地雷を踏むことや自己解決の苦労があったはずです。

ですので、モチベーション高く意気揚々と技術的意思決定をし、そのなかで意思決定を後悔しないために重ねた苦労というのは、それはキャリア・スキル開発の両面で良いことなのだと思います。組織がある程度大きかったり、技術選定のリスクがそこまで大きくないのであれば技術的多様性を持つことで組織全体の課題解決力を高めるために、このようなモチベーションを重視した形での技術選定に対する姿勢は十分に合理的だと思います。

ところが、技術選定の副作用や認識し、「ツケを払う」ことになるのが技術選定をした本人も限らないというところがこの問題の厄介なところです。別プロジェクトへの移籍や退職、あるいはそーコードを書かない立場になったなど、様々な理由でそのつけを払うのが本人ではない誰かであるというのは肝に銘じておくべきです。このことは完全に自分でコントロールすることは難しいものですし、途中で自分自身がモチベーションを失うこともままあるからです。

まとめると、「失敗」というのは技術者にとって最大の福利厚生であるから、リスクを低く小さく失敗できるように、技術的な意思決定におけるリスク評価を正しくできるようにあるべきだし、その意思決定の経験を正しく学びに繋げられるようにすべきだというのがモチベーションをどの程度評価するべきかという問いの間接的な答えになります。

## 解くべき課題を明確にし、解決する。
### 課題をオニオンモデルで整理する。

ソフトウェアは課題を解決するためにあります。言語、設計、アーキテクチャやライブラリ・フレームワークの選定も何らかの問題解決のためにあります。そのため、技術的な意思決定にあたって、課題が何であるかを明確にするべきであるというのは当り前に聞こえるかもしれません。

しかし、しばしば問題よりも先に解決手段を選んでしまうということがあるのも事実です。解決手段のトップページに書いてあるウリ文句をそのまま自分たちの問題だと意図的ないし無意識的に誤認してしまうこともしばしばです。

そうならないために、まずソフトウェアをめぐる課題がどのようなレイヤリングを持って定義されているのかをイメージする必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/85f127f9-fca3-3aac-fac8-cc438cf71a3f.png)

これらは要求のオニオンモデルと言われます。社会、マーケット、ビジネス、業務、システム、ソフトウェアという階層があり、それぞれのレイヤから順次要求(とその源泉）が生まれてくるという様子を表したものです。まるで玉葱の皮を向くように中心部にいくにつれ具体的な問題になり、外側に行くにつれて抽象的な（解決方法の多数ある）ような問題になっていきます。

技術的な動向に関する話は、かならず背後に大きな社会的な課題や問題をはらんでいます。

たとえば、Nocode技術への注目が集まるのは、ソフトウェアエンジニアの供給に対して需要が大きく高まっているという社会的背景に関係しています。

たとえば、ある時期のReactなどは複雑になりがちなUI/Webフロント技術に対応できるエンジニアが不足している自社ないし社会の状況に対して、サーバーサイドWebのメンタルモデルに親しい状態での開発で複雑なSPAを実現することができ、フロントエンドエンジニアへの転向を進めました。

たとえば、Webアプリケーションサービスの高速な開発や仮説検証がビジネスにおいて重要だと考えられた時代にRuby on RailsなどのMVCフレームワークは勃興しました。

このように社会課題と技術選定の問題、ライブラリやフレームワークが登場した背景は切っても来れない関係があります。つまり、そのマクロなトレンドが大きく変わった/変わるだろうと考える場合は技術選択の問題にも影響があるということです。

以下にそれぞれの階層において、どのような観点で思考を巡らすのかのサンプルを提示します。

* 社会
 * ビジネス/企業のビジョンは社会にどうかかわり必要とされるのか。
 * 倫理的、法的な要請に背いていないか。背くようなリスクがないか。
 * コミュニティを通じた支援が期待できるか。
 * 社会を通じた採用・調達にとってどれだけ期待できるか。
 * 政治・環境・経済動向・技術革新などのなかでどのような関連する潮流があるか。
 * フレームワーク：PEST分析など
* 顧客
 * 顧客にとってのコアな価値とはなにか。
 * 顧客の利益、価値、フェアネスに対して問題のある方法ではないか。
 * 顧客のニーズの変化、マーケットの変化に対して対応できる手法か。
 * フレームワーク：3C分析、4P分析など
* 企業
 * なぜ利益が生まれるビジネスなのか。
 * ビジネス上不利益、利益相反、競合になるリスクがないか。
 * ビジネス上のKPIや成功要因を阻害しないか。
 * 今後の事業の発展、縮小にとってブレーキ要因にならないか。
 * 今後の事業の横展開、ピボットに対してブレーキ要因にならないか。
 * フレームワーク：ビジネスモデル可視化、ビジネス環境分析
* 業務
 * 自社のオペレーションはどうなっているのか。
 * 業務負担、運用負担のかかるものではないか。
 * 現状、および将来の業務にフィットしているか。
 * 将来の業務改善をスムースに行うことができるか。
 * フレームワーク：ビジネスプロセスの記述、BPR、イベントストーミング
* システム
 * 上位の要求に対して、情報システム・プロダクトサービスはどのような特性を備えるべきか。
 * それを実現する組織や開発体制・運用体制はどのようなものか。
 * 開発者の採用、育成、調達はどのように実現するか。
 * ソフトウェア上の意思決定をどのように伝承・伝達していくか。
 * フレームワーク；品質特性マトリクス、可変性分析、アーキテクチャ適応度のシナリオ分析
* ソフトウェア
 * 上位の要求に対して、ソフトウェアはどのような品質特性を具体的に持つべきなのか。
 * それらを実現するために開発者はどのような設計にするか
 * フレームワーク：CRC分析、デザイン・アーキテクチャパターン、プロトタイピング

このような社会から自社組織、ソフトウェアの問題に至るまでの観点をゼロから考え直すことは非常に時間がかかります。もちろんすべてを考えておく必要はありません。

これらの観点は、「その意思決定が継続して影響を与え続ける範囲・期間」の長さによってウェイトを持って考える必要があります。より影響範囲の時間と空間が広い場合は、より円の外側(社会)について考える必要があり、より影響範囲が狭い場合には円の内側だけを考えるようになります。

これはプライベート変数や関数のレキシカル変数命名よりも、パブリック関数や公開APIのインタフェースなどに時間をかけて検討することと本質的には同じことです。より影響範囲が狭い場合には、必要に応じて別のものに交換することができますが、影響範囲が広い場合には交換がしにくくなります。

言い換えれば、影響範囲が広く、交換可能性が低い部分を限定的にする手法がアーキテクチャパターンだと言えます。ですので、技術的意思決定で後悔しないためにはその影響範囲の時間と空間を自体を小さくしていくことで、意思決定のスピードと「失敗」した場合の交換をしやすくするという方法をまず第一には考えるべきでしょう。

## ライブラリとフレームワークの違いに気をつける
ソフトウェアの技術要素の中で、「ライブラリ」と「フレームワーク」という言葉があります。どちらの頻繁に技術選択の場面で用いられる言葉です。いずれの言葉も区別せずに利用されることもしばしばですが、ここでは明確な違い持って理解しておくと議論がしやすくなります。

ライブラリは、「あなたのアプリケーション」の一部に組み込まれる「あなたのコード”が”呼び出す」して機能を果たすものです。

それに対して、フレームワークは、「あなたのアプリケーション」の一部に組み込まれて、「あなたのコード”を”呼び出す」ものです。一般にフレームワークは、あなたのコードに特定のインタフェースを持つことを強制することで、ある種のアプリケーションを簡単・高速・安全に作成することを手助けします。当然、フレームワークは最終的にはあなたのアプリケーションとして、あなたのコードから呼び出されることがありますので、ライブラリとしても機能していることも多くあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/269bb593-b985-3433-8b6a-d316b37b6362.png)


この定義はかならずしも一般的なコンセンサスがあるものと言い切れません。しかし、議論の上では、このように区別すると会話が成り立ちやすくなります。一般にフレームワークのほうが長期のライフサイクルでの意思決定になりますが、ライブラリは交換可能性が高い事が多いのです。たとえば、より高速なJSON Parserライブラリが出たという際に、交換が非常に難しくなるということは少ないでしょう。

一方、フレームワークの交換可能性は、呼び出される自分たちのコードが増えるにつれて交換しにくくなっていきます。たとえば、CakePHPで記述されたソフトウェアをLaravelに移植するのは簡単ではありません。これは高速なアプリケーション開発のツケのともいえます。

このようなフレームワークの持つ依存関係における粘着性/スティッキネスの高さを理解しておくとよいでしょう。たとえば、特定のフレームワークの利用は100kSLoCに到達する前に分解あるいは、別サービスとしての構築を検討するなどのアーキテクチャ上の観点を持つことで高速な新規立ち上げと発展後の交換困難性の課題を小さくすることの両立が望めるかもしれません。

## ペースレイヤリングという考え方。
このような設計上の「変わりやすさ」と「変わりにくさ」に注目して、それを建築の分野に取り入れたのが全地球カタログでも有名なスチュアートブランドでした。

彼は、「How Buildings Learn」の中で、ペースレイヤリングと呼ばれる概念を創出しました。それは建物の変化と時の流れがどのような関係を持つかを示したものです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/b0f22258-11c6-a2aa-90bb-7d9c5f755d3a.png)

図は５つの階層が建物の変化には存在していて、変化のスピードがそれぞれ異なるということを示したものです。

用地（Site）は、建物よりも長く永遠に近い期間持続するもの。そしてのその上に建物(Structure)が建てられて、数十年から数百年は持続する。外装(Skin)は10年程度で、リフォームされ、その中にあるキッチンやエアコンなどの設備は5,6年で老朽化していきます。どんな風に部屋を使うか(Space Plan)は1年や2年は同じだけど、日用品 (Stuff)は毎週変わったりします。

ここで重要なのは、依存は常に「変わりにくいもの」に対してのみ行われるということです。「変わりやすいもの」に「変わりにくいもの」が依存するようになると、全て丸ごと交換する必要が出てきます。

たとえば、部屋の中であれば、インテリアや日用品のラインナップと同じ周期で引っ越したり、建物を立て替えるような人はいません。でも、床色やインテリアに合わせて、日用品を選ぶことはあります。

不動産屋さんに言わせると、他の不満はなんとかできるけど、立地の不満だけはなんともできないことが多いから、まずは立地から決めていくことが多いそうです。これも一種のペースレイヤリングです。

ペースレイヤリングという考え方は、建築だけでなく、Webシステムにおける情報アーキテクチャやUXの5Sへと転用されていくことになります。

ソフトウェアにおけるペースレイヤリングとして有名なのは、ガートナーのSoR/SoE/SoIの議論です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/76282c15-45fd-89da-6290-7c26fa7ec89d.png)


システムの変動性に合わせて:

+ SoR( System Of Record　 )
+ SoE( System Of Engagement )
+ SoI( System Of Innovation )

という三階層に分割でき、それぞれが異なる開発サイクルを持つという発想です。ペースレイヤリングという観点をアーキテクチャに持ち込むのは非常に重要な論点だと思っています。むしろ、ペースレイヤリングの重要性が導かれるのは、その抽象性と依存という関係からです。

ソフトウェアの設計原則に、抽象依存の原則(ADP:Abstraction Dependency Principle )というものがあります。依存するならば、より抽象的なものに依存しろという原則です。

また、もう一つ重要な原則に、安定依存の原則(SDP:Stable Dependency Principle )というものがあります。依存するならば、安定しているものに依存しろという原則です。

たとえば、配列をソートする関数があったとします。このとき、利用する側は、ソートするという目的を果たせればいいので、ソートアルゴリズムはそこまで気にしません。より、抽象的なものに依存してコードを書くようにすれば、ソートのアルゴリズムが変わっても利用側のコードを変える必要はありません。

このように、より抽象的(より目的に近い）コードに依存し、より具体的（手段に近い）コードを交換可能にしておくことで、ソフトウェアは変化に強く設計できるようになります。逆に、特定の手段を変更するときに引っ張られて、広い範囲に影響してしまうと修正にたくさんの時間をようすることになります。

これは、抽象的な目的の方が変化しにくく、具体的な手段の方が変化しやすいという性質から導かれているのです。これは、クリーンアーキテクチャやオニオンアーキテクチャと呼ばれる階層型のアーキテクチャが生まれた機序と同じものです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/b04997f2-4d88-5470-d15d-69f8ec23330b.png)

これらはビジネスの不確実性の波をフーリエ変換するようなものです。周波数成分(変更される頻度)で分解し、それぞれに依存関係を設ける

## ステークホルダーインタビューとPoint of View
さてこのように広い範囲の課題整理をして、アーキテクチャ上の意思決定を行うとなると自分ひとりの発想や考えだけでは難しいことはあたりまえです。

もし、先述の通り、この意思決定は大きな影響があるなと考えるのであれば開発チームだけではなく様々な業務上のステークホルダーに対してインタビューをすることが適切でしょう。

しかし、いきなり「アーキテクチャを考えたいんですがインタビューしてもいいですか？」と言われても、ソフトウェアエンジニアではないステークホルダーたちと適切な議論を交わすことは不可能です(できても頓珍漢なことになりがち)。

そのため、ステークホルダーで聞くべきインタビュー内容を事前に整理しておくことが望ましいです。しかも、できる限り我田引水にならないように項目が恣意的にならないように注意が必要です。(たとえば、「高速で安全にUIを表示できるとうれしいですか？」のような質問をしない)

+ 現在の業務の目的はなんですか？定量的な指標をいくつか教えて下さい。
+ 具体的にはどのようなアクションをしてそれらを達成しますか？
+ 業務の目的の達成のためにボトルネックになることはなんですか？
+ 現在の業務内容が大きく変化するとしたらどんなケースが考えられますか？
+ 上記の目的の観点でITシステムに期待することはなんですか？

たとえば、システムを利用する業務担当者に対してヒアリングするのであれば、上記のような業務に関わる目的から順番に聞いていくのもよいかもしれません。オープンクエスチョンすぎる形でインタビューをすると、現状のさまざまな不満や課題に目を取られてしまい、部署のミッションとの合目的性が取れないPoint of Viewを得てしまいがちになります。そうするとインタビューの結果が局所最適な内容になってしまい、議論があらぬ方向にいってしまいます。

そこから、ステークホルダーにとっての観点をつぎのような文法でまとめていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/d13900fc-44d5-1afd-9b4c-525a0a389901.png)

このようなステークホルダーの要望や必要な観点をまとめていき、整理していきます。こうすることで、どのような機能要望や観点が存在するのかを把握することができます。

## リスク(不確実性)・ストーミング
リスクストーミングとは、プロジェクトやシステムのリスクに関するブレインストーミングです。ステークホルダーインタビューで出てきたような観点に関して、そこからずれるような変化やリスクが起こる可能性/不確実性について議論し、見落としてしまいがちな観点を出していきます。。

たとえば、今は会計監査の対象となるようなシステムではないが、今後そのあたりの修正を入れることがおこるかもしれないとか。

たとえば、現在は消費税率が固定でシステムを組んでいるが、商材の設計によっては一部の消費税率が変わるかもしれないとか。

たとえば、現在のリードエンジニアが退職してしまい、別のメンバーだけで改善保守シなくてはならなくなったら。

そういったソフトウェアシステムを開発していく上で、どこかのライフサイクルで起きるかもしれないような出来事です。

ブレーンストーミングは、様々なアイデアを幅広く集めるために行われる議論の方法です。アイデア出しの際には一切の「批判の禁止」です。自由奔放でオープンな場で「質より量」というルールに沿って行われます。

通常、リスクや不確実性について触れるのは、「自分がネガティブだと思われる」ということから避ける傾向があります。特に心理的安全性の低い組織ではその様になりがちです。また、リスクとは言わず、「発生するかもしれない方針の変化」についてもステークホルダーから吸い上げることができるとアーキテクチャ設計についての理解を深めることができます。

ここで発見されたリスクについて、一覧表にしてまとめ、発生確率(頻度や蓋然性)とアーキテクチャへの影響度にマッピングしておくとよいでしょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/37822020-8cae-a417-99dc-bb564e7e30dc.png)

プロジェクトリスクについて、こちらを参照してリスクドライバーの種類やイメージを固めておくと、アイデアが出やすいと思っています。

[ITプロジェクトのリスク予防への実践的アプローチ](https://www.ipa.go.jp/files/000026834.pdf)


### システムとソフトウェアライフサイクル
要求のオニオンモデルでは、「業務」の内側に「システム」という概念を持っています。ここでは、「システム」とは**「ソフトウェア」と「それを修正・保守する組織をあわせた概念**のことであると定義されています。

これはソフトウェアのライフサイクル全体を考えた上で、要求の解釈やデザインするときに考えるべき枠組みです。

ソフトウェアは、誰か一人で作っていることは稀で、チームや組織、外部パートナーとの連携をおこないながら開発をしていることが多いと思います。その際に、ある部分についての修正や機能追加について：

+ 誰が
+ なんのために
+ どのぐらい
+ どこを
+ 変更する

のかというのが明確でないときに、アーキテクチャや技術選択によって、自分たちが解決すべき問題があやふやになってしまうことがしばしばあります。

たとえば、自社のオウンドメディアを開発しているとします。コアなアーキテクチャ部分はソフトウェアエンジニアが開発して、実際の運用の多くはHTML コーディングのできるデザイナー/Webライターのスタッフが実施していくことが想定されていたとします。

このときに、ソフトウェアエンジニアのコアアーキテクチャで解きたい課題とコンテンツ運用の部分で解きたい課題は異なります。スキルセットも常識も違うわけです。どちらも同じライブラリを用いたときの業務への影響が変わってきます。

同じ開発者の中でも、MLにつよい、UI/UXに強い、バックエンドのRDBMSに強い、クラウド運用に強い、フロントエンドアーキテクチャに強いなど特徴が変わってきます。ですが、「誰がどうやって修正するのか/するようになるのか」が整理されていると、選ぶべき技術も鮮明になっていきますし、大きな間違いも少なくなるでしょう。

### 学習コスト/習熟コスト
筆者は個人的には「学習コスト」という言葉があまり好きではありません。新しい技術を学んだり体得したりするのは、基本的には投資であってコストではないわけですし、その技術的な意思決定によって、課題解決ができるのであれば、そちらを選ぶべきだと考えています。

しかし、その学習の成果が短期間しか価値がないのものであった場合にはどうでしょうか。あるいはあまりに難しくて年単位の時間がかかってしまう場合はどうでしょうか。あるいは、その習熟がまるでその人のキャリアプランを無視したものであるなども考える必要があるでしょう。

自分たちのチームだけの効率であれば、学習コストを一定程度無視して投資として新しいことに挑戦することは非常に価値のあることです。一方で、名前も知らない誰かの業務を縛ってしまう可能性があるとしたらどうでしょうか。もしかしたら、そのときに足りないのはステークホルダーへの理解と共感なのかもしれません。

## 品質特性/副特性のトレードオフスライダーを作る
システムとしての要求が見えてきたら、次はソフトウェア設計としての要求に解像度を上げていきましょう。そのために、まずはこれまでの議論を技術選定上の品質特性について考えを巡らせてみましょう。 JIS X 0129-1で定義された品質特性とその副特性についてご紹介します。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/ac81ad96-48bc-1906-2d9f-53db88c9398b.png)

これらの品質特性の中から、今回の意思決定に重要だと思われる項目をピックアップしていきましょう。具体的な特性の定義については参考文献を参照してください。

これらを議論の土台として、「トレードオフスライダー」を作っていきます。トレードオフとは、「何かを立てれば何かが立たない」という両立が難しい物事に対して使われます。「トレードオフスライダー」とは何を重視して、何を重視しないのかの調整つまみのことです。

「トレードオフスライダー」はプロジェクト憲章やインセプションデッキの一部として定義されることが多いです。チームやプロジェクトとして意思決定の基準を揃えていくことで「なぜ」そのような意思決定がされたのかを可視化して、理解・納得しやすくすることでプロジェクト運営をスムースに行うことができます。

たとえば、以下にアーキテクチャ品質特性のトレードオフスライダーのサンプルを用意しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35671/ad5b65b5-f227-01cf-5492-c3aa64e530df.png)
このプロジェクトのある技術選定においては、パフォーマンス要件があまりきびしいわけではないが、モジュール化して独立した変更がしやすい手法が求められている一方、他の環境への移植や習熟コストのようなものはあまり考慮しなくても良いということが記述されています。

## プロトタイピング/概念検証
ある技術的意思決定を行う際に、机上の空論になってしまうことが最も問題です。複数の選択肢やアプローチがあるのであれば、実際に動作するプログラムを書いてみることがもっとも検証として有効なケースがあります。

プロトタイピングを行う際に注意すべき点は、検証項目が表面的な「フレームワークの使い方」に終止してしまい、現実の問題解決とは離れた部分での検証ばかりをしてしまわないようにするという点です。プロトタイピングの目的は、問題解決に利用した際に発生しそうなリスクについて網羅的・実践的に露わにすることです。そのためには、実際に用いる場合の実システムの複雑な部分に向き合って検証していく必要があります。きれいで複雑でないサンプルケースの問題だけを説いても、リスクは暴露されません。せっかくプロトタイピングをしたのであれば、実業務を行うユーザーや開発者にも触れて貰う必要があるでしょう。

そして、さらに注意すべき点はプロトタイピング時のソースコードを基本的には破棄することです。プロトタイピングは、課題の洗い出し、リスクの暴露が目的なので、そのまま実運用に耐えるコードである必要はないのですが、しばしばプロトタイプをそのまま拡張して本番のシステムにしてしまいがちです。このような点にも注意しましょう。

## アーキテクチャディシジョンレコードをつける
軽量なテキストベースのテンプレートを利用して、アーキテクチャ上の意思決定・設計判断を記録します。そのときの意思決定に至った流れが明記され、時系列でわかることであとから追試・学習へと活かすことができます。

gitリポジトリ上に記録するようなさまざまなツールが開発されており、それらを用いて過去の経緯も含めたコンテクストが理解できる。
https://github.com/npryce/adr-tools


```markdown:ADRの典型的なテンプレート

# タイトル
アーキテクチャ意思決定のタイトル
## コンテキスト
いつ、どのような課題・どのような背景でそのような決断を行ったのかがわかるような文章。
## 内容
実際の意思決定の内容
## ステータス
下書き、提案済み、承認済み、非推奨
## 結果
ステークホルダーへの影響など
プラスの影響 /マイナスの影響など
```
## まとめ
技術選定/アーキテクチャ設計における意思決定は、非常に難しく僕自身も多くの後悔をしてきました。最も大事なのは、そのような「失敗」をリカバリーできる体制やチーム、組織を作り上げることです。そのためには、その時考えたことや予測をしっかりと文書化し残していくことが大事になります。担当者が変わってしまったり、ツケを払うのが別の人物である可能性も十分考慮して、誠実な意思決定が行われていれば将来のチームメイトに対しての後悔は少なくなるはずです。


## 参考文献
* [思想としてのペースレイヤリング](https://ekrits.jp/2015/03/403/)
+ [Design It! ―プログラマーのためのアーキテクティング入門](https://amzn.to/3p1xK03)
+ [システム及びソフトウェア品質の見える化、確保及び向上のためのガイド](https://www.meti.go.jp/policy/it_policy/softseibi/metrics/product_metrics.pdf)
+ [アーキテクチャ中心設計手法 (IT Architects’Archive ソフトウェア開発の実践)](https://amzn.to/2LCet6Z)
+ [要求工学知識体系(REBOK)概説](https://www.ipa.go.jp/files/000005375.pdf)
+ [Making Software ―エビデンスが変えるソフトウェア開発](https://amzn.to/3oI9JL4)
+ [ITプロジェクトのリスク予防への実践的アプローチ](https://www.ipa.go.jp/files/000026834.pdf)


## あわせて読みたい
+ [なぜ、組織のつくりとソフトウェアアーキテクチャは似てしまうのか](https://qiita.com/hirokidaichi/items/d12fcce80ee593bcf34d)
+ [エンジニアリングマネージャ/プロダクトマネージャのための知識体系と読書ガイド](https://qiita.com/hirokidaichi/items/95678bb1cef32629c317)
+ [スケールする要求を支える仕様の「意図」と「直交性」](https://qiita.com/hirokidaichi/items/61ad129eae43771d0fc3)