TIME HACKER メイキング

TIME HACKERリリースしました!

img

TIME HACKERをめでたくリリースすることができました。
まだの人は是非この機会にお試しください!

今回は、TIME HACKERを作るにあたり、その制作過程について記載していこうと思います。
今回の記事では、

  • どんなUX思想で作ったのか?
  • 設計思想はどうしたのか?
  • アプリ実装面での設計は?
  • マネタイズについて

上記を、書ける範囲で載せましたので、 これからアプリを作ろうとしている人へは、制作過程の参考に、
同業者の方へは、苦難の共感が得られれば幸いです。

TIME HACKERを作ることとなった動機

時間が欲しい

世の中のサラリーマンの殆どがそうだと思いますが、とにかく時間が無い。
平日に、スキルアップのための勉強や、アプリ造りを行いたくても、家に着くのが日付をまたがる時間帯になる為、中々実施することができません。

休日にやろうと思うのですが、、いざ休日になったら平日の疲れを癒やすために、ガッツリ休んでしまう等、自分のやりたいことがやれない毎日でした。

もう社会人生活も10年を超えてきて、一向に改善しない毎日に諦めの気持ちすら抱いていた際に、一冊の本と出会いました。

ライフハック大全

ふと手にとった、以下の「ライフハック大全―人生と仕事を変える小さな習慣250」という本が私の中で革命的でした。

何個もあるライフハックは、殆どが私の血肉になる位に、良い知識を仕入れる事ができたのですが、その中でも、最も私の中でためになったのは、

自分の1日の行動ログを取って、無駄に過ごしているところは無いか?を見返すことで時間を捻出する術

これにものすごく感銘を受け、その時のツイートが以下。

実際にこのライフハックを実施してみました。
私は1日の中で、以下の時間をもっと取りたいと考えています。

  • 読書をして自己啓発と勉強
  • PCを使ってプログラムや新技術の勉強
  • 個人アプリ、ゲームの開発

この観点を元に、1日の行動ログを記録し、時間を生み出すことが出来ないか分析してみます。
(メモ帳に走り書きしていた為、時間が入っていたり入っていなかったりしてます。)

  1. 8:00 起床
  2. 出る準備 20分 8:20
  3. 家を出てからバスにならぶ 10分 8:31
  4. バス乗車時間 13分 8:45
  5. 電車待ち時間 16分 9:02
  6. 特急 30分 乗り換え後、○○から△△ 20分 計50分 9:50
  7. 以降会社
  8. エレベーター待ちと朝の準備 16分 10:06
  9. タバコ 5分
  10. インシデント対応 41分 10:53
  11. 今日のタスクプランニング 9分 11:00
  12. ○○ミーティング 24分 11:27
  13. トイレとタバコ 15分 11:45
  14. 今年度のプロジェクト目標について議論 15分 12:00
  15. 昼飯と移動 30分 12:30
  16. タバコ 15分 12:45
  17. 目標についての議論 15分 13:00
  18. 溜まっていたSlackやり取り 21分
  19. タバコ 15分 13:40
  20. 雑務 15分
  21. 新規企画のKPI試算 vol1 45分 14:40
  22. タバコ 10分
  23. 新規企画のKPI試算 vol2 48分 15:45
  24. タバコ10分
  25. 部下面談 36分
  26. タバコ 10分
  27. ○○チーム向けプレゼン資料作成 10分
  28. △△MTG 40分
  29. ☓☓MTG 1時間30分
  30. タバコと帰る準備 10分 19:30
  31. ○○まで移動 20分
  32. △△まで 35分
  33. ジムで運動 1時間
  34. ジムの風呂 30分
  35. 買い物 10分
  36. バス停まで移動 5分
  37. バス待ちとバス乗車 18分
  38. タバコ 5分
  39. 家移動2分
  40. 家に着いて落ち着くまで 7分
  41. ダラダラ過ごす 2時間
  42. 風呂とダラダラ 30分
  43. 就寝 1:17

この日を振り返って見ると、例えば、以下を改善できそうです。

タバコ時間を読書時間に企てる

タバコの時間をタバコ + スキルアップのための読書(Kindle)を行うとしたら、80分読書時間が確保出来ます。
全てのタバコの時間を企てるのは難しいのと、読書の開始時には思い返しの時間も必要な事を鑑みても、50分は読書時間が確保できます。

移動時間を読書・勉強時間に企てる

また、バスの時間がトータル31分。電車の時間は特急が65分、在来線が40分。
バスと在来線は基本立つので、ここを読書に当てると71分。

特急は座ることが出来ますが、片道30分程度なので開発するには時間が足りなく見えるので、PCを使った勉強時間に企てると、65分勉強時間が確保できます。

ここまで考えると、家に帰るまでに、以下の時間を確保することがわかります。

  • 読書時間を121分
  • 勉強に65分

ただ、この勉強・読書時間は断片化した時間なので、効率は悪いですが、それでも家に変えるまでに、これだけの事が行えるので、

家では、アプリ開発に集中することができる。いやアプリ開発だけしていていいのです。

これまでだと、「勉強もしないと」「本も読まないと…」と考えがよぎって中々集中出来なかったのですが、
一日の無駄な時間、スキマ時間に十分に勉強を行えているので、家でやる必要が無いのです。

そして、家でダラダラとする時間を2時間から半分削るだけで、1時間確保出来ます。
更にストイックに削れば1時間半〜2時間確保できるでしょう。

ここまで見てわかるように、

1日の時間を細かく記録する事と、分析する事は、忙しいビジネスマンに取って、ものすごく有益である

ことがわかります。

そして、有益で有ることがわかった次は、もっと楽に記録したい・分析したいと思い、今回の「TIME HACKER」アプリに繋がります。

私自身の生活の質を向上させるために、どうしてもこの手のアプリが欲しかったのと、私の中でしっくり来るアプリがStoreに並んでいなかったので、何としてでも手に入れたかった。

気がつけば、全ての開発や勉強を停止して、着手していました。

(なんだかんだで7ヶ月も造ってた…)


仕様検討

コアバリューを決める

いつもは凄い悩む所だったのですが、ここは作り出した動機が動機なので、すぐに固まっていました。

アプリ制作初期は

無駄な時間を管理し、自分のスキルアップに企てたい時間を確保する

で、最後までここは変わらなかったのですが、
もっと範囲を広げて、以下を最終的なコアバリューとしました。

自分の時間を管理し、生活改善のサポートをするアプリ

ターゲット層を考える

ターゲット層は、女性でも・男性でもありませんし、
特段ペルソナも考えていません。

TIME HACKERでは、以下のユーザーをターゲットとして捉えています。

  • 気づいたら時間ばかり過ぎている人
  • 忙しくて自分の時間が確保出来ない人
  • 自分のスキルアップの時間を確保したい人
  • 日々の生活をもっと有意義に送りたい人

UXを検討する

大体のアプリに言えることですが、
このアプリはUXが特に肝となります。

  • 何より、毎日、しかも小刻みにアプリを立ち上げて行動のログを計測しないといけない。
  • それには、ユーザーのアプリ上の動作だけではなく、生活のリズムを一瞬でも妨げてはいけない。
  • 特に、行動ログを記録忘れた場合は、一気に記録するモチベーションが下がります。なので記録忘れを防がなければならない。
    • (結局、ここのサポート部分は1stリリースからは見送りました。)

上記をいろいろ考えてUXを造っている際に、取っていたメモが以下です。

f:id:project-unknown:20180528223801p:plain

f:id:project-unknown:20180528223811p:plain

結局、当時考えていた機能の半分くらいしか実現できていないのですが…。

UIを検討する

ここもUX並にメチャクチャ苦労しました。
なんだかんだで、2ヶ月近く、あーでもないこーでもないをやっていたんじゃないかしら。

ちなみに、最初期の頃に考えていたUI

f:id:project-unknown:20180713010102p:plain:w400

全く違いますね…。
今見ると、個人的に結構しんどいUIですが、当時はこれでいける!!と信じて止みませんでした。
結局、2日位、寝かせてから再度この画像を見て、くっそだせぇって思って、やり直しました
その時の温度感だけで決めるのではなく、一度寝かせるのは大事ですね。

次に考えたのが、以下のUIです。
文字情報を見るのではなくて、行動をアイコン化し、なれたら無意識で記録ができる事を狙っています。
また、無意識で押せる事を狙って、アイコンも結構大きめに設定してます。

f:id:project-unknown:20180713010403p:plain:w400

だいぶ、今の原型が見え隠れしていますね。
ここから、紆余曲折を経て、以下の様な画面で落ち着きました。

f:id:project-unknown:20180713010500p:plain:w400

マネタイズを検討する

TIME HACKERで、現在実装済みのマネタイズをご紹介します。
今後のマネタイズは敢えて載せません。
お金の匂いがプンプンする機能が追加されたら、「あっ、マネタイズに走ってるな」とでも思ってください。

  • アプリトップにバナー広告
  • 一定の回数計測を行った際のインタースティシャル

バナー広告

バナー広告は、KeyHolderでも実装しているのと、KeyHolderでも操作の邪魔にならないところに設置していますが、結構馬鹿にならないくらいの収益を上げてくれます。
UXの所でも述べていますが、TIME HACKERは、UXがとにかく命です。ユーザの行動を阻害する事をしようものなら、記録が面倒になり一気に使わなくなります
なので、バナー広告を設置するにあたり、アプリの操作を阻害する事はしないような画面設計にしています。

インタースティシャル広告

KeyHolderでは、インタースティシャル広告を出さずに本当に公開しました。
というか、KeyHolderはシンプルを極めすぎてインタースティシャル広告を入れる余地が無く、入れようものならアプリとしての価値を大きく欠損しかねるので、断念しました。

なので、TIME HACKERではインタースティシャルは仕様検討の総初期から、なんとかして入れられないかを深く検討しています。
(書けば書くほど、金儲けが全面に出てしまうので、引かれるリスクはありますが、それでもこの記事を記載しています)

バナー広告の項でも記載しましたが、TIME HACKERは何よりUXが命なので、インタースティシャル広告を入れる箇所には最新の注意を払っています。

TIME HACKERでインタースティシャスは、一定の時間、一定の回数、行動ログを取った際に、行動ログを記録したタイミングで広告表示を行っています。
これは、ユーザーとして考えた際に、行動ログを計測する直前に広告が表示されたら、ユーザーの行動を阻害するリスクが非常に高まる為、記録を開始したタイミングで広告を表示することにしました。

行動ログを記録した後に広告を表示しているので、マネタイズとしての期待値は大きく下がると思いますが、私が考えている一番のリスクは、

眼の前の収益に目がくらんで、ユーザの行動を阻害する事で、アプリをアンインストールされる事を一番のリスクとして捉えています

また、上記で一定の回数と記載しましたが、初回リリースまでにどの回数が妥当なのか?の結論を出すことが出来ませんでした。

ですので、FirebaseのA/Bテストを採用して、インタースティシャル広告を出すタイミングの検証を行っています。

www.project-unknown.jp

ここまでは、アプリ設計のお話でした。
次に、実装面でのお話をしていこうと思います。

実装開始

さぁ、ここからお祭りの始まりです。
いやぁ…とにかく紆余曲折しまくった…。

プロトタイプ開発

今回のアプリ開発では、特に真新しい事を中心に、やりたいことは何でもやろうと思い色々tryしました。

大きい所で言うと、

Carthageにも挑戦しましたし

www.project-unknown.jp

Quickにも挑戦しましたし

www.project-unknown.jp

RealmSwiftにも挑戦しました

www.project-unknown.jp

Firebaseにメインの解析機能を移管しましたし、
Firebaseを使ってA/Bテストにも挑戦しています。

www.project-unknown.jp

以下の「Code Complete」等の技術書も読み漁り、開発設計についての色々な挑戦も行いました。

そして気づいたのが、

tryばっかしていて、いつまで経っても完成しない

特に、開発設計のところは、色々な本を読みすぎて、読む本全てに影響を受けて設計が日々変わりすぎていっているのが色々と足を引っ張りました。
こんなところにもエターナル現象は顔をだすんですね。

なので、プロトタイプとしてある程度のものが出来上がったタイミングで、tryは封印し、アプリ完成にフォーカスする事にしました。

以後は、アプリ制作時に大きな節目について記載します。

DBシステムの変更

これまでDBをRealmSwiftで開発していたのですが、
諸々の事情で、結局CoreDataに移しました。

RealmSwiftはCoreDataと違い、Objectを生成して値を突っ込むだけで物理領域にも保存され、直感的にデータを扱うことができる優れもので、開発当初はRealmSwiftを崇拝してやまなかったです。

しかし、

  • DeleteRuleが使えない
  • マイグレーション時に、意図しないデータが潜り込む
  • トランザクション範囲が操作し辛い

等、不満が次々と湧いてきて、最終的にCoreDataにデータを移管しました。

ココらへんは、ここに詳細を記載しています

ただ、RealmSwiftとCoreDataとでは、やはりアプリ設計が異なってくる為、ここを直すために、結構作り直しを余儀なくされました。

(それでもDAOを全て直す気力は無く、一部のDAOはRealmSwift前提とした設計のままになってしまっています)

アイコンをやっぱり全部自分らで造ることにする

開発完了が大きく遅れたのは、ここが原因です。ですがこれは英断だと思っています。

これまで、アイコンをフリーで提供してくださっているサイト様から使わせてもらうつもりでおり、完成直前までこれで行くつもりまんまんでした。

ただ、せっかく造るんだからアイコンも自作する事に決め、ぽぽたが泣きながら作業開始しました。

元々100を超えるアイコンを他サイト様のフリー素材から用意していたのですが、
流石に、この量を開発過渡期に用意するのは無理があったので、数を70ほどにしぼりました。

https://cdn-ak.f.st-hatena.com/images/fotolife/p/project-unknown/20180716/20180716161615.png
(作成したアイコン一覧)

この辺の詳細については、ぽぽたが詳細の記事に起こしています。

www.project-unknown.jp

始まるエターナル化

今回一番厄介だったエターナル化は、機能のエターナル化より、コードのエターナル化でした。
一つの機能を造る度に、4,5回リファクタリングを行ったり。
一度仕上げたコードを、設計しなおしたり。
自分が満足するまで何度も何度も作り直してました。

ただ、これって、

システムの保守性だけ上がって、いつまで経ってもリリースできなくなる自体を引き起こしていました

確かに保守性は非常に大事なのですが、とにかく時間がかかる。
プライベート開発なので納期を気にしないというのが更に拍車をかけてしまっていました。

塩梅を調整するのが本当に難しい…。
このリファクタリングも最終的には自分の中で最低限に抑えるようにしました。

例えば、以下の時だけリファクタリングを行うようにしています。

  • DRYを守れていない
  • SOLIDの原則に準拠していない
  • ViewからModelクラスの細かいメソッドにまでアクセスしようとした時

観点は以下です。


DRYを守れていない

似た機能が乱立した場合、開発過渡期になればなるほど、修正漏れによるさらなる不具合、進捗の遅れに響きます。
ここは徹底的に潰しました。
ちなみにDRYが有名になったのは、以下の「達人プログラマー」からですね。この概念は道を踏み外しそうになった際の羅針盤になり得る考えでいつも大いに助けられています。


SOLIDの原則に準拠していない

iOSライクなMVVMとかではなく、またはプロトコル指向でもなく、オブジェクト指向の1つの考えであるSOLIDをとにかく大事にしました。

プロトコル指向で統一したかった所はありますが、Swiftのプロトコル指向は熟成されていません。これを守るがあまりに無駄で汚いコードになりがちです(会社の現場でこれに囚われて、意味不明なコードを書くエンジニアを散々見ています)。

また、何でもかんでもMVVMを採用するのは愚の骨頂です。ただクラスを増やすだけで、自己満足だけ満たされるコードになるでしょう。
こういうのは適材適所であるべきです。

なので、SOLIDの原則だけを準拠することにしています。
これはDRYを包括している思想ですので、DRYルールと非常に相性が良い。

以下は、SOLIDの原則について記載しています。

  • S - 単一責任の原則 (Single Responsibility Principle)
  • O - 開放・閉鎖原則 (Open/closed principle)
  • L - リスコフ置換原則 (Liskov substitution principle)
  • I - インタフェース分離の原則 (Interface segregation principle)
  • D - 依存性逆転の原則 (Dependency inversion principle)

当たり前だけど、気がついたら守れていない原則ですが、ちゃんと守れている時の効果は絶大です。
このルールには非常に気を使いました。


ViewからModelクラスの細かいメソッドにまでアクセスしようとした時

これはSOLIDの一種ですね。
ViewからModelのデータをごにょごにょするのはイケていません。
その場はそれで良いかもしれませんが、後ほど似たようなデータアクセスが必要になる度にインタフェースを作る羽目になります。


終わらないローカライズ

TIME HACKERは日本以外の世界で発信しています。
細かく言うと、GDPRを受け、EU諸国を除いた全世界に発信しています。

アプリ内のローカライズは、元々ローカライズを意識した実装を行う癖があったので、さほど問題無かったのですが、
問題は、ブログに紹介やらヘルプやらをやたらと親切に記載してしまっていた為、これら全てをローカライズする必要ができました

いやぁー、これはアプリをリリースするのを辞めるか悩むくらい霹靂しました。
最後の1ヶ月間は、このローカライズを延々とやっていた気がします。
実際にアプリ以外のローカライズは以下を対応しました。

繰り返しますが、、

アプリのローカライズ以上に、このローカライズの方が遥かにしんどかったです

しかも、後述しますが、最終的にこの1ヶ月の作業は殆ど無駄になり、申請日にプロジェクトメンバー総掛かりで作り直してます。

最後の追い込み

具体的な日付だと、2018/7/15(土)にプロジェクトメンバーで集まり、
最終テスト、ヘルプページやプロモーションページの仕上げを行って、
夜までに申請を上げて打ち上げを想定していたのですが…、

相次ぐ不具合
まさかの、申請日にUI変更
UI変更に引っ張られて、全ての画像変更

が発生し、気づいたら申請したのは、2018/7/16(日)の夜でした…。
特に、UI変更が本当にしんどかった…。
これにより、具体的には、

以下の、ストアキャプチャ作り直し

英語版iPhoneX

f:id:project-unknown:20180716013728p:plain

英語版5.5 inch

f:id:project-unknown:20180716013744p:plain

日本語版iPhoneX

f:id:project-unknown:20180716013811p:plain

日本語版5.5inch

f:id:project-unknown:20180716013830p:plain

というか、最後の2日間、殆ど画像の差し替えしかやってない気がする…。


くらうリジェクト

今書いているブログ記事もそうですが、
申請を待っている間に、私含め、ぽぽたもTIME HACKER関連の記事を色々書き溜め、申請が通ったらアプリのリリースも含め、ブログ記事のリリースをするために待ち構えていましたが、ものの見事にリジェクトをくらいました

内容は

2. 4 Performance: Hardware Compatibility
Guideline 2.4.1 – Performance – Hardware Compatibility

iPadでの表示が崩れているから、ちゃんとUI整えろよというご指摘です。

実は、リリース前にiPadで表示が崩れる事を知っていましたし、Appleの審査する人はiPadで審査するということも知っていました。

(iPhoneアプリであっても、iPadに内蔵されているiPhoneシミュレータで動くべきであるという考えなので、私が知る限りでは、iPadで審査を行っていそうです。)

ですが、まぁ、操作できない事ないじゃんという謎の過信で、対応を見送っていたところを、案の定指摘されました。

もう、目も当てられない…。

こちら、OSSを使ってUI表現していた所だったので、ライセンスの問題もあり、手を加えるわけにもいきませんから、その場しのぎとして、表示崩れが発生する端末では、一部機能を削除して再申請しました。

初回リリースで諦めた事

たくさんあります。
本当にたくさんあります。

何故か申請日にiTunes Connectの調子が悪くて、iTunes Connectにバイナリアップロードするのに数時間かかった為、
心が盛大にポッキリ折れて、気づいていた簡単なバグはそのままにしてしまっていたり、

UXの検討の時に記録忘れ防止のための通知機能も、
通知タイミングを間違えたらユーザーの不満がものすごく上がりそうという、チキンハートがひょっこり顔を出して見送ったり、

本当に色々積み残しています。

ざっくりと列挙すると、以下の機能を初回リリースでは諦めています。

通知機能

上述した通りです

Apple Watch

Twitterに思いっきりApple Watch化すると記載しているのに、工数の兼ね合いという大人の都合で諦めてます。

Widget対応

大人の都合

分析機能の何点か

最終的にTIME HACKERの押しにしていきたいのですが、
まずは、ユーザーの行動ログを貯めることが何より優先すべき事だったので、ここの機能も結構諦めています。

アプリ内課金

やりたかった…。
本当にやりたかった…。
できなかった…。

KPT

締めくくりとして、今回のTIME HACKERのKPTを考えたいと思います。

Keep

自分の信念を最後まで貫いた

ライフハック大全を読んで、是非このアプリを使いたい、そして造りたいと言う思いを最後まで貫けたのは良かった。

このアプリは、万人受けするアプリではないという事はわかっています。
しかし、ターゲット層項目に記載した人に長く使ってもらう事だけを想定して造っています。

エターナル化を防いだ

本当はAppleWatch、Widget、分析機能の強化、Push等もっとやりたかったけど、これを全て捨てました。
初回リリースでは、ユーザーのログを貯めることを何より重要視し、それ以外の機能は二の次にしました
結果として、この判断を行わなければ、リリースは来年になっていたでしょう。

Problem

何でもかんでもやりすぎた

最低限の事だけしかやっていないつもりだったのですが、今考えると色々手を広げすぎたと思います。

特にローカライズはリリース後でも良かったかもしれません…が、iTunes Connectの仕組み上、プライマリー言語を最初から英語に指定していないと、後々更に面倒な事になっていたので、これでよかったのかもしれませんが…。

またヘルプやプロモーションはやりすぎました、これこそリリース後でも良かった。

至る所でチキンハートが顔を出した

RealmSwiftをやめたのも結局の所、チキンハートが問題でしたし、
チキンハートが顔を出したせいで、ハレーションを生みそうな機能を見送ったり、もっと強気に造っても良かった。

プロジェクトとして、集まって作業する頻度が少なすぎた

最近はリモートワークが流行っていますが、やはり対面でやり取りする作業だと、それぞれのクオリティ・速度が全然違います。

特に申請日に集まって、最後のテストを行った際の不具合の出方がやばかったです。
もうちょっと早めに集まってテストするなどすれば、問題の早期発見に気づけたでしょう。

明らかにリスクがあるとわかっていた不具合を放置した

最後のリジェクトの所ですね。
これは本当にもう愚かだったとしか言いようが無い。
面倒くさがって、対応を先送りにした結果としか言いようが無い。

Try

プロジェクトとして集まる頻度を増やす

これはProblemの裏返しですね、クオリティ・速度を上げる意味で、無理にでも集まって集中して造る時間を確保したほうが良いです。

チキンハートをどうにかする

なにかする度に、いや契約が…とかいや請求一気にきたら怖いしー…とか、
出す前にでもでもだってを発揮して、チャンスをことごとく逃しているのがとにかくもったいない。
やる前に後悔するなら、やって後悔するの精神を持とうと思います。

多少面倒でも正しいことをする

これは最後のProblemの不具合と気づいていて目を背けたものに掛かります。
結局バグの放置や不具合の放置は、問題の先送りでしか無いですし、別な言い方をすれば、ローンと同じで先送りにすれば金利(より面倒な工数)が増えるものとし、リスクがあるものに関しては、速攻潰していくマインドは持ち続けなければと痛感しました。

最後に

自分たちで言うのも変な話ですが、TIME HACKERは、自分の時間を生み出す為に有用なツールに仕上がっています。
また、ユーザーの声を聞いて、機能追加やアイコン追加も行っていこうと思いますので、気になる事などありましたら、いつでも、以下のフォームよりお問い合わせください!

TIME HACKER ご要望・お問い合わせ

是非、TIME HACKERを使って、毎日の生活を少しでも改善していきましょう!