Androidアプリの開発するなら要件定義と設計はこう考えるといいんじゃない

# はじめに

ごぶさたしてます。Javaおじさんです。
相変わらずのフリーランス稼業で糊口をしのいでいる感じですが、さすがにこのご時世Webアプリだけ作って食っていけるわけでもないのでAndroidのアプリにも手を出しているわけです。
ただ、Webアプリって結構設計前に考えなきゃいけないことが少ないせいで、Androidのアプリ考えるときいろいろスコーンと抜けてることが多くていざブツを作ろうとすると結構大変だったりします。
というわけで、いろいろ過去の事例を思い出しつつAndroidアプリを作る場合の要件定義や設計なんかについて備忘録代わりにちょっとまとめてみましょ。

# 前提

そもそもAndroidアプリだろうがiOSアプリだろうが、Webアプリと違って以下の特性が存在します。ぶっちゃけこのあたりはクライアント/サーバ型のシステムの設計/運用ノウハウが結構流用できると思うんだけど意外にもうみんな忘れてるんだろうか。

- Webサーバと違ってメモリが決定的に少ない。なのであまり一度に大量のデータを受信するとメモリ不足でアプリが死ぬ。それゆえ事前のデータ量見積、各データのCRUDタイミングの洗い出し、インストール直後の初期データの定義はとても重要。
- Webのサーバサイドと違ってデータをアドホックに取得するコストが高い。サーバサイドの感覚でモバイルの処理を設計するとAPIの粒度が小さすぎてコールバック地獄どころじゃないレベルになる。そのため、ある程度大きな粒度でサーバ側のAPIを設計する必要がある。あー、でも今だとRxJavaとかJetpackとかあるのでその辺使えるとそこまでコストは高くないのかも。...ホントに？
- モバイルで運用するのが前提なのでモバイル機器ならではの考慮点が存在する。画面の回転やアプリの切り替えへの対応、バージョンアップの通知など。

なお、以下は別にAndroidに限ったことでもなく基本の話。

- 開発初期にコードの良しあしを見極められるメンバーを確保するのがとても重要。内製するにせよ外部に委託するにせよ後から軌道修正するのは本当に本当に大変なので、最初からきちんとコードを律することのできる体制がとても重要。Javaでブツを作るのにパッケージ分割もロクにしてないとか、クラス間の**相互直接**依存関係をもりもり設定するとか、ネットのサンプルコードをコピペするしか能がないとかそんな奴は論外ですYO!
- その意味では2019年の暮れにもなってMVVMとかJetpackとかのキーワードをぶつけてちゃんと理解した答えが返ってこないような要員は初期にチームに入れるべきではないと断言できます。開発後半になってアプリケーションアーキテクチャが定まったら別にいいけどね。
- チーム開発するのに**共有可能な概念モデルなし**とかエスパーですかあんたたちは。「チームが自律的に動いてくれない」とお嘆きのそこのあなた、もしかしたら一般的な人間には無理なことを要求してるのかもしれないっすよ？**情報は持ってる人間が出すのが基本**です。だって他人の頭の中はふつう見えないからね？あんたの頭の中の情報は常にみんなに見えるようにしておかないとそりゃ自律的になんて動きようがないですからね？

# 要件定義ではこれを作っとこう

「要件定義は終わってます」と言いつつこのあたりが出てこなかったらその仕事は受けるか受けないか考えてしまうな。

### 採用するハードウェアのスペック表

上にも書きましたが**モバイル機器はサーバどころか一般的なPCと比べてもリソース量は劣ります。**...そのはず。極まれに支給されたPC見て「**いやこれおれのiPhoneの方がマシだろ**」とつっこみたくなる現場あるけど。

特にメモリは重要。ただし、**「RAMが2GB」**と言われても**2GB使えると思っちゃいけません。**OSがどこで動いてると思ってんの。他のアプリも動いてるんですよ。RAMが2GBと言われてもそのうち使えるのは半分もないと覚悟してソフトウェアの設計を考えるべき。

そういうことを考えないとサーバのDBのデータを一気に全件落としてくるとかいう愉快なステキ設計をします。その結果開発中は大丈夫でもいざ本番データ入れて実機検証始めるとメモリ不足でさくっと死ぬという事象が頻発します。Android Studioでログ見てるとすげえ勢いでGCログが流れたあとポクッと死ぬところが観察できてなかなか大笑い。いや笑えないけど。

### データ量見積

ここでいうデータ量見積は以下の3種類。
いずれも重要です。

- 初期データ量
- データ増加量
- データ変更量

初期データ量はわかりやすいですな。
稼働直後にDBテーブルそれぞれについて何行のデータが必要かを見積もります。
「商品」テーブルだったら扱ってる商品の数ってどのくらいですか？とかそういうヒアリングをちゃんとやること。
基本的に行数の情報とテーブル個々の設計があれば実際にどのくらいの容量（DBやらメモリやら）が必要になるかは概算でわかります。
1行100バイト程度のデータが10000行あるのと、画像データ含んだ1行1GB前後のデータが1000行あるのとどっちが重いかってことは考える必要があるけれども、普通のDBAがそんな1行1GBなんて設計するはずが...え？DB設計のスキルがない？なんなら追加料金払ってもらえば請け負いますけど？

データ増加量もわかりやすいと思うんですよ。
稼働開始から一定期間にどのくらいのペースでデータが増えていくのか見積もります。
上の商品の例でいえば、新しい取り扱い商品の増加ペースってどのくらいですかね？とかそんなヒアリングをすると。
これが結構激しい場合はローカルにデータをロードするのはちょっと考えた方がいいかも。
ローカルのマスターデータをサーバから差分でとってきて更新するとかいうことを考える場合、これと次に出てくるデータ変更量の見積もりが大事になります。

データ変更量は読んで字のごとく、登録されたデータがどれだけの頻度でどの範囲が更新されるかを見積もるものです。
商品情報の洗い替えを定期的にやったりするのかとか、データの削除タイミングとかから見積もることになります。
変更量が大きい場合には差分とか言いつつ結構なデータ量のダウンロードが必要になるので注意が必要ですね。これをちゃんと見積もっておくとおかないのとでは雲泥の差です。リスクがあるのかないのかわからない、というのがマネージメント上最悪だからね？

### CRUD図

これも重要。
各種処理においてどのテーブルのデータをC（Create）、R（Read/Retrieve）、U（Update）、D（Delete）するかを表であらわしたもの。
上にも書いたけど、基本的にモバイルからサーバに対してデータを要求する処理はサーバサイドアプリに比べてはるかにコストが高いし使えるメモリも少ないので、処理を完結させるのに必要十分なデータを最初にまとめて持ってくる必要があります。なのでAPIの適切な粒度を見極めるためにはどの処理の中でどのデータがどれだけ必要なのかの情報が必要不可欠。
これがないと、必要もないデータを全部持っておこうとか逆にサーバサイドのWebアプリ作る感覚でAPIの粒度を小さくしてアドホックにデータを引っ張ろうとします。
どっちもモバイルアプリ向けの設計としちゃNGだと思うんだ。
特にAPIの粒度を細かくするのは本当にNG。コールバックの連鎖とかもう完全な地獄。ちょっと設計間違えるとリトライもしづらいようなややこしい構造が平気で出来上がるので、CRUD図は絶対的に必要。

### 概念モデル

説明不要ですよね？重要に決まってるよね？
そもそも概念モデルの共有もなしにどうやって設計すんの。
上述のCRUD図とか作る過程で当然のように作るでしょ？
ていうか作りなさい。

別にUMLとかでなくてもかまわないけど、あとからプロジェクト外の人間が入ってきたときに理解できる形式であることが大前提。少なくともExcelの表形式とかデータ間のつながりが全く分からないんで却下。
ER図でもいいんだけど視点がDBに寄りすぎるのはアプリケーションのアーキテクチャ考えるうえでちょっと引きずられてしまいがちなので注意するべき。

### 要件リスト

そりゃ要件定義なんだから作るよね？
顧客的にどれが優先事項か、そこもちゃんとヒアリングしてるよね？
技術的難易度による優先順位付けなんてもんはこっちで考えればいいんだから、要件定義で聞いてくるべきは**「顧客が一番やりたいことはなんだ」**ってことでいいです。
それがなければ「システム導入後の業務設計」もできないんだから。
顧客はシステムに夢を見るべきだし、おれらはそれを技術でかなえるのが仕事なんです。
ただし、空を飛べとか言われても無理なんでそこは技術的な検討後にきちんとできないものは**「xxなんでできないです、代わりにこんなんどうですか」**って言わないといけないけれども。

なに、こんなにいろいろ作るのめんどくさい？
じゃあやめちまえよもう。
プロなんでしょ？ギャラもらってるんでしょ？もらったギャラ分は働きなさいよ。

# 設計するとき気を付けること

### これはサーバサイドアプリじゃないと強く意識すること

まずはこれに尽きるんじゃないかなと。
前提としてモバイル側でやれることは限定されているので、サーバ連携をすること前提なら多量のデータを扱うタスクはサーバ側でやらせること。
逆にモバイル側でないと拾えないデータについてはモバイル側で処理をする、といったようにデータのCRUDを考えてどちらで処理するかをきちんと意識することがとても重要になります。
なに？CRUD表作ってない？...お疲れ様でした。終了～。

### Excel方眼紙なんて窓から投げ捨てること（特に画面設計をするときは）

画面設計をExcel方眼紙でやっている時間ほど無駄な時間は、他に類を見ない。
エビデンスたらいうスクショコピペを作ってる時間よりも無駄。あ、どっちもExcelだった。
と言いつつおれは別にExcelは嫌いじゃないですよ？何の生産性もない無駄な作業が嫌いなだけ。

だって考えてみ？Excel方眼紙でしこしこ画面設計作りました、レビューとおりました、そのあとどうつながるの？何にもつながらないよね？そのExcel方眼紙がレイアウトファイルになったりするの？なんないでしょ。
それどころかモバイルの特性無視した激重UIを簡単に生むよね？
ListViewやらRecyclerViewの1行に20個くらいTextView載せたりとかさ。しかもそれが結構な行数出てくるとかさ。そら動きももっさりするわ。
「頑張ってデータ詰め込みました」...いやそれWebだったらただの文字列で済むけどモバイルだと回転したときの再配置とかを考慮しないといけないから文字表示するにもそこそこリソース使うのよ？
そんなところ頑張らなくていいですから。

だったら最初っからAndroid Studioでレイアウトファイル作ってそれエミュで動かしてお客さんにみてもらった方が早いんですよ。イメージもつけやすい。アジャイルとかそういう以前の問題として、これから何を作るか確認する、というのは必要だしそれを最もイメージしやすいのは実機で動くモックですよ。
あんまり詳しくないのであれですが、プロトタイプツールだとレイアウトファイルに変換できるものもあるかもしれないのでそっちはAndroid Studioより使い勝手が良ければ使ってもいいのかもしんない。

だがExcel方眼紙、てめーだけはだめだ。...や、おれが知らないだけでF通とかがExcelをレイアウトファイルに変換するようなツール作ってるのかもしれんけど。

### 画面設計とDB設計は別物と考える

案外画面項目＝DBカラムみたいに考えてしまいがちなのでそこは注意するべき。
昔よく見たなーその手の設計。そのたびひどい目にあったっけ。
画面項目の変更に合わせてDB項目が毎日毎日朝令暮改でくるくる変わるとかもう二度とごめんです。

画面はあくまでViewであり、本質はドメインデータであることを忘れてはいけないし、ドメインデータがRDBにそのままマッピングできるものでもないというのも忘れてはいけない。
RDBはあくまでデータの永続化の一形態に過ぎないのでER図が必ずしも正とは言いきれないのですよ。
その辺クリーンアーキテクチャとかDDDとか参考にするべき話はいっぱい転がっているので勉強しないとなー（自戒）。

とりあえずデータに関しては、たとえばモバイルで集めたデータをどんな風に今後活用するのか、という視点まで含めて考えたいところ。
モバイルでデータを集めるというのはこれは容易にビッグデータになりうるので、それを分析して以後のビジネスにつなげるというのはちょっと面白そうだし挑戦してみる価値はある。
そういった未来図を描くのも仕事のうちなのだから、そのためにどんなデータ設計をすればいいのかを学ぶのは意味がある。とはいえここら辺はデータサイエンティストの領分に近づいていくわけだけど。

### 贅沢は敵

富豪的なプログラミングはできないものと覚悟してください。
だから言ってるでしょリソース少ないんだって。
作ったそばからインスタンスをGCに放り込むような真似は今すぐやめるんだ。

### MVVMを実現するための技術は積極的に使う

Databindを使うだけでもかなりいろいろと楽になります。
むしろ使わない奴がドMに見えるレベル。
「開発が楽になる＝保守が楽になる」なので、後の世のためにも積極的に楽をしていきたい所存。

# おしまい

とりあえず今んとこ言えるのはこんなところかなーと。
とにかく開発初期にきちんといろいろ整えておくことで、バグの発生やら手戻りやらを抑えられるので最初にパワーをかけるべきだし、いっそ要件定義と同時に受入テストのテストケースだって書いてしまった方がいいと思います。
後回しにしたっていいことなんて何もないしね。