クロスプラットフォームの個人開発をした時に思ったこと

[前回書いた記事](https://qiita.com/ito-kenichi/items/b5dc1a38e10be0919aa7)の続きで、Flutter, React Native, Xamarin.Formsで同じ振る舞いのアプリを作った時に、「こう作ったからこんな風に思った」ってことを書いていきます。

# 第一印象〜実際のギャップ
## Flutter
第一印象は「HTMLとCSSと描画するためのロジックがHTMLとは違う記法で1つのファイルに書いてある」って思いました。あと、Widgetが豊富で名前から機能を推測しやすい（FloatingActionButton, GridViewなど）。
実装を進めて思ったのは、Widgetごとの必須プロパティがあってそのプロパティ名は「どんな値を設定すれば良いか直感的にわかる」ということです。
難点だったのはエラー出た時に英語のサイトでも情報がまだ少ないということです。当然、英語の情報が少ないので日本語の情報も少なく、動くかどうかコードを1ステップごとに確認しながら進めなくてはいけなかったことが大変でした。

## React Native
第一印象は、JavaScriptは以前から触っていたので抵抗なく、main.jsの構成もHTMLタグとScriptがあって、分かりやすいな〜と思ってました。（思ってました！、強く強調しますが、過去形です！！）
実際にやってみると、ライブラリのバージョン管理が非常に、非常に、大変でした。画面遷移したいだけなのにReact Native側でもExpo側でも機能として提供していないので、npmからインストールするしかないのです。が、依存関係のある別ライブラリをインストールするとビルドエラーが発生し、その解決を試みると、別のエラーが、、、ということの繰り返しでした。
ただ、React Nativeで開発を進めて「こういう風に理解できた！」という概念（？）が、「ツリー構造」と「状態の管理」です。この点は後述します。

## Xamarin.Forms
第一印象は、正直HelloWorldの次に何をすればいいのか分からなかったことです。XAMLとコードビハインドの関係性がよく分からなくて、「XAMLファイルとコードビハインドをこうしたら、こういう期待通りに動く」ということを理解するまでに時間がかかりました。
ただ、実際に同じ振る舞いのアプリに着手すると、JSPのページとJavaの関係に似ているという印象に変わりました。例えば、テキストの文字列を動的に変更したい場合、コードビハインドでXAMLのLabelのx:Nameを指定してtextに文字列を代入すれば操作できると理解しました。

# クロスプラットフォームで開発して自分なりに理解したこと
開発で詰まったことを解決する過程で、こんな風に理解したということが「ツリー構造(階層構造)」と「状態の管理」です。書籍や概要説明のサイトでよく見かけるのですが、いまいちよく分かりませんでした。そしてとりあえず作ってみて、振り返ってこういうことを言っていたのかと理解したことを自分なりの言葉でまとめました。
先にも書きましたが、この２つはReact Nativeでハマった時に学びました。

## ツリー構造(階層構造)
ツリーや階層と言っているので、複数の何かがあることは分かるのですが、具体的にどういう関連性で紐づいているのか分かりませんでした。
これを理解したのは、

1. TabNavigationのtab1つごとにScrollViewを実装
2. 上記のScrollViewにGridViewを実装
3. 上記のGridViewのセル1つごとにTapGestureを実装
4. 上記のTapGestureに画像を配置

が終わった時でした。
これは、以下のようなレイアウトの場合に、最後に実装した画像はTapGestureの子要素で、TapGestureはGridViewの子要素で・・・、というった具合に入れ子になっていることに気づきました。

![スクリーンショット 2021-02-23 13.58.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456945/b8ca1332-82ab-38bf-3f32-7adfa731a550.png)

つまり、断面として以下のようになっている「親子関係のある入れ子」なのだと理解しました。

![スクリーンショット 2021-02-23 14.13.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456945/40748af1-f4ad-2562-9070-7f7b3fdbd471.png)

さらに詳しく説明すると、Component(Widget または Class)が土台となって、その土台に他のComponentを乗せることができる、またはそのような構造となっていると理解しました。
（実際にはやらないと思いますが）Tab NavigationやScrollViewだけをひたすら入れ子にして行くこともできると理解したのです。
Componentとその子要素をどのように表示するのかを、Componentのプロパティによって決定すると理解しました。これに加えて、Componentに対するプロパティの操作がその子要素にも波及することも合わせて理解しました。

## 状態の管理
そもそも、「状態」というのがなんなのなんとなくしか理解できていなかったのが開発の前でした。開発を進めていく上で状態というのは、「表示するために必要な値の状態」であると理解しました。
例えば、Flutterの新規Projectにある"count"というintの変数は、タップするごとに値が変化します（1増加していく）。そして"count"はアプリの画面に表示している「タップ回数が今何回タップされたのか」という情報を保持しています。
つまり、表示するために必要な値が変化すれば、値の変化に応じて表示が変わるということを理解しました。状態の管理の「管理」とは、表示するための値が変わったら、それを検知して表示に反映させる目的で表示に必要な値を監視しているということです。
ここでいう表示に必要な値は、配列であったり、Componentであったりと表示に必要なものであるということです。

# 個人的にこんな人にオススメ

- Flutter
    - 後述のReact Nativeにも、Xamarin.Formsにも該当しない人にオススメ
    - スマホアプリ開発が初めての人にもオススメ！
        - これからFlutterのプロジェクトが主流になっていくと見込んでいるので！（多分、、）
        - 簡単なUIを実装するアプリならサンプルは豊富

- React Native
    - フロントエンド開発の経験者にオススメ
        - 特にReactやVueを経験した人は構造体やComponentの理解がすでにできている
        - スマホアプリの初学者にはオススメしない！（ライブラリの管理でハマって嫌になるかも、、）

- Xamarin.Forms
    - バックエンド開発の経験者にオススメ
        - XAMLとコードビハインドの関係性を画面とロジックに置き換えて理解しやすい（個人的に、、）
        - スマホアプリの初学者にはオススメしない！（やるならUnoPlatformやMauiからの方が将来性がある、多分）

# [雑談]もっともよく聞かれた質問
いろんなところで「３つのクロスプラットフォームで同じ振る舞いのアプリを作ってます！」っていうと、絶対と言っていいくらい聞かれることがあります。
それを勝手にこう呼んでいます。FAQならぬ、**EAEAQ**と。

**Everytime And Everywhere Asked Question**
(いつでもどこでも聞かれること)

そして、その聞かれることというのは、

**どれが一番オススメですか？**

正直、ハマりポイントや実装のタイミグによって答えがコロコロ変わるので、グラフにしました。

3 : オススメ
2 : まぁまぁオススメ
1 : オススメしない
0 : 「オススメについての発言を差し控えさせていただきます。」

![スクリーンショット 2021-02-23 15.24.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456945/184d1bfa-5005-dcce-ce1e-3679ae43a079.png)