どこまでアプリケーションを「完璧」にすべきか

こんにちは。 エキサイト株式会社の三浦です。

アプリケーションを作るときや改修するとき、すべてのエンジニアが「完璧なアプリケーションを作ろう」と一度は思うはずです。

しかし、シンプルなコードで済むアプリケーションならともかく、複雑になればなるほど「完璧」を達成するのは難しくなっていきます。

今回は、どこまで「完璧」を目指すべきか、持論を語っていきたいと思います。 なおこちら、あくまで持論であり、必ずしも会社の方針と100%一致するとは限らないので、あらかじめご了承下さい。

完璧なアプリケーションとは

まず最初に、「完璧なアプリケーション」とは何でしょうか? それはもちろん、「いついかなる時も問題が起きない」アプリケーションです。

例えば、「2つの値を渡すとその合計値を返す」というアプリケーションの場合、正の数・負の数・非整数でも計算が可能であるとか、(仕様次第ですが)IntegerやLong値の限界を超えても問題なく動作する、などが「完璧」の条件として挙げられます。

この程度であれば問題ありませんが、ではWebサイトであればどうでしょうか? 考えられる条件としては、

  1. サイトにアクセスすれば、必ず想定通りの情報がサイトに載っている
  2. いつサイトにアクセスしても、一定以下の時間でページが表示される

でしょうか。 一見条件も少なく、簡単に達成できるような気もしてきますが、Webサイトというのは様々な状況下に陥ることが多々あります。 例えば、

  • 急に大量のアクセスが来る
  • 外部からの攻撃を受ける
  • ごく限られた条件下でしか起きない、コード内の潜在的なバグが発火する
  • 運用上のミス等で、DBなどのデータソース内のデータに不整合が生じる
  • インフラ周りに物理的な障害が発生する
  • クラウドを使用している場合、クラウド側に問題が発生する

などが挙げられるでしょう。 これら(もちろんここで挙げていないその他様々な原因も)をすべて解決し、「完璧なアプリケーション」を作り上げることは可能なのでしょうか?

「完璧」でなく「ベストエフォート」なアプリケーションを作る

個人的には、これら全てを完全に解決することはかなり難しいと考えています。

もちろん、例えば「急に大量のアクセスが来る」の対処法として「サーバ/コンテナが自動スケールするようにする」ですとか、「外部からの攻撃を受ける」の対処法として「セキュリティ対策を万全にする」など様々な解決策はありますが、それでも自動スケールが完了するまでの数分間はページ速度の急激な低下、もしくはタイムアウトはどうしても発生してしまうでしょうし、外部からの攻撃も新しい種類のものが出てきてしまえばまた新しく対処法を考える必要が出てきます。

さらに言えば、例えばごく限られた条件でしか起きない問題に対してどこまで対応するべきでしょうか? 1年に1~2回、しかも1回あたり数秒程度しか起きない問題に対して、何日も何週間もかけて原因調査・対応をするべきなのでしょうか?

私もしばらくこういった問題に頭を悩ませてきましたが、他のエンジニアと相談したり、色々と考えた結果、「完璧」ではなく「ベストエフォート」こそ目指すべきアプリケーションなのではないか、と考えるようになりました。

アプリケーション、及びそれらの上で展開されるサービスには、もちろん譲れない点があります。 例えば、「1日6時間はエラーでサイトが見られない」などといったサービスは、いくらなんでも受け入れられないでしょう。 可能な限り、いつでも見られるようにする必要はあります。

しかし、例えば「年間で99.9%の時間のサイトの動作は保証する(0.1%の時間はエラーでサイトが見られない可能性がある)」だとしたらどうでしょう? この程度であれば許容範囲、というサービスならあるのではないでしょうか? なおこれは、1年 = 365日 = 8760時間の0.1%なので、8.7時間ほどエラーが許容される、ということになります。

考えてみると、そもそもインターネットという仕組みそのものがベストエフォートという考え方で作られています。 今回の例であるWebサイトでいえば、その上で作られているアプリケーションがベストエフォートを目指すのは、ある意味自然なのかもしれません。

また有名なAWSも、サービスレベルアグリーメントという形で、「完璧」ではなく「ベストエフォート」でサービスを作っていることを宣言しています。

もちろん、サービスの内容によってどこまで許容されるかは変わってきます。 ニュースメディアサイトと医療用のオンライン手術サービスのようなものであれば、許容されるエラーのレベルは全く違うことでしょう。

ただしなんにせよ、やみくもに「完璧」なアプリケーションを作ることを考えるのではなく、まずはそのサービスでどこまでエラーが許容されるかを考えるべき、というのはすべてのアプリケーションに共通しているのではないでしょうか。 そして、許容されるエラーレベルに対して、適切に「ベストエフォート」なアプリケーションを作っていくことが、開発速度と開発精度の両方を兼ね備えた開発方法なのかもしれません。

最後に

AWSのように非常に大きく、インフラそのものをサービスとして提供するサービスであれば、最初から「~~%までの正常動作は保証する」というように宣言をしています。 一方で、いわゆる一般的なサービス・アプリケーションであれば、暗黙的に「まれに障害が発生することもある」という認識はありつつも、どこまでエラーが許容されるかという話し合いをすることは少ないのではないでしょうか? 特に自社開発であれば、その傾向は大きなものとなるでしょう。

ですがエラーや障害というのは、そのサービスが大きくなればなるほどいつか必ず起きるものとなっていきます。 例え自社開発のサービスであっても、一度はエラー許容レベルに関して話し合って決めることで、開発速度と精度のバランスを取ることができ、長期的に見てサービスの開発に良い影響を与えるのではないでしょうか。