💎

フロントエンドアプリを画面駆動で考えて本当によかったのか: フロントエンドとバックエンドはそんなに違わない

2024/01/15に公開

アプリエンジニアの同僚からよく、「アプリって画面が中心なんだよね」との声を聞く。筆者にはそれだと、画面と画面を繋ぐ一貫性を持った何かしらのテーマを見逃しているように思えるので、この記事で考えを説明していきたいと思います。

アプリの存在意義を考える

アプリの存在意義を考えてみると、エンジニアは目的もなくただ漠然とUIを作っているわけではないということが分かります。エンジニアがアプリを作るのには目的があって、その目的とはユーザーがやりたかったことを実現してあげることになります。

ユーザーがやりたかったことの実現(ユースケース)は画面に言及しなくても語れるのに対し、画面はその流れをグラフィカルに表現した手段(UI)に過ぎない。

このことから、

という依存関係が成立していることが分かり、アプリの中心はUIの裏で糸を引くユースケースであると言うことができます。

ユースケースの領域

一つのユースケースは、アプリの特定の一通りの使い方を表現しており、複雑な処理を一つの単位にまとめる手段でもあります。

例えば勤怠管理アプリなら、「社員が有給申請を出す」というユースケースが存在し、その中で、

  • 有給残日数が足りているか
  • 申請理由を記入しているか
  • 上長は誰なのか

などの複雑な処理が実行される可能性があります。

この、複数の部品によって支えられた複雑な処理に、一つの統一された簡潔な入り口を提供するという手法は、オブジェクト指向設計でいうFacadeパターンになります。図示すると下記のようになります。

  • ボール: 内部の複雑な処理を支える複数の部品
  • レンズ: 外部向けの一つの統一された簡潔な入り口
  • レンズに入る矢印: 外部から依頼できる、処理のステップ
  • 同色の矢印: 一つのステップ内に登場する部品や処理の順序を表す

UIにFacadeだけ提供することにより、内部の実情がUIに漏れることもなく、UI側としてもステップを進めることだけ意識すればいい、というUI↔ユースケース間の疎結合を実現することができます。

ユースケースの実例: Voicyのアカウント作成のユースケース

ユースケース駆動の具体例として、弊社Voicyのアプリ(AndroidiOS)におけるアカウント作成のユースケースを取り上げたいと思います。

ユースケーステキスト

このユースケースをテキストで説明すると、下記のようになります。

  1. ユーザーが利用規約に同意する
  2. ユーザーが段階的に名前、メールアドレス、パスワードを記入する
  3. システムが入力に不備がないか都度チェックしてユーザーに伝える
  4. (不備がなくなるまで2と3を繰り返す)
  5. ユーザーが記入完了を宣言し、アカウント登録を確定させる

ユースケースはUIから独立して存在するものなので、ここでは登場人物の行動や意図だけを語り、ボタンやテキスト入力欄などのUI要素で語らないようにしています。

部品による実現

このユースケースは下記の部品を使って実現することができます。

アカウント作成のユースケース

前述したFacadeにあたるもの。ユーザー・アプリ間のインタラクション一種類につき、ステップを表すメソッドが一つ用意されている。

メソッドの戻り値に、そのステップが成功したか失敗したか、失敗したならなぜ失敗したのか、といった情報が含まれる想定。

利用規約同意状況

一般的なBooleanに、具体的な名前を付けたもの。

登録情報

名前、メールアドレス、パスワードを格納し、フォーマットの制限が守られているかどうか、必要な情報が揃っているかどうかが分かるもの。

登録サービス

登録情報を永続化する意図を表したもの。

登録API、登録リクエスト

登録情報を永続化する手段を表したもの。バックエンドの所在、バックエンドに求められるデータフォーマットを把握している。

意図を語るときにバックエンドの都合に振り回されないよう、バックエンドに関連するものを手段の領域内に閉じ込めている。

ユースケースだけでも成り立つテスタビリティ

まだUIには一切手を付けていない状況ですが、ここまでで既に論理的な仕様がテストできるようになっています。例えば、

  • 正しく手順を踏んだユーザーはアカウントを作成することができる
  • 利用規約に同意しなかったユーザーはアカウントを作成することができない
  • 長すぎる名前を指定してアカウントを作成することができない

などが挙げられます。

まだ出番がないフレームワーク

ここまででフレームワーク(プラットフォーム)が指定したクラスを継承しなければならないとか、決められた手順を守らなければならないとか、そういったことをやる必要性は一切出てきていないです。

ユースケースの領域は、表現したかった仕様を自由に表現していい領域であると言うこともできます。

プラグインとしてのUI: 画面数とユースケース数は無関係

ユースケースが実現できたら、プラグインとしてUIの部品をユースケースに接続します。Voicyアプリでは利用規約同意画面と登録情報記入画面が分かれているので、

  • 利用規約同意画面を表示するタイミングで、「アカウント作成のユースケース」を構築する
  • 登録情報記入画面に遷移するタイミングで、「アカウント作成のユースケース」を保持する

という風にUIとユースケースのライフサイクルを切り分けることができます。

UIのロジックとしては、ユーザーの操作をキャッチする他に、ユースケースとの通訳の部分も含まれます。例えば、

ユースケースでいう UIでいう
ニックネーム文字数超過 ニックネーム枠赤表示オン
記入に不備あり 進むボタン活性化されず

などが挙げられます。

フロントエンドとバックエンドはそんなに違わない

ここまで見るとフロントエンドとバックエンドのアーキテクチャはそんなに違わないことが分かります。

フロントエンド バックエンド
表現の層 グラフィカルな要素 JSON
主旨の層 ユースケース以内の部品たち ユースケース以内の部品たち
通信の層 ストレージ、バックエンド、OS データベース、OS

フロントエンドを、バックエンドの表現の層をただ強化しただけのものとして捉えずに、フォーカスは違えど両方とも自走できるプログラムである、と捉えた方がよいのではないかと筆者は思います。

Further Reading

記事内ではユースケースを魔法の言葉のように使ってきましたが、ユースケースとはなにかや、ユースケースを書くのにあたって注意するべきポイントなどを紹介した Writing Effective Use Cases という本があるので、詳しくはそちらをご覧ください。

Voicyテックブログ

Discussion