
インタラクションの設計は、デザイナーとエンジニアの間で責任範囲が曖昧であったり、デザイナー視点ではデザインファイルやプロトタイプ上で表現することが難しかったりと、ユーザー体験に最適化した実装を行うためのハードルがいくつか存在します。今回はそんなインラタクションの設計の中でも、スムーズなUIの操作性に影響する「Optimistic Update(楽観的更新)」という実装パターンを紹介します。
UI更新における楽観的・悲観的とは?
今回紹介するのは「Optimistic Update」、つまり楽観的な更新です。ここでいう「楽観的」とは、ある処理が「成功すると楽観的に信じて」結果を待たずにUIを更新するような実装のことを指します。

どういうことかわかりやすいように、まずはより一般的な普通の実装、つまり「楽観的ではない更新」を見てみましょう。

このように、通常の実装ではユーザーアクションの結果がシステムから返ってきた後にエラーなどの問題がないことを確認してからUIの状態を更新します。UI上では、ローディングインディケーターやプログレスバーを表示して、ユーザーに処理が進行していることを伝えるようなケースがこれにあたります。
このような実装は、処理の結果が失敗する可能性もあることを考慮して、正確な処理結果を待った上でUIを更新するという意味で「悲観的な更新」と いうことができます。
悲観的な更新の問題点
このような「悲観的」なUI更新には、わかりやすい欠点が一つあります。それは、「処理の結果が返ってくるまでユーザーを待たせてしまう」という点です。
特にサーバーとの通信を行うような処理では、サーバーでの処理の長さやネットワークの状態が影響して、ユーザーの想定よりも長く時間がかかってしまう場合があります。このような場合、ユーザーの想定している処理時間との乖離が大きければ大きいほどユーザー体験を損なうことになります。
例えば、ECサイトの購入ボタンをクリックするような場合は、一連の購入フローの最後のアクションである(= 次に続く操作が存在しない)上、ユーザー側も「購入」というアクションに一定の時間がかかることを想定するため、多少処理に時間がかかっても大きなストレスを生むことはないでしょう。
一方で、例えばタスク管理ツールにおける「タスクの削除」というアクションはタスク管理という一連の作業の中で行われることも多く、これに想定以上の時間がかかるとユーザーはス トレスを感じます。しかし、ユーザー視点ではシンプルに見えるアクションにも、場合によってはシステム側での処理に時間がかかってしまうこともあります。

このように「ユーザーの期待する処理速度との乖離」があるような場合には、システムの反応を待ってからUIを更新するとユーザー体験を損なうことにつながってしまいます。
楽観的なUI更新(Optimistic Update)
そこで有効なのが『Optimistic Update』と呼ばれる実装パターンです。

Optimistic Updateとは、「システムの処理結果を待たずに処理が成功したと仮定して”楽観的に”UIの状態を更新するような実装 」のことを指します。
このような実装を行うことで、ユーザー側は処理の完了を待つことなく次のアクションに移ることができ、スムーズな操作感を実現することができます。まさに、タスク管理ツールにおけるタスクの削除のようなユースケースにはぴったりの実装です。
Optimistic Updateの使用を検討する際には、前述した「ユーザーの期待する速度との乖離」と同時に「処理が失敗する確率」と「失敗した際のリカバリーの重要度」も考慮すると良さそうです。
Optimistic Updateを導入する上で検討したい項目
ユーザーの期待する処理速度と実際のシステムの処理速度の乖離
処理が失敗する確率
失敗した際のリカバリーの重要度
例えば、フォームの送信や課金処理などはユーザーが入力した情報に左右されて処理が失敗する可能性も比較的高い上、失敗した際にはすぐに再入力などのユーザーアクションを促す必要があります。このようなケースでは、Optimistic Updateを導入せずにローディング・インディケーターなどを表示しながらユーザーに処理結果を待ってもらうことが適切でしょう。
一方でタスクの削除など、ユーザー側の事情で失敗するようなケースが少ないような処理に関してはOptimistic Updateを導入することによるメリットは大きいでしょう。
万が一、処理が失敗した場合のリカバリーを考える
Optimistic Updateは処理の失敗確率が低いアクションに取り入れられるとはいえ、場合によってはユーザーネットワーク接続の問題などで処理が失敗することも考えられます。このようなケースに対応するために、処理が失敗した場合のリカバリー方法も考慮しておくと安心です。

多くの場合は、トースト通知などを使用して非同期的に処理の失敗をユーザーに伝えるような方法で十分ですが、ネットワーク接続の問 題などは一定期間後に解決していることも多いため、バックグラウンドで複数回処理を試して一定回数失敗したらユーザーに通知するというようなケースも多いです。
Optimistic Updateによってユーザーが何度も状態を切り替えてしまわないように
その他、一回目の処理の後にユーザーが再度同じボタンを押せるようなケースには注意が必要です。前述のタスク削除などではタスク自体がUI上から消えるため、ユーザーが再度削除ボタンを押すことはできませんが、「データの更新」や「状態の切り替え」などの処理では、Optimistic Updateを導入することで「前の処理が終わる前に次の処理リクエストが連続して始まってしまう」というような状況が起こりえます。

このような場合には、ユーザーアクションの交通整理を行う『Debounce』という処理と組み合わせると有効です。Debounceとは、ユーザーアクションが連続する場合に、ユーザーの操作が止まったタイミングで一度だけ処理を行うという実装パターンで、Optimistic Updateと組み合わせて使用することも非常に多いです。Debounceについて詳しくは以下の記事で解説しているので、ぜひこちらも合わせて参考にしてみてください。