こんにちは。てぃろです。
今回は提供しているサービスで障害が発生した時に、どのように障害を是正していけばよいかということを考えます。
ここでいう「提供しているサービス」はSIで顧客に提供しているサービスも、自社で開発しているサービスも両方を含みます。
あくまでここでフォーカスしたいのは、このサービスを提供している主体として発生した障害に自分がどう関わっていけばよいのかということです。
障害是正するには、技術と組織の2つの視点を持つ
まず大前提として「障害は発生するもの」であるという認識を持つことが必要です。
どんなに完璧にサービスを開発したと思っても、人間は間違うものなので抜け漏れはどこかにあるものです。サービスを他人に使われるということは想定外の使われ方をする場合もあります。
だからこそ、ここ最近のシステム開発の主流になりつつある考え方は、カオスエンジニアリングで言われるようなシステムそのものに備わるレジリエンスだったり、予防的統制や発見的統制により事前の予防や早期発見による被害の最小化にあると思います。
これらはいずれも、アーキテクチャやクラウドサービスレベルを主とした技術的な対処と言えます。
ここで技術的に最小化した障害発生率をさらに小さくするために、組織的な対処もすることが必要と思います。
技術的な対処は別の言い方をすれば、プロダクトそのものの範囲における不確実性(リスク)を最小化する行為ですが、「提供しているサービス」とはプロダクトだけを指すものではなく、オペレーションを含みます。
つまり、「サービス = プロダクト + オペレーション」であるはずなのです。
ならば、オペレーションによる障害発生のリスクを抑え込まなければ、真に障害是正といえる障害発生率の最小化は実現できないと言えるのではないでしょうか。
ただし、私がここで言うオペレーションとは、人間が介在する行為すべてをオペレーションと言っています。それは開発作業、QAオペレーション、リリース後の運用まですべてです。つまり私がここで扱いたいオペレーションによる障害発生のリスクとは人間そのものの不確実性であり、言い換えれば人間はミスをする生き物であることを前提にどのようにオペレーションのリスクを減らすのかということです。
QAオペレーションの見直しで障害発生率を最小化したい
改めてオペレーションには何があるかを洗い出してみると、以下のようになると思います。
- 要件定義
- 各種設計
- 開発
- QA
- 運用
すごくざっくりではありますが、このような区分けで考えたときに一番力を入れて是正するべきはQAオペレーションであると思います。
要件定義や各種設計では、ほとんどの場合障害発生のリスクを検討することができません。明らかに仕様としておかしかったりしない限りはおおよそ夢を語っているところなので、具体的に動かしてみないとわからないよね、という段階です。
開発では、エンジニアなら経験があると思いますが、開発そのものに没頭することによって、自身では予期しないケースというのは往々にして見逃してしまうものです。ペアプログラミングやモブプログラミングをすることによって、他者の視点によるチェックで障害発生のリスクはやはり下げられますが限界があります。
運用まで行ってしまったら、もはや障害として流出している段階なのでここでの障害発生のリスクの低下を考えようとするのは難しく、できるとしたら障害発生後の迅速な対応のためのマニュアル作りや体制づくりになってくるでしょう。
障害の流出を防ぐにはやはりQAオペレーションが最重要であるというわけです。
では、具体的にどうするのか?というと、「異常系」と「デグレ」の2つの観点でのQAケースの強化をすることです。
当たり前ですが、設計はやりたいことを書きますし、開発でもそのやりたいことを実現するために作ります。いわゆる「正常系」です。ここのテストというのは開発中からずっと動作確認という名目で実施され続けているため、ほとんどそこにバグは含まれているようには見えないのです。
本当にバグが含まれているのは、正常系を作りこんだ時に見逃している部分であり、それは正常系のロジックの中で想定外のインプットが与えられたときの挙動として定義できる「異常系」がほとんどです。
さらに大規模で複雑なプロダクトであった場合には、従来からあるロジックが正常系も異常系もこれまで通りに動くかどうかをチェックする(= デグレを検知する)ことが必要になります。
障害は大抵、この2種類のQAが十分できていないことが原因だと私は思います。
異常系のケースは、実行前と実行後の状態をきちんと洗い出そう
より具体的に言えば、異常系のケースは以下の点に注意しましょう。
- あらゆるインプットのパターンを網羅しているか?
- 内部状態や、DBのデータによる挙動の変化はないか?
- 実行後の状態(内部状態やDBのデータ)は想定通りか?
- 例外を返却している部分は、適切にキャッチされているのか?(ユーザに見せるべき?ログに出すべき?など)
この中でも特に実行後の状態の定義が最も大事です。
これはメソッドの返り値だけの話ではなく、DBのデータや内部状態(ReactでいうとStateなど)のことです。QAケースで一番見逃されているチェック観点はこのあたりです。
だからこそ、そもそもそういった状態を作らないアプリケーションアーキテクチャが推奨されてきているとは思いますが、現実にはDBデータに依存したロジックなど山ほどあります。だからこそ、世間一般で推奨されているだけのアーキテクチャを自分たちの現場の考えに持ち込むべきではなく、現実を直視して愚直に何を確認するべきなのかを見極めなければならないのです。
また、こういったQAケースは膨大になることがありますが、その洗い出しをサボるから致命的な障害が発生する原因となってしまうのです。
ただし、たいていの場合すべてのケースを実行する必要はなく、理論的に実行対象のケースから排除できるものが多いですし、場合によってはリスクを鑑みてインプットとして受け付けないというバリデーションチェックを追加するなどの仕様変更で対処できることも多いからです。
それでもケースが膨大というなら、それはやるしかないでしょう。工数を確保するようにプロジェクトマネージャーと交渉します。リリース日をずらせないなら、そのリスクは報告した上でリリース後でもQAを実行するのがよいでしょう。一番最悪なのはなにもせずに障害を発生させてしまうことです。後からでも必ずQAはやるべきです。
デグレのケースは、QAケースを貯めていくことが重要
デグレを検知するには、当たり前ですが従来の動作を定義することが必要になります。
これはQAオペレーションがきちんと回っていれば、QAケースとして過去のQA実行履歴が残っているはずなのでそれを整理してためておくことがよいでしょう。
開発後のQAでは、蓄積されたQAケースの中から開発で影響を与えた機能を含むケースのみをピックアップして実行すればよいのです。最も理想的なのは、すべてのQAケースを実行することですが、人手でやっているうちはそんなことはできないので、ほんとうに実行することが必要なQAケースを見極めることが重要になるわけです。
E2Eテストなど、テスト自動化をうまく使うことも理想に近づく一手ではあると思うので、是非それも組わせてデグレ検知しやすいオペレーションを作っていくといいでしょう。以前の記事で一例を紹介しているのでよければそちらも参考にしてください。
最後に
今回は障害是正には、技術的対処と組織的対処があり、その中でもQAオペレーションの強化が必要であるという話をしました。
以前から、QAにはよく関わっていたので以下のような記事も書いていました。
改めて見返してみると、今いる現場も同じような状況になっているなというのがよくわかります。
あのときも10カ月ほどかかっていたので、今回もそこそこの時間は必要になってくるはずです。根気よく品質の重要性やそのチェックのための観点を伝えていく必要があるんだろうと思います。
つまり、障害是正は一度やれば終わりなのではないものであり、組織作りという面が非常に大きいものであると言えます。今の立場だからこそそれを痛感します。
QAオペレーションというHowをしっかりと考えながら、何をチェックしなければならないのか?というWhatについてより組織全体で考えられる文化を作っていかないといけないのです。