🗻

【設計編】はじめてのReactで都道府県を当てるゲームをつくりました

2022/10/01に公開
2

前回の記事

前回の記事が予想以上の反響でびっくりしています。ありがとうございます🥲🌟
https://zenn.dev/karugamo/articles/bb7477d1e7a648

今回は自分の備忘録・反省として、前回省いた設計のことを書いてみます。
https://youtu.be/htrsHoqhoTY

1.要件定義

Reactの習得のため、ゲームを作ろうと思い立ち、まずは要件定義をしました。
要件定義にはNotionで以前自分なりに作ったテンプレートを使っています。
ただ今回のゲームに関しては、①Reactの習得のため・②仲間内で遊ぶために作ったので、そこまで詳細な要件定義はせず、あくまで簡易的な機能要件を書き出したのみにとどめています。

このへんは空欄ばかりです。

機能要件として、つける機能をすべて書きました。
このあとにもいろいろと書いていますが、常に念頭においていたのは「あまり複雑なゲームにはしたくない。あくまでできるだけシンプルにする」です。
そういった視点で考えたとき、アクセスしたら名前を設定しなければいけなかったり、ルームを作成する必要があるのは嫌だったので、アクセス時に名前は自動割り当てされ、アクセスすればすぐに遊べるように作りました。
(私自身が複雑なゲームが苦手なのもあります…)

要件定義は自己流で何が正解なのかわからないのですが、個人的に何か作るときにはひとまず最初に「何が作りたいのか」「何をゴールとして、何が課題なのか」「どうやって作るのか、なぜ作るのか」あたりがわかる文書を作成することにしています。

2.フローチャートを作った


この段階ではユーザー名の設定が最初に来ているなど今と違っている箇所が多いですが…
前項の要件定義をもとに、機能要件を満たすフローチャート図を作成しました。
このフローチャートで、どのような処理が必要なのかを大まかに以下の3つに分けました。

  • gameSetter ターゲットの都道府県を決め、入力されたモードに従い、出題項目を取得する処理

  • chatter 入力されたモードに従い、1秒ごとに出題する処理

  • judger ユーザーの入力(input)を判定する処理

    • 当たりかどうかの判定をする処理
    • 残機の処理
    • スコアをつける処理
  • inputHelper ユーザーの入力時にサジェストする処理

  • hint ヒントの表示

必要な画面とその構成要素


また、上記フローチャートに基づき、必要な画面と、それぞれの画面を構成する要素を書き出しました。

フローチャートの作成にはdraw.ioを使用しています。ブラウザ上で動作し、フローチャートの作成操作が直感的でわかりやすく、またER図なども作成でき機能が豊富ですごく便利で使っています。おすすめです。(他に良いツールがあったら教えてください…)
https://drawio-app.com/

3.ワイヤーフレームの作成

前項で、必要な画面とその構成する要素が判明したので、それに基づいてFigmaでワイヤーフレームを作成しました。

※前回載せた手書きのワイヤーフレームは、これを作った後にレイアウトをもう一度考え直したくなり、より直感的な方法である手書きでワイヤーフレームを作りなおしたものです。

キーボードで埋まる画面をどうレイアウトするか

前回の記事で紹介したように今回のゲームは元となるLINE botが存在していたので、それをどうWebベースに作り変えるかが課題でした。
LINEはチャットという制約がある中だったのでUIのことを考えずに済んでいましたが、WebベースだとUIやレイアウトが自由です。

ワイヤーフレームを作りながら、まず本ゲームを大まかに以下の3つのゾーンに分けました。

  • Questioner 問題を出題するゾーン
  • AnswerInput ユーザーが回答を入力・送信するゾーン
  • Chat ユーザーの回答を表示するゾーン

この3つの要素を、特にモバイルの小さい画面でどう見やすく・分かりやすく・楽しくレイアウトするかが大きな課題となりました。
スマートフォンでは入力中は画面の半分近くがキーボードで埋まってしまうので、非常に限られたスペースでどう面白く構成するかに悩みました。
キーボードを利用せず、選択肢の中から回答するUIも考えましたが、早押しに近いゲームの中で47個の選択肢をどう表現するかが難しく、キーボードを利用することにしました。
そのため、キーボード表示時のレイアウトからまず構成し、ワイヤーフレームの段階で試行錯誤してレイアウトを決めていきました。

4.ER図みたいなものを作った

次に技術選定を行い、データベースにFirebase Realtime Databaseを選択しました。
また今回Reactの学習のための制作ということで、できるだけシンプルに、バックエンドは書かずクライアントサイドのみの処理で完結したかったので、Firebaseとクライアントのみでどうやってゲームの処理を成立させるかが課題でした。
そのためコードを書く前に、ER図のようなアーキテクチャ図のようなシーケンス図のような、とりあえず流れを考えられればいいやみたいな図を作成しました。

こちらもdraw.ioで作成しています。

5.Reactの流儀に従って作った

いよいよ実装をしていく段階です。
Reactの公式サイトにReactの流儀というものがあったので、それに沿って行いました。
https://ja.reactjs.org/docs/thinking-in-react.html

1.Figmaで作ったワイヤーフレームをコンポーネントの階層構造に落とし込む


Figma上で、コンポーネントの階層構造を赤の点線で表現し、コメントでコンポーネント名とpropsを書いていきました。
ここで念頭に置いたのは以下の2点です。

  • ひとつのコンポーネントはひとつのことだけをする
  • 宣言的なコンポーネントにする。propsが同じなら、必ずレンダリング結果が同じになるようにする

(今見ると、inputが独立したコンポーネントになっていないなど改善できる部分がありますね)


必要なコンポーネントを割り出したので、Notionで階層構造に書き出します。
青文字はstateで、このあと追記した部分です。

2.静的に動作するバージョンを作成する

UIの描画だけを行って、ユーザからの操作はできないというバージョンをまず作ります。
この段階では一切stateは使わず、propsだけを使って作ります。

ダミーテキストが適当すぎる
ここまでの流れで、アプリを描画するコンポーネントが手に入るということです。

ここまでのステップを終えると、データモデルを描画する再利用可能なコンポーネントの一式が手に入ります。このアプリは静的なバージョンなので、コンポーネントは render()メソッドだけを持つことになります。
このやり方なら、複雑なことをしていないので、UI がどのように更新されて、どこを変更すればよいか、理解できることでしょう。React の単方向データフロー(あるいは単方向バインディング)により、すべてがモジュール化された高速な状態で保たれます。

3.UIを表現する必要かつ十分なstateを決定する

stateを決定していきます。
stateは、アプリケーションが必要としている最小限にするべきということを念頭に置きました。

DRY (don’t repeat yourself)の原則。アプリケーションが必要としている最小限のstateにする。他に必要なものが出てきたら、そのとき計算すればよいのです。

  1. まず、アプリを構成するすべてのデータを書き出しました。
  2. それぞれのデータについて、3つの質問(Reactの流儀より)をして、どれをstateにするのかを決めました。
    1. 親から props を通じて与えられたデータでしょうか? もしそうなら、それは state ではありません
    2. 時間経過で変化しないままでいるデータでしょうか? もしそうなら、それは state ではありません
    3. コンポーネント内にある他の props や state を使って算出可能なデータでしょうか? もしそうなら、それは state ではありません

上記のステップで、stateの最小構成が明確になるということです。

4.stateをどこに配置すべきかを決める

どのコンポーネントがstateを所有するのかを決めました。

5.逆方向のデータフローを追加する

ロジックを追加し、アプリケーションが動作するようにコードを書いていきました。

まとめ

今回の反省点

ワイヤーフレームの段階でReactの実装をしたこと

今回、ワイヤーフレームを作った段階で実装を行い、機能ができてからデザインをしていく方式をとりました。
この流れだと、ワイヤーフレーム時になかった要素がデザイン時に発生したり、逆にあった要素が不要になったりして、せっかく考えたコンポーネント設計をやり直すことになってしまいました。
これでは非効率なので、これからはデザインが完成してから実装を行いたいと思います。

技術選定が中途半端だった

今回、ボトムアップな作り方をしました。具体的には、Reactの流儀に従い、最初にFirebase抜きで動作する状態を作り出し、その次にFirebaseを導入したのですが、それによってコードをかなり書き換える手間が発生しました。最初からFirebaseを導入していれば起こらないものでした。
また、当初状態管理ライブラリは必要ないと考えていたのですが、ゲーム中かどうかの判定などで次第にバケツリレーが多くなってきたため、途中でReduxを導入しかなりコードを書き換える手間が発生してしまいました。
要するに、いきあたりばったりになってしまったので、今度は最初にもう少しちゃんとアーキテクチャを設計しようと思います。
https://twitter.com/koluriri/status/1556494691272884224
https://twitter.com/koluriri/status/1556618949491851265
https://twitter.com/koluriri/status/1560477506247213056

React楽しい

なにはともあれReact楽しいです!🥳
今また作ってるものがあるので完成したら紹介したいと思います。
読んでいただきありがとうございました🙌

Discussion

takataka

設計のフローめちゃくちゃ参考になりました。
私も参考にさせていただきます。
まだ、18歳なんて、、、、、、、、プロにしか思えないですね。

こるりりこるりり

ありがとうございます〜!!
拙い記事ですが少しでも参考になれば嬉しいです😚