COCOAの開発から、無関係な一個人が大いに学んだこと

8 min read読了の目安(約7900字

COCOAの開発とは全く無関係な一個人が、一連の状況を伝聞で聞く中で勉強になったポイントを記載します。
まず、個人の見解として、COCOAの開発は単純なアプリ開発と比較すると難しい要素がいくつかあったという事が前提にあり、携わっている関係各所に敬意を表します。
一方で、"後から気付いてしまえば"改善できたポイントは確実にあると実感しています。これは、携わった人たちが能力的に劣っていた/取り組みの精神に問題があったという事では決してなくて、実際にやってみてわかったノウハウということです。
この改善できたポイントは、普通の開発でも考える必要のあることだと思い、私自身も勉強になったポイントとしてまとめました。要約については「まとめ」の節を確認ください。

参考:
COCOA騒動メモ

前提:バグは必ず存在する

開発の大前提として、バグは必ず存在する。まず、これを認める事が大事だなと思いました。
ある程度のテストをして、リリースをしても、十分に実環境でのテストを繰り返さない限りは、想定外のバグは必ず発生する。
その前提で考えると、バグがあった時にどうやってそれをハンドルしていくか、という事をリリース後も考えることが重要になります。
※COCOAのように、開発からリリースまで十分な時間がない状況であれば、特に致命的なバグが存在していてもおかしくないという事だと思います。

運用ステージでバグを捕まえるサービス全体設計

本来、開発ステージ(リリースをしていない状態)でどうやってバグを捕まえるか、という事の検討が第一にあってしかるべきと思います。しかし、COCOAの場合は原理的に開発ステージでバグを捕まえる事が難しかった(可能性がある)ように感じました。また一般論として、開発ステージでどんなに頑張ったとしても、そこでバグを捕まえられなかった時に運用で気づけなかったとすると、脆弱なアプリになってしまいます。
このような観点で考えると、致命的なバグに関しては、万一開発をスルーしたとしても必ず運用で早期に気付いて対策をできるというサービス全体の設計が重要になります。例えば、セキュリティホールがあるという事自体はあってはならない事ですが、一方で一般的なOSやブラウザなどでは当たり前のようにセキュリティホールが報告されています。これは、リリースをしてからセキュリティホールが見つかったという事なので、理想論的にはあってはならないことです。しかし現実の人間が関わる事としては、どうしてもそのようなバグ/考慮漏れが存在します。

そうすると、致命的なバグの発生を前提としたサービス全体の設計を開発当初から念頭に置く必要があります。

派手なバグと静かなバグ・静かなバグの監視

これは今回の事に限らずですが、バグの一般論として、派手なバグと静かなバグがあると思っています。

派手なバグとは、事象が発生すると利用者が操作を進められないなど、明らかに操作的に支障のあるバグです。このようなバグは、利用者が直接確認できるため、トラブルがあると利用者から報告が上がります。

静かなバグとは、利用者に対して深刻な影響があるものの、操作には支障がなく、認知することが難しい種類のバグです。Androidにおいて通知が機能していなかったというのは、この静かなバグであると考えます。

派手なバグは、システムを利用できないという意味で当然あってはならないバグですが、しかし発見や再現が比較的易しく、その意味で対応しやすいという特性があります。
一方の静かなバグは、利用者が直接気付くことは困難です。このようなバグについては、様々なデータを見守ってチェックするなどして存在を認知する必要があります。一方で、何らかの観点で致命的なダメージを負わせるようなバグについては、ほとんどの場合においてそのダメージの指標となるデータが直接/間接的に存在する事にも注意します。というのは、ある種のデータに現れるような無視できない影響があるからこそ、致命的と言えるからです。
(例えば今回の場合においては、もし通知数を実測できていたとすれば、Androidの通知数がゼロというのは重要な指標でした。)

先程の前提に戻ると、静かなバグの存在を前提としたサービス全体の設計が必要になります。
つまり、派手なバグへの対応は当然として、仮に利用者の操作上の影響が無かったとしても、データが本来意図されたように蓄積されているかどうかを監視するという静かなバグへの対応も、サービス設計に盛り込んでおく必要があるということです。

自動化するかどうかは必ずしも関係ない

この監視については、必ずしもシステム化/自動化しないといけないかというと、そうでもないと思います。つまり、サービスをローンチした直後などでシステム開発リソースが不足している場合は、人間が運用して対応するという事も十分に考えられます。
重要なのは、サービスの設計に静かなバグの運用における確認が盛り込まれているという事であって、それが必ずしもシステムである必要はないと思っています。ただし、多くの場合は自動化した方が工数を削減できるので、システム化した方がよいとは思いますが。

リリースをトリガーにした監視・A/Bリリース

今回のAndroidの通知に関しては、9月のリリースによって動作しなくなったという因果関係がありました。このリリースをいきなり全体に対して行うのではなくて、部分的にリリースを行うことにして、その間の統計情報を比較することによってアプリの正常動作を担保してから全体にリリースを行う、という事も考えられました。
(ただし、今回の場合の統計情報の取得に関する難しさについては後述します)

匿名性を守ろうとした結果、という解釈

ところで、通常のアプリであれば、そのアプリの根幹機能が動作している/していないという事については、まず確実に観測していると思います。では、COCOAではなぜそれを行えなかったのか?
その一つの要因としては、匿名性を担保しようとした結果、という事があると思います。つまり、例えばある端末が通知を受け取ったという事を、仮に本人の情報を全く含めずに通知を受け取ったというシグナルだけサーバーに送信したとしても、そのIPは経路を秘匿化しない限りはサーバー側で判別ができます。
そうすると、サーバー側で悪さをした場合には、どの個人が通知を受け取ったか?という事をそれなりに特定できてしまう可能性があります。つまり、今回のようなセンシティブな物事を取り扱う限りでは、ただ通信が発生するというだけの事であっても、それがセキュリティ的に問題になる可能性があるという事でした。
ただでさえ国のアプリという事で情報についてセンシティブな中で、国ないし国の委託した業者の集計サーバーに状況を通知するという事になると、悪用を指摘する声も出てくると思います。
そのような批判への対応、あるいは国として守るべき事を守ろうとすると、単純に情報を取ることも難しかったという想像ができます。
これが、静かなバグの監視を難しくする一つの要因であったということでした。では、どう対策できたのか?という事は後述します。

"特殊な環境"または"開発者と異なる環境"でしか再現できないバグをどうやって認知して捕まえるか

バグが静かであっても派手であっても、特殊な環境でしか再現しないという場合があります。ここでいう「特殊」という言葉の意味は色々と考えられるので、総じて「開発者と異なる環境」としておきます。
「開発者とは異なるが普通の環境がいくらでもあるだろ」という指摘の声も聞こえそうです。それは確かにその通りですが、一般の開発リソースというのは有限であるため、開発者の環境にも当然ですが限りがあります。その限りがある中で、それを超えた環境で発生したバグをどう捕まえるか、という事がこの節で考えたいことです。

さて、COCOAの場合でいうと、そもそも本番のAPIは一般開発者では触ることができないなどの制約がありました。また、仮に本番のAPIを触る場合でも、正確なテストをするにはそれなりの手順・時間が必要でした。
そのような点を踏まえて、今回の場合は、単純な静かなバグの監視とは別に、以下の3点がサービス全体の設計として必要だったと考えます。

  • 本番で正確なテストを行うための手順と十分な時間の確保
  • 開発者が自主的に検証を行えるテスト環境・開発環境の確保
  • 明示的な利用許諾を得た利用者については、よりセンシティブな情報についても送受信できるような枠組みの確立

本番で正確なテストを行うための手順と十分な時間の確保

言うまでもない事かもしれませんが、サービスを設計する時点で、本番で正確なテストを行うための手順の確保が必要であったかと思います。例えば、保健所との情報の照合が必要であれば、テストに関してのみ保健所と情報を照合するスキームを設けるなど。
(これが実際に法的に可能かどうかなどはわかっていませんが、要はそのようなレベルも含めてサービスのレイヤーで検討をする必要があった、という事でした。)

開発者が自主的に検証を行えるテスト環境・開発環境の確保

リリースをしてからの本番環境でのテストは必要ですが、一方で、本番以外の環境(準本番・テスト環境)において開発者が主体的にテストを行えるようにしておく、という事も重要です。
例えば、上述のような「テストに関してのみ保健所と情報を照合するスキーム」を検討する場合には、同等の事ができる環境を準本番環境として用意しておくという選択肢もあります。実際の仕組みとしては本番のAPIを叩く事になるのかもしれませんが、開発作業として完了する前に、開発者が本番と同等の環境で確認ができるスキームをサービス設計時点で作る・作ることを想定する事が本質的であると思います。
これは、"特殊な環境"を出来る限り無くすという事でもあり、開発者をより巻き込んで主体的に開発が行えるようにする(いわゆるDeveloper eXperienceの向上)という事でもあります。

明示的な利用許諾を得た利用者については、よりセンシティブな情報についても送受信できるような枠組みの確立

開発・運用サイドでどこまで体制を確立したとしても、結局のところ実際の本番環境とは差が出る可能性があります。そうすると、匿名性を担保する必要のあるアプリにおいても、一定の情報を収集する事が改善のために不可欠になってきます。
サービス設計のレベルで対応できることとしては、例えば以下のような事があるかなと思います。

(1) ローカルには常にあらゆるログを残しておいて、何かあった時に許諾を得て発信する
(2) ログを外部のクラウドサービス等に保管しておいて、何かあった時にやはりこれを許諾を得て発信する
(3) 利用開始時に許諾を得て、通常のアプリよりもログを細かく通知する(IPなど、追いかけると個人特定に繋がる情報も、通常より多く送信する)
(4) アプリとは別枠で、利用しているOSと通知を受けた事がある・無いということの利用調査を取る(例えば、この調査でAndroidだけ低く出れば、AndroidとiOSで差があったということ)

実際にどこまでが実現可能か?という事はプライバシーポリシー等の問題もあって非常に難しいと思いますが、それも含めてサービスの設計に織り込む必要があった、というのが私の思ったことでした。

まとめ

これまでの私の学びをまとめると、以下の通りです。

  • 前提として、バグは必ず存在する(=継続的改善を前提とする)
  • 運用ステージでバグを捕まえるサービス全体設計が必要になる
  • 静かなバグを監視するサービス設計を行う
    • 必ずしも自動化が前提ではなく、サービスのレイヤーで監視を考える
    • 必要に応じてA/Bリリースやクローズドリリースなども検討する
    • 利用者の求めに応じて匿名性を守った上でも、監視に必要な情報を取得するスキームを考える
  • 開発者と異なる環境をできる限りなくしつつ、異なる環境が存在する前提でバグを捕まえるサービス設計を行う
    • 本番で正確なテストを行うための手順と十分な時間を確保する
    • 開発者が自主的に検証を行えるテスト環境・開発環境を確保する
    • 明示的な利用許諾を得た利用者については、よりセンシティブな情報についても送受信できるような枠組みを確立する

この事を、プロジェクト/プロダクトのオーナーとしても、開発担当者としても、念頭に置いた上で開発をする事が大事なのだな、という事を改めて実感しました。
改めて見ると、すごく当たり前のことを書いているかもしれません。しかし、私が実際に同じ立場であったとき、これらの事についてミスなく物事を進められたかというと、同様の失敗をした可能性も十二分にあると感じます。今回の事を他山の石として、自分の携わるサービスの改善に努めようと思いました。

なお、これらの事をさらに一言で言おうとすると、サービスの運用において、継続的改善を前提とした設計をする必要があるという事になると思います。
これは以下の記事において平井大臣のコメントとして紹介されている内容と整合的であると思いました。

記事(itmedia): https://www.itmedia.co.jp/news/articles/2102/12/news142.html

では一体、今回得た教訓は何だろうか。平井大臣はアプリのアップデートという発注に国が不慣れだった点を指摘する。「これまではお金を出して終わりだったが、これ(アプリ)は常に関与し続けないといけない。永久に完成しないものに国は今まで付き合ったことがない。今までの国のシステムの発注とは違う種類だった」と振り返り、「今後はわれわれ(デジタル庁)できっちり見る」としている。

このコメントだけを見るとやはり"当たり前感"がありますが、言うは易く行うは難し、当たり前の事であるだけに難しい部分もあるのかなと思いました。

補遺

平井大臣のコメント「そんなに難しいアプリではない」という言葉ですが、私個人としては2つのニュアンスがあると思っています。
一つは、身内の失敗を世間に説明するにあたって、身内を下げた発言の仕方であるということ。外部であるところの世間に説明をするにあたって、「自分たちのやっていたことは難しいことだった」というのは、事実として正しかったかもしれませんが、その言葉を言い訳としか受け止められない人も多くいます。大臣として発信をするという事は、多様な人に対して一つのメッセージを発信するということであって、その多様な人の中には開発に対して理解がある人もいれば、そうでない人もいます。「そうでない人に対してこそ、開発が難しいという事を説明するべきなのではないか」という意見もあってしかるべきとは思いますが、その説明が長くなればなるほど、「そんなの言い訳だ」と受け止める人もいます。そのような文脈で察すると、身内を下げた表現をする事は、必ずしも直ちに現実や認識を反映しているものでもないと思います。(本音と建前に近いところですよね、良いか悪いかという事は別にして)
そのような謙虚さを持っての発言として受け止めた方がよいのかな、という事を感じました。ワールドスタンダードではない、と言われればそうなのかもしれませんが…

もう一つは、"気付いてしまえば"対応が不可能ではなかったということ。例えば、オリンピックにおいて体操の選手の繰り出す様々な技というのは鍛錬の賜物であって、極限まで鍛え抜いたごく一部の人間にしか為せないものであると考えます。一方、今回の失敗はそのような意味での難しさはなく、一側面を"素人的に"捉える限りでは、もっと違った取り組み方であればこのような問題を起こさずに取り組めていたのではないか、という想像をすることができます。これが、上述の謙虚さ・そんなに難しくないと断じることの要因になっているのかな、とも思います。

ただ、その"気付いてしまえば"というのはとても大事なことで、コロンブスがアメリカを"発見"したことを他の人が過小評価した際に言い返した「コロンブスの卵」という逸話があるように、気付くか否かというところには大きな差があります。(一般)相対性理論は、今でこそ世界各地の多くの大学で当たり前に教えられていますが、発表された当時ではまともに理解している人は3人しかいないと言われていました。これは過去と現在で人間が本質的に違うという事ではなくて、人類の蓄積した気付きを共有した結果、(少なくとも3人よりも)多くの人が一般相対性理論という突飛で難解な発想を理解出来るようになった、ということです。

今後、我々はこのような"気づかなければ難しいかもしれない"事を、軽々と乗り越えていく必要があります。「そんなに難しいアプリではない」という言葉は、そのための発奮材料でもあります。今回起こった事を軽視する、あるいは過小評価するという事ではなくて、「軽々と乗り越えるべき壁」として心の中に位置づけるための言葉としても解釈できるという事です。
「これからDXを進めていく中で、こんなところで挫けてどうする」
そういう気持ちの言葉として受け止めた上で、一方で今回明らかになった様々な難しさについては、きちんと理解をしてそれぞれの立場で取り入れる。
それが建設的なあり方なんじゃないかな、ということを思いました。

いまDXという言葉を使いましたが、今回の学びは2つのDXが繋がると巷で言われている事を象徴しているようにも思いました。つまり、サービス設計に継続的な開発を行うことを前提として盛り込み、Developer eXperienceを向上させるような仕組みにしておくことで、Digital transformationが成立するということです。後者のDXを成立させるためには、前者のDXが必要なのですね。
コンウェイの法則を意識すると、このようなサービス設計を目指す上での組織や業務のあり方についても考える必要があります。平井大臣の「今までの国のシステムの発注とは違う種類だった」というコメントは、この観点においても示唆的ですね。

今回のことを学びとして活かして、がんばりましょう!

※「開発者が自主的に検証を行えるテスト環境・開発環境の確保」の部分に関しては、参考記事のこのコメントを受けて付け加えました。ありがとうございました。