クロスプラットフォームの個人開発をこんな風に進めたという話

Flutter, React Native(Expo), Xamarin.Formsで振る舞いの同じアプリを作っていく上で、どんな風に開発を進めていったのかということを書いていきます。

# なぜ、3つのクロスプラットフォームで振る舞いが同じアプリを作ったのか？
業務でUnityとCocos2d-x(C++)に関わることがあって（開発とは全く別の関わり方です）、UnityとCocos2d-xのことをその当時ほとんど知らなかったので、どんな特徴があって、どんな違いがあるのかを勉強するためにほぼ同じゲームを作りました。この当時C#とC++は文法しか知らない程度から勉強を始めたので、いろんなサイトの見よう見まねで作りました。

ほぼ同じゲーム作りを進めていく上で、初めて「クロスプラットフォーム」という言葉を知りました。(Unityはゲームエンジンなので、正確にはクロスプラットフォームではありませんが)

その翌年、引き続きクロスプラットフォームを勉強したくて~~（本音その１：1つの言語でiOSとAndroid作れるなんてお得じゃん！、と思って）~~どのクロスプラットフォームが良いかなと思って調査して、最終候補が以下の3つになりました。

- Xamarin.Forms
- React Native
- Flutter

正直、調べてもこれらの違いって、提供会社と言語とリリース年くらいしか分からなかったので、3つで同じ振る舞いのアプリ作れば違いは分かるかなと思って、3つのクロスプラットフォームで作ることを決めました。
~~（本音その２：UnityとCocos2d-xでほぼ同じゲーム作って、とある場所でそれをネタにLTの登壇をしたら、「違う言語で同じゲーム作るって器用だね」「2つもできるなんてすごい！」って感想をもらって舞い上がって、なら今度は3つやろうと思ったからです）~~

※脱線話
Cocos2d-xは当時、名前すら知らなかったのですが、今では「MacとWindowsとiOSとAndroidで同じアプリ作りたいなぁ〜」って時、選択肢の第一候補になるくらい使ってます！しかもCocos Creatorを使ってUI周りを作ってから、それをCocos2d-xで取り込んます。さらに現在はCocos2d-xのwebアプリに挑戦中です！

# こんな風に開発した

## 作るアプリ
作るアプリは忘れ物防止アプリです。「旅行一週間前、当日、旅行中、帰りまで、で持っていくものや持っていったものの画像やイラストをタップするとそれが反転する」というアプリです。後で買い物のメモにも応用できるように作ろうと計画しました。

## 立てた計画
3つのクロスプラットフォームで同じ振る舞いのアプリを作るために、以下のように進めようと計画を立てました。

1. それぞれのクロスプラットフォームの入門書を購入する
1. 書籍をもとに環境構築する
1. HelloWorldまで進める
1. 書籍でHelloWorldの次に書いてある簡単なアプリを作成する
1. 3つのクロスプラットフォームに対して個人的な難易度をつける
1. プロトタイプ(見た目部分だけ)を作る
1. 実装を開始する

ここでの要点は「書籍でHelloWorldの次に書いてある簡単なアプリを作成する」と「3つのクロスプラットフォームに対して個人的な難易度をつける」です。
HelloWorldの次にある簡単なアプリを作ることで、どのクロスプラットフォームが自分にとって開発しやすいかという難易度を決めて、難易度の低い順に開発を進めました。これは進め方として、難易度の低いクロスプラットフォームをスモールスタートで基幹部分となるUIを実装して、もしその後で難易度の高いクロスプラットフォームでつまづいた時に、難易度の低い方に立ち戻って、別の方法で実装しようとしたからです。

難易度の高い方から進めてつまづいた時に、立ち戻って方針の転換ができないと思ったからです。
（そもそも、自分のように同じ振る舞いのアプリを異なる言語で同じタイミングに作る人がいて、かつ「この方針が良い！」「計画はこうした方が効率的だ」と指南してくれれば、この限りではありませんでしたが、こんな変わったことするのは自分くらいなので、いまだに出会ってません。）

自分で決めた難易度は低い順に（開発する順番は）

1. Flutter
1. React Native
1. Xamarin.Forms

としました。この順番にした理由は後述します。

### 参考にした書籍

- Android/iOSクロス開発フレームワーク Flutter入門
- Android/iOSクロス開発フレームワーク React Native入門
- Xamarinネイティブによるモバイルアプリ開発 C#によるAndroid/iOS UI制御の基礎

## 調査してわかったことを計画に反映(計画の軌道修正)
「書籍でHelloWorldの次に書いてある簡単なアプリを作成する」の時点で分かったことですが、自分にとってReact Nativeは3つの中で一番難易度が高いという状態でした。描画するために必要なJavaScriptの処理部分と実際に描画する部分の記述で、それらの因果関係がよく分からなかったんです。その時の難易度は低い順に

1. Flutter
1. Xamarin.Forms
1. React Native

でした。
ただ、調査段階でReact Nativeでの開発を容易にするためのサービス(ツール)があると知りました。それがExpoです。合わせてExpo自体が提供しているライブラリがあることも分かったので、React Nativeの開発はExpoを使うことで自分にとっての難易度を下げることができると分かったのです。
そして改めて開発する順番を以下のように修正しました。

1. Flutter
1. React Native(Expo)
1. Xamarin.Forms

## 開発順番を決めた理由
開発を決めた理由は以下の通り、個人的な感覚値です。

- Flutter
    - 提供しているUIが豊富で、UIの名前から直感的にどんな機能を持っているのか分かりやすかった
- React Native(Expo)
    - HTML&JavaScriptを知っていたのと、先述の軌道修正で調査前に比べて容易に開発できようと思った
- Xamarin.Forms
    - XAMLとコードビハインドの関係がよく分からなかった
        - 本格的に開発してから気づいたのですが、XAMLとコードビハインドの関係はJSPの画面とJavaの関係に似ていると思いました

## 開発の進め方（概要）
まず、プロトタイプをもとにFlutterで画像をGridで表示する機能を実装しました。それができたらReact Nativeで同じ機能を実装します。それができたらXamarin.Formsで同じ機能を実装しました。それができたら今度は・・・
あ〜〜、つまり、以下のような流れです。

1.画像をGridで表示する機能を実装
　1-1. Flutterで実装
　1-2. React Native(Expo)で実装
　1-3. Xamarin.Formsで実装
2.画像をタップできる機能(TapGesture)を実装
　2-1. Flutterで実装
　2-2. React Native(Expo)で実装
　2-3. Xamarin.Formsで実装
3.どの画像をタップしたか判定できる機能を実装
　3-1. Flutterで実装
　3-2. React Native(Expo)で実装
　3-3. Xamarin.Formsで実装
4.Tabでページ分けする(Tab Navigation)機能を実装
　4-1. Flutterで実装
　4-2. React Native(Expo)で実装
　4-3. Xamarin.Formsで実装

・・・

こんな感じに進めていきました。
一番時間かかったのは、3と4です。1つのクロスプラットフォームだけで2週間近く悩んでました。