前提知識
UAFというアーキテクチャフレームワークがある。
もっとも抽象的な最上位の目的を定義する黄色のメタビュー(Missionビュー)があり、
それをStrategic~Resourceビューという抽象から具体までの各レイヤーで実現関係にあるかのトレーサビリティを取りながら、目的を達成するためのアーキテクチャを考える。
ここでは、Strategicビュー、Operationalビュー、Servicesビューという順であるが、
Strategicビュー、Servicesビュー、Operationalビュー、という順番に私は入れ替えている。
理由は、経営戦略、事業戦略指標やビジネスケイパビリティを考えるStrategicビュー
→ それを実現するサービス全体の設計をServicesビューで考える。
つまりサービス利用者目線というマクロな視点のServicesビューは次にあった方が、
目的と手段の階層関係になっており、トレーサビリティが取りやすいという実感があるからだ。
そしてその次にサービスを提供する業務側の一連のプロセスとして、
Operationalビューで業務活動の流れを時系列で表す。
ちなみに【-】とUAFのマトリクスで表示されている部分に関しては定義しなくていい部分である。
戦略であるStrategicビューで時系列的に、
「このケイパビリティを実行した後に、あのケイパビリティを~」みたいな順番は考えないからである。
またServicesで考えるサービスでは、内部でどんな業務活動の集合から成立しているか?という内容は関心の外である。
それらはOperationalのワークフロー(Operationalビューのシナリオ列)で考えることだ。
SLAとSLO
ここでちょっとSLAとSLOの2つに触れておきたい。理由は後で判明する。
この2つは似ているようで、実は意味が全く異なります。
SLA(Service Level Agreement)
日本語にすると「サービスレベル合意書」となります。
サービス利用者がサービスを利用する際に期待するサービスレベルであり、
これはサービス提供者とサービス利用者の間で、
どのような内容のサービスを、どのレベルの品質で提供するか?
を定量的にサービス開始前に双方で取り決めて明文化したものです。
現実性のある達成水準を定義し、それに違反した場合には罰金を払うなどして、
サービスを利用する側に対して損害の補償などをしなくてはならない。
SLO(Service Level Objective)
SLOはあくまでもSLAを満たせていることを保証するための「目標」なので、
サービスの提供者が設定するだけのもので、サービス利用者には見せなくてもいい。
SLAを満たすことを保証する目標値なので、SLA よりも高い(厳しい)数値が設定されます。
SLO は、守れなくても利用者に対してのペナルティはありません。
SLAとSLOの関係構造は、丁度以下のような関係性になっています。
まさにSLAが上位目的概念であり、それを実現する構造としてSLOがあると考えると非常に分かりやすいです。
事業戦略とサービスの関係
ビジネスケイパビリティを扱う事業戦略レイヤーでの話からすることにする。
まず戦略は1つ以上のケイパビリティの組み合わせから構成され、
ビジネスケイパビリティは、リードタイムが何時間以内などといった定量的な達成目標を持つ。
たとえば簡単な例として事業戦略の指標が
① サービスの稼働率:90%以上
② 1か月で合計サービス停止許容時間:3時間以内
またポリシーとして、
③ 戦略水準に違反した場合には、サービス利用料の5%以上を利用者に返金
という定義であったと仮定する。
サービスレベルは、この事業戦略を実現するサービス全体の定量指標であるため、
上記の達成基準を【すべて】満たしていなくてはならない。
①~③のどれか1つでも満たせていない状態では、実現関係に違反する。
これはまさにリスコフの置換原則の考え方そのものである。
上位概念の戦略指標をサービスレベルが全て満たせている場合のみ、利用者側に提供できるといえる。
リスコフの置換原則
ここでSOLID原則の1つである【リスコフの置換原則】を思い出してほしい。
インターフェイスや抽象クラスといった、
実装クラスに対する上位概念である目的を実装側で実現できている。
正常にポリモーフィズムが使えるようになっていることを保証するための原則である。
そのためには、上位概念の指標や持っているロジックの事前事後・不変条件をすべて満たせていなくてはならない。
これは事業戦略と、それを実現する事業戦術に当たるサービスの関係にも言えること。
上位の事業戦略の指標で、サービスの稼働率:90%以上
とうたっているにもかかわらず、実際には80%程度であるといった場合には、
その時点で実現関係にあるとは言えない。
リスコフを満たせているかのチェック
例として、
① サービスの稼働率:95%以上
② 1か月で合計サービス停止許容時間:2時間半以内
③ 戦略水準に違反した場合には、サービス利用料の10%を利用者に返金
これは上記の戦略指標を満たせており、サービスとして実現しているといえる。
しかしながら、
① サービスの稼働率:90%以上
② 1か月で合計サービス停止許容時間:3時間半以内
③ 戦略水準に違反した場合には、サービス利用料の3%を利用者に返金
これは①のみしか満たせておらず、サービスとして実現しているとは言えない。
なので、ボトムアップ式に戦略指標を現実的なものに訂正するか、
サービスレベルを上げられるようなアーキテクチャを考えなくてはならない。
各ビューの指標とSLA、SLOの関係
ここまででもうお気づきかとは思いますが、
事業戦略の補償すべき達成目標として、SLAの目標値
事業戦術であるサービスの達成目標として、SLOの目標値
と考えると、構造的に非常に分かりやすいと思います。
補足 -サービス1つに対するケイパビリティの個数-
複数のビジネスケイパビリティを1つのサービスで実現することがあり得ます。
これはまさに手段であるサービス1つに対して、目的のビジネスケイパビリティが複数の関係にあるインターフェイス分離原則の構造そのものです。
イテレーションサイクルでSLAの定義
自分は案件では、以下のような順番でそれぞれを定義しました。
これはあくまでも自分が要件定義セオリーを学びつつ、
案件の中で実際に実現性のあるプロセスとして思いついたものです。
この通りにやらないといけないといったものではないです。
MissionからStrategicへトップダウン
まず最初に
ケイパビリティよりもさらに上位にある目的Missionの達成目標を定義しないといけません。
でないと目的が超曖昧な状態で、アーキテクチャを考えることになります。
Missionを達成するためには、いくつかのケイパビリティを組み合わせて戦略を定義します。
この戦略無くして、戦術は語れません。
つまりDDDモデリングのコンテキストマップを正確には描くことができません。
その際にMissionの達成目標のために、各ケイパビリティはおおよそどの程度満たせていればいいか?を仮説ベースで定義します。
この時点で※【仮決めのSLA】(精密な指標ではないことに注意)を定義し、
もしもそのSLAによって最上位目的が達成できるかのチェックができるのであればしてしまいましょう。
検証ができなければSLOのレイヤー(UAFのServicesビュー)で検証すれば充分です。
Servicesビューで実現可能性をチェック
SLAの指標を満たす指標をうたっている既存のサービスを使ってMissionの実現可能性を検証します。
仮説検証アジャイルなどのように、最初の方での素早い検証をすることで、どんな価値を実現すればいいか?の探索を速やかに行いたい際などにもこの方法は向いていると感じます。
ここでポイントなのは、いつまでもStrategicビューで各ケイパビリティにどの程度の達成目標が必須なのかを考えるよりも、
さっさとServicesビューで検証してしまう
ことです。また同時に、
ここでMissionの達成できるかの実験をどんな既存のサービスを再利用したらいいか?
皆目見当つかないってことは、それだけまだ要件が曖昧過ぎるとも言えます。
なので速やかに手戻った方がいいです。
既存のサービスを可能な限り再利用して検証し、開発するのは最低限かゼロに努めましょう。
でないと無駄な開発コストがかかってしまいますし、
作りこんでしまっているほど、手戻ることを開発者たちが嫌がってしまいます。
その結果、そもそもの解くべき問いの設定を間違え、
使われないのにメンテコストはかかるサービスが出来上がってしまいます。
仮にもしも問いの設定が間違っていなくても、その問いの領域に対してあまりにも十分すぎるほどのソリューションを考えてしまうことにもなり得ます。
このあたりの詳しいお話は以下の記事をお読みください。
個人的には、既存の一時利用可能なサービスで実験することを薦めます。
ここでの検証のための投資コストをケチると、技術的負債を助長させる可能性が高まるため、ケチらずに一時利用し、最小限の開発に努めましょう。
その方がADRの運用や、コアドメインの品質を担保することに時間を割けます。
最初の検証サイクルでいきなりMissionの達成基準を超えられることは、余程リソースやコストが豊富でない限り不可能でしょう。
そこで以下の大きく2通りの分岐を考えておきます。
余裕で目標が達成できていたら
たとえばMissionが、
1日当たりのクリア達成走行距離が1000km
であるにもかかわらず、
検証の時点で、2000kmであったとしましょう。
この時点で十分すぎるほどに達成できているにもかかわらず、
「思ってたのと違う」というリアクションがあった場合には、
そもそもの問いの設定の仮説が違っていたことを証明してくれています。
「そうそうそう」というリアクションがあった場合、
問いの設定は合っていると言えますが、Missionの達成水準を調整してみましょう。
現状は仮決めで【達成走行距離が1000km】であるので、
たとえば1800km → 1600km とかっていうようにちょっとずつ落としてみましょう。
それによって必ず満たしてほしい下限値を探っていくのです。
というのも現状の数値では十分すぎるほどの解決策を考えてしまっており、
1000km分の余計な使わなくてもいいリソースがあり、無駄な浪費をしている状態なので、
どこを削れば必要十分でMisiionが達成できるかの落としどころを検証サイクルを回しながら探っていきましょう。
目標が達成できていなかったら
Missionの目標に到達できていない場合には、
・ビジネスケイパビリティの要素がそもそも足りないのか?
・それともビジネスケイパビリティの要素は揃っているけども、SLAの達成目標が低すぎるがゆえに、Missionが目標に到達できていないのか?
・あるいは、その両方なのか?
この3種類に集約されます。
素早く検証サイクルを回すことによって、そもそも最初に定義したMission目標は、
既存のサービスや自分たちの所有する設備やヒト系のリソースなどを使っても無理なのかの検証もすることができます。
このようにMissionからServicesビューまでの仮説検証サイクルを回すことで、
正しい問いの設定ができているかの検証
その問いに対して必要最低限のソリューションとして、
どのくらいのSLAや SLOが必要なのか?
をちょっとずつ精度を高めていくことができます。
これによって無駄な開発をすることなく、自分たちはコアドメインの開発運用だけに専念しやすくなり、サービスの達成目標も定量的な値を設定。
さらにそれを外部環境や内部環境の変化によって再定義することもしやすくなります。
interfaceの定義と同じような感じ
抽象概念であるinterfaceの定義を最初からガッツリやるのではなく、
最初は具象クラスで検証し、変更が入る度に徐々にinterface定義を明確にしていくのと同じような感じで、SLAの正確な値は後からボトムアップ式に定義するのが現実的である。