はじめに

2017年もあっという間でしたね!この記事はGoodpatch Advent Calendar 2017 – Qiitaの18日目です。

モバイルアプリケーションの仕様やデザインを決めていくうえで、エラーにどう対処するかは、PMやデザイナーから見落とされがちです。エンジニア視点でも、どう対処すべきか迷いながらコードを書くことは多いのではないでしょうか。

この記事では、モバイルアプリケーションをつくる際に、どのようなエラーが発生しうるのか、それらにどう対処すべきなのか、全体像が俯瞰できるようにエラーを分類しながら、私個人の考えをまとめます。
Swiftのエラー4分類(参考:Swiftのエラー4分類が素晴らしすぎるのでみんなに知ってほしい – Qiita)はすばらしいのですが、これでもまだどれに分類されるのか判断が難しいと感じたので、よりわかりやすい分類を試みてみました。

エラーが発生する場所で分類する

多くのモバイルアプリケーションは、スマートフォンの中だけで完結していません。サーバーとAPIでデータをやりとりすることで成り立っています。したがって、エラーは発生場所で以下の3つに分類できます。

アプリ側のエラー

例えば以下のようなケースがあります。

  • アプリ側のコードにバグがあった(仕様としては想定していたのに、コードが対応できていなかった)
  • 仕様に抜け漏れがあり、コードが対応できていなかった
  • ユーザーの入力値が、アプリが想定しているものと異なっていた

アプリとサーバーのやりとりに関するエラー

APIでアプリとサーバーでやりとりするときに発生するエラーです。以下の3種類があります。

  • ネットワークエラー
  • 機内モードになっていて通信できない
  • 電波状況がわるく通信がタイムアウトする
  • リクエストエラー
  • リクエストパラメータ(取得するデータの件数や並び順など、アプリ側から指定できるもの)が、サーバー側の想定と異なっていて対応できない
  • アプリ側が要求するリソースが、サーバー側で見つからない
  • 認証が必要なのに、未認証の状態でリクエストしている
  • レスポンスエラー
  • レスポンスのデータ形式が、アプリ側が想定しているものと異なっていて、解釈できない


リクエストエラーは、HTTPステータスコードの400番台で、より細かく定義されています。

サーバー側・インフラ側のエラー

例えば以下のようなケースがあります。

  • サーバー側のコードにバグがあった(仕様としては想定していたのに、コードが対応できていなかった)
  • 仕様に抜け漏れがあり、コードが対応できていなかった
  • インフラのトラブル

サーバー側のエラーは、HTTPステータスコードの500番台で、より細かく定義されています。

エラーにどう対処するかで分類する

ここまでで、どういうときにどのようなエラーが発生するのかは、なんとなくわかったのではないでしょうか。ここからは、それらにどう対処するか考えます。

回復可能か回復不能か

まず、エラーに遭遇した時に、ユーザーの手で回復可能か回復不能かで対応を分けます。回復可能な場合、エラーの内容とあわせて回復方法をユーザーに伝えるのが親切です。例えば、以下のような例があります。

  • 通信のタイムアウト
  • 「データの取得に時間がかかっています。通信状況のよい場所で再度お試しください」
  • パスワードの文字数(強度)が足りない
  • 「パスワードは◯文字以上で入力してください」
  • 強度を示すインジケータもあるとより親切ですね

ユーザーにとって、エラーに遭遇するというのはとても残念な体験ですが、理由や対処方法を説明することで、イライラを軽減できます。

iOSの場合 LocalizedErrorerrorDescriptionrecoverySuggestionを定義できるので、それを活用して、アラートを表示するとよいでしょう。少し古めの記事ですが、こちらも参考になります。
iPhoneアプリの通信エラー処理を考える - iOS Advent Calendar 2011 - ninjinkun’s diary

仕様としてアプリで発生しうるエラーを定義できていれば、たいていのものは回復可能(ユーザーに何らかの回復方法を提示できる)と思います。とはいえ、大体の場合において想定外のケースは発生するので、回復不能な場合も考えてみましょう。

回復不能な場合どうするか

想定外のケースでアプリの利用に支障がでる場合、それを開発側が検知できるようにする事が重要です。クラッシュさせて、クラッシュレポートを活用するのも手ですし、クラッシュは防ぎつつ、エラーログを送って開発者が見れるようにするのも手です。Crashlyticsであれば recordError が使えます。なお、エラーログは、クラッシュログだけでは情報が足りないときにも有効です。エラー監視についてはこちらのスライドが参考になります。
iOS アプリエラー監視の設計とその効果 // Speaker Deck

また、エラーの内容・理由をユーザーに伝えましょう。クラッシュしてアプリが終了するとユーザーに伝えられませんが、丁寧にやる場合は、再起動時にメッセージをだす、サービス内にお知らせを出す、Twitterなど外部のチャネルでサポートするといった対応が考えられます。

アプリの利用に支障がない場合は無視してもいいかなと思いますが、そのようなエラーはそもそもコンパイル時にチェックできないか、エラーとして扱わなくても済むようにできないかなど、検討したほうがよいでしょう。なお、開発時は、assertionを活用してコードの問題に気づきやすくすることが重要です。クラッシュログやエラーログから原因を推定するよりも、よっぽど早く問題に気づけます。

おわりに

以上、いかがでしたか。全体像がわかると、次はいかに仕様の抜け漏れを防ぐのがポイントですね。
この記事が、予期せぬエラーが発生してユーザー満足度が下がることを防いだり、適切なエラーメッセージを表示してユーザー満足度を上げることにつながれば幸いです。