10Xにおけるアーキテクチャ特性の定義

アーキテクチャ特性の導入と手応え - 10X Product Blog」の記事を補完する内容です。

10Xにおける「アーキテクチャ特性」という概念に対する解釈を定義しています。

これは元々社内向けに書かれたドキュメントでした。社内ドキュメントをそのまま転記する形で記載しています。

概念の出自は「ソフトウェアアーキテクチャの基礎」です。

ここでの内容が、アーキテクチャ特性への理解の足がかりになれれば幸いです。

アーキテクチャ特性とは

アーキテクチャ特性とは、「ソフトウェアが成功するために備わっておくべき性質」のことです。 ここでのソフトウェアの成功とは、期待通りに振る舞うことを指します。

具体的には、

  1. プログラムの実行開始から、期待時間までに処理が完了すること
  2. 処理データ量が増えても、期待時間までに処理が完了すること
  3. 途中でエラーが起きても、継続して処理が続くこと

解決したい課題とその手続き処理とは別で、期待する振る舞いを実現するために、ソフトウェアに要求する性質をアーキテクチャ特性と呼びます。

具体例の1と2は時間に対する制約ですが、観点が異なります。

1はプログラム自体の”パフォーマンス”というアーキテクチャ特性が求められている。

2は処理するデータに対する”スケーラビリティ”というアーキテクチャ特性が求められている。

同じ時間制約でも観点が異なれば要求されるアーキテクチャ特性も変わります

3は何らかの失敗に対する耐性という性質で、広くは”耐障害性”、狭くは”堅牢性””信頼性” “安全性”といったアーキテクチャ特性になります。

広くや狭くと表現するのは、アーキテクチャ特性自体が全て同じ抽象度で括られるわけではなく、それぞれが依存していたり、包含関係にあったりするからです。

これを複合的なアーキテクチャ特性と呼びます。

巷でもよく聞く、ソフトウェアの市場への投入速度を示す “俊敏性 (アジリティ)” というのは、複合的なアーキテクチャ特性の代表例です。

俊敏性を獲得するためには”デプロイ容易性”, ”テスト容易性”, ”保守性” などが必要になります。

アーキテクチャ特性の必要性は状況や文脈によって変わるので、常に全てが要求されるわけではありません。何らかのSaaSを導入することでデプロイ容易性が担保されるなら、ソフトウェア開発では残り2つにだけ集中すれば良くなる場合もあります。

ソフトウェアの機能的側面 (ex: 特定のデータをデータベースに取り込むことができる) とは別で、ソフトウェアの性質的側面 (ex: 特定のデータが不正であってもスキップして後続処理を続ける = 堅牢性) に注目し、その性質を定義したものがアーキテクチャ特性です。

なぜアーキテクチャ特性が必要なのか

アーキテクチャ特性を明確に定義して考慮する理由は、ソフトウェアを成功させるためです。

ソフトウェアの成功は以下3つの要素が揃うことを指します。(前述も参照)

  • 必要とする要件が備わっているか
  • 必要とする性質が備わっているか
  • 上記2つが揃って期待通りに振る舞うか

この内、”必要とする要件が備わっているか”は認識しやすく、考慮が不足することは稀です。 対して、”必要とする性質が備わっているか”は認識しづらく、考慮が不足しやすいです。

この不足しやすい特徴である ”必要な性質の認識しづらさ” という課題を深ぼってみると、開発者同士でも注視する観点が異なっていたり、使う言葉の定義がズレていることが、問題の根本原因であることがわかってきました。(10X社内ヒアリング結果)

この根本原因を解消することで性質考慮の不足を減らし、ソフトウェアの成功確度を上げたいという狙いから、10Xとしてのアーキテクチャ特性の定義と活用方針の策定を決めました。

備えるべきアーキテクチャ特性とは

備えるべきアーキテクチャ特性

ソフトウェアが備えるべきアーキテクチャ特性は、3つの基準で判断できます。

※ 1と2は観点が異なり、3は1と2どちらにも共通している観点です。

  1. 設計に対する考慮事項が要求仕様として明らかなもの
  2. 設計の構造的側面に影響を与えるもの
  3. ソフトウェアの成功に不可欠 or 重要なもの

1. 設計に対する考慮事項が要求仕様として明らかなもの (明示的)

プロダクトマネージャーやデザイナー、BizDevといった開発者以外の(場合によっては開発者も含む)メンバーが関わって定める、仕様要求として明らかなアーキテクチャ特性があります。

店舗が増えて品数が増えたとしても売り場への表示速度は変えない。 (= ユーザビリティ)

店舗が増えて品数が増えたとしてもデータ取り込みは3時間以内に完了する。 (= パフォーマンス or スケーラビリティ)

こういった要求は仕様書に書かれていたり、開発者以外の人でもソフトウェアの成功可否がわかるものであるため、明示的な基準と呼びます。

2. 設計の構造的な側面に影響を与えるもの (暗黙的)

開発者の目線で、要求がソフトウェアの設計構造に影響を与えると判断できるものも、備えるべきアーキテクチャ特性です。

安全性は常に求められるアーキテクチャ特性ですが、決済機能を実装する場合は特に意識して高く求められる特性になります。それは通信時のデータの暗号化や取引履歴の扱い、決済の確定処理で要求される確実性など。

これらの要求が設計に影響を与えるかどうかは開発者がシステムをどのように作り上げるかを検討しなければ把握できません。

ソフトウェアの今ある構造 (or これから作り上げる構造) を正しく認識できるのは開発者だけです。システム設計への影響が仕様書に書かれていることはなく、開発者以外のメンバーが検討しずらい領域の場合がほとんどです。よってこれを暗黙的な基準と呼びます。

3. ソフトウェアの成功に不可欠 or 重要なもの

ソフトウェアは多くのアーキテクチャ特性をサポートすることが(やろうと思えば)できますが、その中でも成功に影響を及ぼす外せない性質に限って達成することを目指します。

なぜなら、全てのアーキテクチャ特性を満たそうとすればするほど、設計自体が複雑になり、実装コストや運用コストが上がる可能性があるからです。

成功に影響を及ぼす重要な品質特性に集中して、それを満たすような構造を目指します。

備えるべきアーキテクチャ特性であるかどうかは、2つの問いに答えて判断しましょう。 ケースは2つあります。

ケース1.

  • 設計に対する考慮事項が要求仕様として明らかなものか? ⇒ Yes.
  • ソフトウェアの成功に不可欠 or 重要なものか? ⇒ Yes.

2つにYesである場合、それは備えるべきアーキテクチャ特性であると言えます。

ケース2.

  • 設計の構造的な側面に影響を与えるものか? ⇒ Yes.
  • ソフトウェアの成功に不可欠 or 重要なものか? ⇒ Yes.

2つにYesである場合、それは備えるべきアーキテクチャ特性であると言えます。

この判断基準と考え方で備えるべきアーキテクチャ特性を判断していきます。

アーキテクチャ特性の見極め

アーキテクチャ特性の見極め

備えるべきアーキテクチャ特性の判断基準をもとに、具体的に何を備えていくかを見極めていきます。この見極めは感覚的に行うのではなく、推奨される3つの観点があり、合理的に判断します。

備えるべきアーキテクチャ特性を見極める観点

  1. ドメイン特性 (ドメイン由来)
  2. 明示特性 (要件由来)
  3. 暗黙特性 (システム由来)

ドメイン特性 (ドメイン由来)

アーキテクチャ特性は変更追加を行う先のドメインによって決まる場合があります。これがドメイン特性です。ドメイン特性はドメインの特徴として求められる特性のことです。

注文管理というスタッフさんが扱うドメインでは可用性, 完全性, 信頼性が求められます。お客様の注文を扱うので業務中は常にアクセスできる状態でなければならず、情報に誤りがなく常に正しい情報に触れられる状態でなければいけません。

この様に、注文管理ドメインを扱う時点で要求される特性があります。

明示特性 (要件由来)

仕様の中の要件として要求される場合があります。これが明示特性です。 明示特性はプロダクトマネージャーやデザイナーの方といったエンジニア以外のロールの方でも認識可能なレベルで求められる特性でもあります。

お客様の注文操作の動線に関わる箇所はサービス体験の大通りであり、ユーザービリティとアクセシビリティを厳しく要求します。それは1秒単位の待ちであったり、ダイアログの一言一句の文言の決め事まで正確に定めなければいけません。また表示の速度も速くなければ気持ちよさを実現できないのでパフォーマンスも要求します。

この様に、お客様の体験ベースなどからプロダクトマネージャーが仕様書に記載するくらい明らかに定められる特性があります。

暗黙特性 (システム由来)

DesignDocの策定時に要求される仕様に応える構造を決めることや、既存のシステム構造由来で明らかになる場合があります。これが暗黙特性です。 暗黙特性はプロダクトマネージャーやデザイナーの方はそれに気づき言及することができません。システムを真に理解するソフトウェアエンジニアのみが気づくことができます。ゆえに”暗黙”なのです。

決済に関わる変更である場合、必然的に完全性や安全性が実装コードでも要求されます。決済で不整合や情報漏洩は商売上あってはならないからです。

この様に、システム設計や実装コード由来で明らかになる特性があります。

見極める際の注意点

見つかったアーキテクチャ特性の全てに応えない

アーキテクチャ特性を考え始めると、多くの特性をサポートした方がより良い機能や体験が実現できそうだと思いがちですが、それは罠です。全ての特性に応えようとしてはいけません。

様々なアーキテクチャ特性を応えようとするとソフトウェアの複雑性が上がってしまうという、トレードオフの関係にあります。この関係は厳密ではないため、必ず複雑性が上がる保証はないですが、可能性は大いにあります。

このことを踏まえると、無闇に特性を取りに行くのではなく、最低限守りたい3つを選んで満たしに行くのが良いと一般的には言われています。

アーキテクチャ特性が多く見つかってしまい、実装に迷いが生まれてしまう場合は、守りたい3つを満たすことに集中することに立ち返って考えてみてください。

いつアーキテクチャ特性を考慮するのか

アーキテクチャ特性は、機能開発の初期段階から検討を始めます

具体的にはプロダクトマネージャーが仕様書を書くタイミング、デザイナーがUI/UXを検討するタイミング、エンジニアがDesignDocを書くタイミング。

それぞれのタイミングで特性の必要性に気づくことができ、機能開発が始まる前に関わるメンバー間で守りたい要件として共通認識と合意が取れるようになるのが理想です。

あくまで理想なので、必ずできなければいけないわけではありません。

最低でもDesignDocには守りたい要件として記載され、どう特性を満たすのかまでが定義できているようにしたいです。必要に応じて検討を判断してください。 例えば、決済やポイントに関わる箇所などでは考慮すること強く推奨します。

どのようにアーキテクチャ特性を考慮するのか

アーキテクチャ特性の考慮

アーキテクチャ特性は、共通の言葉と理解を持ち、認識を共有することで考慮していきます

何よりもまずアーキテクチャ特性という言葉に慣れ、その言葉の定義と概念を理解し、同じ感覚で議論できる状態になる必要があります。そうなるために存在するのがこのドキュメントです。

ここで定義された内容を理解し、「この仕様はアーキテクチャ特性を考えられているか?」「守りたいアーキテクチャ特性が何か教えてほしい」といった感じに、日常的な議論で使われる状態になりましょう。最初は違和感を感じるかもしれませんが、慣れれば大丈夫です。

慣れてくると唐突に「可用性」「スケーラビリティ」といった言葉が出ても、反射的に ”今は特性に対して言及しているな” と話の論点を自然と掴めるようになります。

慣れることで自然と考慮ができるケースもありますが、それだけだと個人の力量に頼りすぎてしまいます。現状の開発の進め方をもとに考えると先の ”いつアーキテクチャ特性を考慮するのか” でも触れたように、仕様書, DesignDocといったドキュメンテーションのステップで考慮することを推奨します。加えてProof of Conceptsという検証プロセスでも考慮できるため、併せて紹介します。

アーキテクチャ特性を考慮するステップ

  • 仕様書の策定
  • DesignDocの策定
  • Proof of Conceptsによる検証

仕様書の策定

仕様書はユーザーストーリーベースで書かれており、このユーザーストーリーの中で必要とされるアーキテクチャ特性が明らかになる場合があります。

例えば、新しい決済手段を追加する場合に、追加に伴って新たな個人認証が必要になったとすると、そこでは必然的に安全性が求められるようになります。また、その体験が全体の8割以上のお客様に影響を及ぼす変更である場合、ユーザビリティも併せて考慮しなければ利用率の低下にも繋がりかねないもので、事業インパクトの観点からも必ず守ってほしいという制約になるかもしれません。

この様に、仕様書で仕様を決めるタイミングで明らかにすることで、次に行われるDesignDocの策定で考慮されたシステム設計を依頼することに繋がります。

DesignDocの策定

仕様書をもとに、システムに加える変更追加を青写真として定義する中で、システム観点で必要とされるアーキテクチャ特性が明らかになる場合があります。

仕様書策定時に定められたアーキテクチャ特性を守りつつ、システム構成の観点で守らなければいけないと感じる特性を見つけましょう。

例えば、要求をシステムで答えようとすると可用性を一定犠牲にしても良いが回復性は確実に担保して実現したいという構造になるかもしれません。その時点で回復性の担保を織り込んだシステム設計にすることで、得たい成果を確実に得られることとDesignDoc時点で証明し、成果品質を引き上げます。

Proof of Concepts (Prototyping) による検証

仕様書やDesignDocの策定よりも不確実性が高い課題に対応する場合に、Proof of Conceptsという検証ステップを挟む場合があります。言い換えるとプロトタイプ開発ですが、この検証を行う過程でアーキテクチャ特性が得られそうかも確認できます。得たいアーキテクチャ特性を先に定めて、それが得られるかどうかをPoCを通じて確認するという流れです。

この時、PoCは捨てる前提のものではなく限りなく本番実装に近い形で検証してアーキテクチャ特性担保の確実性を見極める様にしましょう。捨てる前提にすると、後々になって「やはり担保できない」という出戻りが発生する可能性が生まれるからです。

アーキテクチャ特性のトレードオフ

アーキテクチャ特性にはトレードオフの関係を持つものがあります。

この特性のトレードオフという関係性を理解することは非常に重要です。 なぜなら、トレードオフを理解しなければアーキテクチャ特性の効力を発揮するドメインで、正しい意思決定ができないからです。

アーキテクチャ特性に関わる意思決定の大半はソフトウェア価値の最大化に影響を及ぼします。 そこで正しい意思決定ができないというのは、価値最大化の機会を失うことを意味します。

例えば、ユーザビリティ改善で変更を加えることと、可用性を保ち続けることはトレードオフになり得ます。それはユーザービリティは実験的に変更を加え続けることでより良い状態を目指すのに対し、可用性は障害可能性を伴う変更に対して消極的な態度を取るからです。

この特性の共存は意思決定のジレンマ(板挟み)を生みます。変更を加えて価値を最大化させたい方向と、なるべく変更を加えず可用性を取りたい方向とで、向かう方向がアライン(整列)しません。 それは変更というリスク/リターンを伴う行為に対する、価値基準がそれぞれ異なるからです。

こうなるとソフトウェア価値を拡大すること、 つまり正しい意思決定をし続けることが双方にとって難しくなります。結果として硬直状態になり、双方アクションが取りずらい状況に。

このジレンマを避けるためにも、変更に対する責任範囲と影響範囲を限定し、相反する2つのアーキテクチャ特性を持つ領域が健全に共存できる(= それぞれが独立性を持つ)プロダクトにしていくことで、ソフトウェア価値の最大化を目指し続けられる組織構造とプロダクト構造、即ちアーキテクチャを策定する必要があります。

これがアーキテクチャ特性のトレードオフを理解するべき最たる理由です。 (※ もちろんこれ以外にも理由はありますが、組織とプロダクトへの影響という角度では最もな例)

つまりは、組織構造やプロダクト構造 (アーキテクチャ) の策定といった大きな影響範囲を持つ意思決定に関わる人ほど、アーキテクチャ特性を理解し、ドメインに存在する特性を認識し、その中のトレードオフを踏まえた上で、正しい意思決定をすることに努めなければいけないということです。

この理解はリソースが限られた中で高い価値を証明し、非連続な成長をし続けなければいけないソフトウェアスタートアップにおいては、特に重要なものです。なぜなら、急激な成長によって要求される特性が変わることに追従し続けなければいけないからです。

もちろん、そうではない既に巨大なソフトウェアプロダクトを扱うTech企業でも同じであることに変わりありません。

アーキテクチャ特性 カタログ

アーキテクチャ特性の具体をカタログとしてまとめました。

ここまでの文章の中でも既に可用性パフォーマンスといったアーキテクチャ特性が登場してきていますが、以下では厳密にそれら特性の定義を行なっています。

このカタログを参考にしながら、仕様書やDesignDocの作成時にソフトウェアに必要な性質を考慮し、合理的な仕様定義とアプリケーション構造の策定を進めてください。

ここで定義された特性は10X社内の会話には高頻度に登場します。 これ以外にも世間的に使われている定義があれば、それを採用してもらっても構いません。

また、特性の定義は真理に近い正解を追求した内容ではなく、”自分達が信じられる概念を定義したもの”です。人によっては矛盾に感じるものや、定義自体を改めたいものがあるかもしれません。その場合は、遠慮なくフィードバックをいただきたいです。

もし定義に疑問を持ったり、特性自体の理解を深めたい場合は、ソフトウェアエンジニアのメンバーに質問してください。全員が全てを理解しているわけではありませんが、一定理解の手助けになる考えを述べられるかと思います。

Stailerのドメインに現れるアーキテクチャ特性

★ アクセシビリティ (Accessibility)

定義

ユーザーの状態や能力、取り巻く状況によらず、同じようにプロダクトを利用できる性質。

通信状況が悪くても、ITリテラシーが低くても、期待状態に障害なく到達できる場合、それはアクセシビリティが高いと言える。

★ ユーザビリティ (Usability)

定義

ユーザーが特定の状況下で目的を果たすにあたって、機能を効果的で効率的に、満足できるように使える性質。

効率的で効果的に、満足いく水準でプロダクトを利用できている場合、それはユーザビリティが高いと言える。

★ パフォーマンス (Performance)

定義

マシン性能を基に機能の利用頻度やデータ容量によって決まる、システムを効果的で効率的に、満足できるように使える性質。

効率的で効果的に、満足いく水準でシステムを扱えている場合、それはパフォーマンスが高いと言える。

★ スケーラビリティ (Scalability)

定義

規模や数量が拡増しても変化適応し、期待通りに動作できる性質。

システムのトラフィックが増加しても、体験水準が変わらずに動作し続ける場合、それはスケーラビリティがあると言える。

組織規模が大きくなり、人が増えた場合でも、スループットが低下せずに高い水準のアウトカムが出続ける場合、それはスケーラビリティがあると言える。

★ 可用性 (Availability)

定義

システムが障害で停止されることがない、または期待通りの振る舞いや状態であり続ける性質。

長い期間、システムが期待通りの状態で振る舞い続けている場合、それは可用性があると言える。

★ 信頼性 (Reliability)

定義

システムが要求された機能を安定して果たすことができ、期待成果を生み出し続ける性質。

システムが機能を提供できていたとしても、それが期待成果を生み出していない場合、それは信頼性があるとは言えない。

システムに変更が加わるたびに機能が不安定になる場合、それは信頼性があるとは言えない。

★ 耐障害性 (Fault tolerance)

定義

障害が発生しても期待通りに稼働、もしくは振る舞いを続けられる性質。

障害が発生することを想定して、発生したとしても正常状態を維持し続けられる場合、それは耐障害性があると言える。

障害を未然に防ぐのではなく、想定範囲外の障害が発生したとしても、別の代替手段を用いるなどして、正常状態を維持し続ける仕組みを設ける。 (一般的にフェイルオーバーと呼ぶ)

そして障害発生に素早く気づくことができ、想定範囲内で障害を収束させることができる仕組みを用意するのが、耐障害性を持つということ。

★ 回復性 (Resilience)

定義

障害発生時に素早く正常状態に復旧できる性質。

障害を検知し、素早く障害を収束させ、正常状態に戻せる場合、それは回復性があると言える。

障害に対して代替手段を用いて正常状態を維持し続けるのではなく(これは耐障害性)、障害発生後から復旧までをいかに素早く対処できるかということ。

★ 安全性 (Safety)

定義

システムで利用するデータに対して、外部からの不正侵入によるデータの閲覧、データの改ざん、データの漏洩などの脅威から守られている性質。

不正侵入を防ぐ対策が施され、データの漏洩が起き得ない仕組みが敷かれている場合、それは安全性があると言える。

★ 完全性 (Completeness)

定義

データが期待通りに正確な状態で揃っている性質。

システムAで認識しているデータと、システムBで認識しているデータに差異がなく、かつ期待通りの状態である場合、それは完全性があると言える。

★ 堅牢性 (Robustness)

定義

プログラムに予期せぬデータがきても期待通りに振る舞うこと、またはプログラム自体に変更が加わっても不具合が混入しづらい構造で、処理やデータの誤りが起こりづらい性質。

プログラムで想定される振る舞い範囲と想定されない振る舞い範囲への線引きが明確で、正常系、異常系の単体テストが備わっており、振る舞いを正確で網羅的に想定できている場合、それは堅牢性があると言える。


以上が、アーキテクチャ特性の概念を定義した10X社内のドキュメント内容です。

参考資料