画像は開発中のアプリです。開発を始めてから4か月が経過し、辛うじて基本機能が動くかな、と言えるレベルになりました。紅茶を飲みながら、ここに至るまでの過去を振り返ります。
進捗の話
まずは進捗について。働きながらではありますが、今の完成度に達するまで4か月もかかるとは思っていませんでした。とはいえ、1か月で完成させるぞ!という目標があったわけでもありません。初めてのスマホアプリ開発、初めてのReactNative、初めてのRedux、初めてのDDDといろいろ手を広げていたので、実は妥当だった可能性すらあります。実際、Gitのログを見てみると「そうそう、この時はこれが必要だった」と思えるものばかりです。その時持っている知識で開発をし、改善できそうな余地があれば新しい技術を調査・学習していました。
進捗が早いのか遅いのか、遅いならどのくらい遅いのか、定量的な答えが用意できていないのは問題です。現在の進捗をうまく説明できないのは、完成形がイメージできていないからでしょう。作りながら要件を探していく開発スタイルでは、なかなかゴールに到達しません。一応、なるべくやることを増やさないように気をつけていましたが、やると決めたことは正しくやるために時間をかけていました。
一応、脳内にある開発要素を分類してみると
- UI (デザイン)
- UI (UX・アニメーション)
- UI (基本操作)
- モデル (基本操作)
- モデル (付加価値)
- フレームワーク (共通部品)
と分類できそうです。共通部品の開発や基本操作の実装が一息ついていること、UIは極力後回しにしたこと、付加価値の実装はまだ行っていないことを考えると、作業量を等分配したとしても進捗率は20%でしょうか。となると、単純計算であと1年半くらいかかる計算になります。ただ、4か月の中には開発に関係のない時間がたくさん含まれています。例えばmobXをやめてReduxを採用したり、mobXのアノテーションでぐちゃぐちゃになりかけていたmodelを分解したり、Entity/Factory/Service/InfrastructureといったDDDの設計要素を取り入れたり。仕様変更したときに変更する箇所は増えましたが、機能追加は以前よりも容易になりました。半分の9か月あれば納得のいく品質のソフトが完成する・・・という希望的観測を持っています(ただし、寄り道をしない場合)。
ソフトウェアメトリクス
進捗率や生産性などを見積もりたいのですが、何をすればいいのかよくわかりません(ソフト屋として働いているのにね!)。ただなんとなく、ソフトウェアメトリクスが鍵となるような気がしています。例えば実装要件に対する残件の割合だったり、コード行数や増分、テストのカバレッジといった情報は進捗を測るための情報になります。見えないものは制御できないと言いますしね。
思い返せば、ソフトウェアの品質管理やプロジェクトマネジメントについては全然実践してきていませんでした。技術検証や設計は楽しいものですが、たまには立ち止まって計画を振り返ったり、ソフトウェアの品質管理をするのも大事だなと感じています。(でも実作業と管理の両立は大変です)
設計の話
主にやったことと、それでもまだ困っていることについてです。
はじめに、mobXをReduxに切り替えました。当時、プログラムのあちこちにmobXの@actionや@runInActionが使われていました。モデルの変更をビューに反映させるためにmobXでModelを実装し、ステートを変更するメソッドを@actionにしたからです。これは失敗でした。ビューとモデルが密に結合し、気が付いたらビューを更新するためだけの機能がモデルに実装されていたりしました。そこでモデル周りを修正することにしました。
mobXだろうがReduxだろうが、やりたかったことは「データの更新をビューに反映させること」です。そのあたりを隠蔽して簡潔に書けるmobXよりも、明示して書けるReduxの方が初学者にとっては有用だと判断しました。
Reduxを採用するにあたり、Reduxの責務を「データを受け取ってビューに反映させること」だけにしました。具体的には、Redux-thunkの採用を見送りました。Redux-thunkを使うと非同期のActionを定義できて便利に見えますが、ようはReduxに非同期処理の解決の責務を押し付けているだけにすぎません。「データの更新をビューに反映させる」という主目的からは外れていますし、非同期処理のエラー処理とかも考えたかったので、非同期処理はアプリケーションで面倒を見ることにしました。ちなみにこのルールを守れるならmobXでも理論上は同じように書けますが、Reduxの方が自由度が低くて簡単です。
モデル周りの修正の第二策としてDDDを勉強しました。別にDDDを実装する予定はなかったのですが、単体テストを実装するためにレイヤードの概念は既にあったので、あとはDDDの流儀を参考にモデルを整理するだけでした。現在も勉強中です。
データベースのテーブル操作はDAO(Data Access Object)に任せています。ReactNativeで簡単に使えそうなORMライブラリを見つけられず、データの入出力だけでなく集計や分析もしたかったのでDAOを採用しました。DAOを作ったのは初めてですが、なかなか厄介だと分かりました。1つのテーブルに対する入出力は簡単ですが、テーブルの正規化によってテーブルが複数に分かれると、入出力のパラメータが必要な場合・必要でない場合に分かれるため、一気に扱いづらくなりました。データを読み取るときも、テーブルをJOINするのか、2回クエリを発行するのか、どうすればいいのか現状答えを持っていません。DAOは複数テーブルを扱うのが苦手だという見解ならどこかで見つけました。データベース設計についてもあまり勉強したことがないので、また近日に。