気軽に参加しやすいモバイルアプリ開発環境を育てる3つのこと

こんにちは、 [freee Engineers Advent Calendar 2016](http://qiita.com/advent-calendar/2016/freee) 10日目担当の @laprasDrum です。
最近社内で付けられた呼称に基づき「らぷらぷ」と呼ばれる日々です。

今回はスタートアップによく見られるモバイル開発の悩みと freee のモバイルチームでの実践法について知見共有できたらと思います。

---

# 少数精鋭から始まった後の話

知らない方もいらっしゃると思うので、まずは freee がリリースしているモバイルアプリについてカンタンに説明します。
現在 freee には2つのアプリをリリースしています。

- 会計 freee
    - [iOS](https://itunes.apple.com/jp/app/kuraudo-hui-jisofuto-freee/id811207074?mt=8): 2014年2月にリリース
    - [Android](https://play.google.com/store/apps/details?id=jp.co.freee.freee&hl=ja): iOS の1ヶ月後にリリース
- freee for チーム
    - [iOS](): 2015年10月にリリース
    - [Android](): iOS と同時リリース

プラットフォームを分ければ 2 x 2 = 4つのアプリを運用しています。
開発メンバーですが、初期からメンバーの立ち代わりはあるものの、新規開発・運用・保守含めメインエンジニアは基本2, 3人で回しています。
**メイン**と付けたのには理由があり、freee の開発者にはサーバーサイドやフロントエンド分け隔てなく開発する者が多く、モバイルの領域もその対象になっているからです。

# 社内でモバイルアプリ開発者を増やしたい

採用は別途進めるものの、やはり社内でプロダクトを触れる同僚を増やしていきたいという気持ちは加速させて実現したいですよね。
中には以前モバイルアプリ開発をされていた方もいますが、多くは「Storyboard…?」「Java は書いたことあるけど…」「リリースってどうやるの…?」など開発における基礎のキャッチアップが必要な状態がほとんどです。

そのような人でも、**モバイルアプリ開発に対する不安を和らげつつ開発実践してお客さんに価値を届けられるようにする体制**を実現するためのアプローチをいくつか紹介します。

# 1. iOS/Android のアーキテクチャ統一
**iOS 版を読み書き出来るようになれば Android 版も読み書き出来るように、逆も然りの状況を作るため**、基本的な設計思想は統一することにしています。

構成をルール化することで、新規機能作成時にどういうクラスをどういう Group / Package に切るべきかある程度迷わずに開発できるでしょう。

「であれば Xamarin や libGDX、Sencha Touch などのクロスプラットフォームでいいんじゃないの？」という疑問もあるでしょうが、導入するに当たって熟考すべき点が2つあります。

**1 同僚が開発参加しやすい & キャッチアップを続けやすいものであるか**
言語が統一されるということを考えると工数圧縮できるポイントはありますが、コミュニティの持続性を含めたキャッチアップは必要になります。
その場合、Apple や Google などの一次情報の他、国内・海外ブログよりも、**その技術情報が探しやすく最新の情報が集まりやすい**かどうかも検討しなくてはなりません。

弊社の同僚にそこまでの調査負荷を掛けたくないので、この時点で見送りになっています。

**2 得たかったのは秩序と DRY**
クロスプラットフォームを調べたくなる源泉に「同じロジックを2度も書くのは御免だ」というのがあるかと思います。
しかしながら、ニーズに依ってはクロスプラットフォームが出力したプロジェクトファイルをよしなに後処理しないとうまくいかないシチュエーションはあります。
特にプロジェクトファイルの構成がベンダーロックされている iOS 開発においては `xcodeproj/project.pbxproj` をゴニョゴニョしたいなんてシチュエーションを経験されているのではないでしょうか。

同僚にそんな辛い思いをさせたくないです。
現行及び未来のメインエンジニアにとっても辛い世界になるのは避けたいのです。

## 会計 freee

初期より MVVM + Rx で構成されています。
iOS は [ReactiveCocoa](https://github.com/ReactiveCocoa/ReactiveCocoa)、Android は [RxJava](https://github.com/ReactiveX/RxJava) を採用しています。

![image](https://qiita-image-store.s3.amazonaws.com/0/7950/7ab348bc-2ffc-cf0c-31aa-fccc4165b2cc.png)
<iframe src="//www.slideshare.net/slideshow/embed_code/key/rbXXO2j23De3HI" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/yo_waka/reactivecocoa-tokyo" title="freee社でのReactiveCocoa活用例" target="_blank">freee社でのReactiveCocoa活用例</a> </strong> from <strong><a target="_blank" href="//www.slideshare.net/yo_waka">yo_waka </a></strong> </div>

![image](https://qiita-image-store.s3.amazonaws.com/0/7950/963031e5-4d2c-98f0-4cc9-b603b2d5caae.png)
<iframe src="//www.slideshare.net/slideshow/embed_code/key/Mhq837K33iBTho" width="595" height="485" frameborder="0" marginwidth="0" marginheight="0" scrolling="no" style="border:1px solid #CCC; border-width:1px; margin-bottom:5px; max-width: 100%;" allowfullscreen> </iframe> <div style="margin-bottom:5px"> <strong> <a href="//www.slideshare.net/yo_waka/rxjava-night" title="RxJava on Android" target="_blank">RxJava on Android</a> </strong> from <strong><a target="_blank" href="//www.slideshare.net/yo_waka">yo_waka </a></strong> </div>

## freee for チーム

![image](https://qiita-image-store.s3.amazonaws.com/0/7950/f59a06b5-6584-bc37-830a-8c46a3b00fe6.png)
[ネイティブアプリでもFluxしたい by yonekawa](https://speakerdeck.com/yonekawa/neiteibuapuridemofluxsitai)

MVVM でプロジェクトを回してみて直面したのが双方向バインディングです。
Model と View の状態の並行管理が辛くなり、記述が次第に膨らみ、複数の Model を一度に扱うことになる画面ではあっという間に Fat ViewModel が出来上がってしまいます。
その解法として弊社が採用したのが Flux です。

個人的な思惑として、WPF 開発における MVVM でも View のアクショントリガーとして command が用意されていますが、あれを Action というレイヤーに逃がすことで既存の ViewModel は Action と Store に責務分割できるのではないかなと考えていました。

iOS では @yonekawa が作成した [SwiftFlux](https://github.com/yonekawa/SwiftFlux) を利用することで実現しています。
一方 Android ではガッツリとライブラリ化してるわけではないですが簡易的な Action / Store / Dispatcher を実装しました。
完璧な Flux を実現することではなく、上記の思惑が正しいかどうか、そのメリットは享受可能かどうかを検証するためです。
結果としては納得できる良い結果でした。

まだ Redux も考慮されていなかったので、Reducer まわり含めどうすべきかなーというのは検証中です。

# 2. コンテキストスイッチの低い言語選定

会計 freee が Obj-C (今は Swift との Mix-in) / Java に対して、for チームは初期から Swift / Kotlin の組み合わせです。
当時の Kotlin のバージョンは M8~9 ぐらいで先も読めない感じでしたが、積極的に採用した理由として、

- Obj-C から Swift 移行時に欲しかったと考えていた特徴が共通していた
    - extension
    - nullable operator
- 100% Java Compatibility なので、会計 freee の資産を活かせる
    - **最悪撤退すべきだなと思ったらいつでも撤退できた**
- JetBrains 自体の熱量の高さ
    - Android Studio との連携も手厚い
- 2015年1月の段階で Jake Wharton が調査ログをまとめていた
    - [Using Project Kotlin for Android](https://docs.google.com/document/d/1ReS3ep-hjxWA8kZi0YqDbEhCqTt29hG8P44aA9W0DM8/edit)
- **自分で一通り書いてみたところ、Swift プロジェクトが読み書きできれば Kotlin プロジェクトもほぼ読み書きできると感じた**

などが挙げられます。
上述したアーキテクチャの話と合わせて、同僚にすぐキャッチアップしやすい & フォローしやすい環境を考慮した結果です。

# 3. 気軽に相談しやすいインタフェースの提供

弊社の Slack Channel に "mobile-do-jo" というものを開設しました。
基本的には、初学者が気軽に質問したり、言語やIDEにまつわる基礎情報や初学者向け勉強会の情報を流しています。
中には同僚と飲んでるうちに「モバイルやってみたいんですよ―」と相談され、その場で「やりましょう」の一言と do-jo invite まで進み、実際に機能開発まで進めている方もいます。

最初のうちは「何で躓いているか言語化しにくい状況」というものが多々あるので、困ってそうな方がいれば**問診**と称して雑談しつつ直接見てあげるようにしています。

---

いかがでしたか。
今回はモバイルアプリ開発初心者が気学にスタートできる環境を用意するとともに、モバイルチームのメインエンジニアの欲求にあたる技術的挑戦を同時に達成するための回し方を紹介しました。

ちょうど同じ悩みに行き着いていた方や、これから採用を頑張っていこうとしているチームへの一助になれば幸いです。

freee では[お客さんも同僚も幸せにするためにプロダクト開発と技術的挑戦の両刀で攻められるエンジニアを大募集しています](https://jobs.freee.co.jp/)。
気軽にオフィスツアーも体験できますので是非一声掛けてくるとうれしいです。

さてさて明日の担当者ですが、日々自己研磨に勤しむ闘争氏こと @toshi0607 が思いを綴ってれるそうです。
去年は[営業職からエンジニアまで登りつめた闘争話](http://qiita.com/toshi0607/items/17218329314f1ed063ef)を紹介してくれましたが、今年はどんな成長を見せてくれるんでしょうか。
お楽しみに :smile_cat: