Android 開発初心者, 2017年の開発を振り返る


&nbsp;
※ この記事は **[エキサイト Advent Calendar 2017](https://qiita.com/advent-calendar/2017/excite)** 15 日目の記事です ※

ごあいさつ
---

はじめまして [**ウーマンエキサイト**](https://woman.excite.co.jp/) エンジニアの[伊藤](https://qiita.com/sosuke-ito)です.

![ウーマンエキサイト](https://image.excite.co.jp/jp/woman/sp/images/logo-woman.png)

今年 僕は **[Android 版ウーマンエキサイトアプリ](
https://play.google.com/store/apps/details?id=jp.co.excite.woman.topics&hl=ja)**の担当となりまして
リニューアルバージョンアップを行うことになりました.

ほかには PHP でサーバー/フロントまわりを浅くやったりしています.
[*去年は JavaScript で遊んでました*](http://exdev.exblog.jp/27091041/).

今回はそんな **Android 開発初心者**が
リリースにこぎつけるまでに経験したことをお話したいと思います.


できたもの
---

結果から言いますと
なんとか 5月開発開始 → 7月にリリースをすることができました！

![ic_launcher.png](https://qiita-image-store.s3.amazonaws.com/0/149331/f61f7030-4b02-5d19-98dc-1a61d25f4abe.png)

https://play.google.com/store/apps/details?id=jp.co.excite.woman.topics&hl=ja

ウーマンの皆さんにはもちろん
**メンズのかたがたもぜひインストールしていただいて**
毎日の動物占いや記事を楽しんでください.

ちなみに僕は男性で

![Screenshot_20171214-184846.png](https://qiita-image-store.s3.amazonaws.com/0/149331/aed75d7a-12c6-1628-eedf-69fcaae135b7.png)
満月グループごろごろ組の黒ひょう です.


やりたかったこと
---

今回の開発にあたり 以下の目標を定めました (脳内):

1. **ややレガシー気味になっている既存コードを<br />
  モダン(だと思ってる)なものに置き換える<br />&nbsp;**
2. **`MVP` とか `MVVM` とかいい感じの設計にしたい<br />&nbsp;**
3. **リアクティブとかいい感じの設計にしたい<br />&nbsp;**
4. **現在一般となっている Android 開発のやりかたの全体像を掴む**<br />&nbsp;
5. **リリースする (あたりまえ)**

開発前の一番楽しい計画段階です.

やったこと
---

### 1. もともとのバージョンのコードベースをほぼすべて強行削除

<img width="1003" alt="もともとのバージョンのコードベースを強行削除" src="https://qiita-image-store.s3.amazonaws.com/0/149331/26c51b86-9579-c50f-feb8-3fa9c3f3a2fc.png">
*強行削除*

このアプリの担当になったときには
もう既に立派なアプリがありました.
(バージョンは `1.2.3` でした)

![Screenshot_20171214-203029.png](https://qiita-image-store.s3.amazonaws.com/0/149331/76cf925b-ca8c-ea75-a251-dc36e1787272.png)

しかしながら、メンテナンス等の問題があり
コードベースを新しくしたいという思いと
これを機にアプリのコード全体を独裁するために
既存のコードベースをほとんど削除することになりました.

<img width="416" alt="暴君" src="https://qiita-image-store.s3.amazonaws.com/0/149331/24871461-4c42-df9e-a461-d3184914746e.png">
*初心者なのにやることだけは暴君*

残ったものはビルド設定や
CI, 外部 API 設定くらいとしてしまいました.

(前のバージョンが好きだったかたにはすみません……
 しかしながら新バージョンで改良していきたいので
 ぜひご意見をください)

### 2. 他プロジェクトのコードからおいしそうなところを抽出

良くも悪くも真っ白なキャンバスになったので
その上に新たなコードを書ける状態になりました！

次に, エキサイトにあるアプリのプロジェクトは
もちろん Github Enterprise 上で自由に閲覧できるので

開発にあたって

- 他サービスの Android エンジニアのかたに質問
- 片っ端から他 Android プロジェクトのコードリーディング

を行いました.

プロジェクトごとに特色はいろいろありまして:

- MVP な設計 や MVVM な設計
- RxJava を使っていたり
- Realm を使っていたり Android-Orma を使っていたり
- ButterKnife を使っていたり DataBinding を使っていたり

さまざまな特徴があって
コードリーディングしているだけでも
非常に有意義な時間を過ごせました.

今回の開発には相当に他プロジェクトがあってのことで
開発初期の[巨人の肩に乗る](https://ja.wikipedia.org/wiki/%E5%B7%A8%E4%BA%BA%E3%81%AE%E8%82%A9%E3%81%AE%E4%B8%8A)部分が大きかったです.

---

最終的に

1. **他プロジェクトで使われているもの**<br />
  (多くのプロジェクトで使われているか)<br />&nbsp;
2. **自分の力量**<br />
  (StackOverflow 力, Qiita 力)<br />&nbsp;
3. **簡単にかけるか, 短くかけるか**<br />
  (開発期間と初期段階なので早く結果を出したい気持ち)

からライブラリや設計を決定しました.

<img width="674" alt="+" src="https://qiita-image-store.s3.amazonaws.com/0/149331/829562e4-665b-00a7-fb31-4fd0eff92416.png">
*これはノリノリでライブラリを追加する初期当初の僕のコミットです.*

### 2. 開発

紆余曲折の開発があったので
技術面については後述したいと思います.

### 3. リリース

開発が終わってしばらくのデバッグのあと
Google Play Developer Console の操作に戦々恐々としつつも
無事リリースができて
今ありがたく皆様にアプリをお使いいただいています.


つかったもの
---

今回の開発で使っている設計やライブラリのご紹介タイムです。

もし、同じく新たに Android プロジェクトを始める境遇のかた
いらっしゃったら参考になれば幸いです.

### [MVP](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter) な設計を目指す

アーキテクチャは [**MVP**](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93presenter) を採用しました.
というのも [MVVM](https://qiita.com/rmakiyama/items/779cf6407f70b40e4ee7) が知識不足で不安だったからです……

とはいえ, 他プロジェクトでも MVP を採用したものが多く
十分に枯れたしっかりとした実績があった事実と

[DataBinding](https://developer.android.com/topic/libraries/data-binding/index.html?hl=ja) や[リアクティブ](http://postd.cc/what-is-functional-reactive-programming/)の知識が求められる MVVM を
初心でいきなり採用するのに
自分の力量に不安なところがあったので
結果的に MVP でもまったく問題なかったと思いました.

とはいえ, 今後別のアプリを開発するとなれば
興味でも技術面でも MVVM を採用してみたいという気持ちがあるので
**設計に関しては鋭意見直していきたい**と思っています.

しかしながら MVP と主張していても
他のプロジェクトに影響されて
*[キメラ](https://dic.pixiv.net/a/%E3%82%AD%E3%83%A1%E3%83%A9)アーキテクチャ*になっている現在です.

### [RxJava](https://github.com/ReactiveX/RxJava), [EventBus](https://github.com/greenrobot/EventBus)

```groovy:app/build.gradle
dependencies {
    implementation 'io.reactivex.rxjava2:rxjava:2.1.1'
    implementation 'io.reactivex.rxjava2:rxandroid:2.0.1'
    implementation 'org.greenrobot:eventbus:3.0.0'
}
```

この2つは非同期なデータないしイベントを扱うために導入しました.
(EventBus は RxJava だけでも代用できると思います).

[RxJava](https://github.com/ReactiveX/RxJava) に関していうと
学習コストはヒマラヤのように高いものでした.

![mount-everest-413_640.jpg](https://qiita-image-store.s3.amazonaws.com/0/149331/8cb5e461-7db0-7c8d-5fa6-34bea657df36.jpeg)
(https://pixabay.com/photo-413/)

が, アプリとなるとやはり
**スレッド間の操作**や **UI イベント**, **ネットワーク処理**のような
一筋縄ではいかない非同期処理があるので
多少時間をかけてでも導入することにしました.

採用してみて感じたのは
非常に**多くの場面で有用**で

コードを書いていて非同期の処理を
**同期的にチェーンしていけるのは爽快**です.
(JS の `Promise` に慣れている人は似たものを感じると思います).

API, DB の操作から UI 処理まで
**あらゆる非同期処理に活用できた**ので
**プロジェクトには欠かせない存在**だと思いました.

### [Retrofit](http://square.github.io/retrofit/) + [Gson](https://github.com/google/gson) + [Okhttp](https://github.com/square/okhttp)

```groovy:app/build.gradle
dependencies {
    implementation "com.squareup.retrofit2:retrofit:2.2.0"
    implementation "com.squareup.retrofit2:converter-gson:2.2.0"
    implementation "com.squareup.retrofit2:adapter-rxjava2:2.2.0"
    implementation 'com.squareup.okhttp3:logging-interceptor:3.0.1'
}
```

REST WebAPI との通信のために導入しました.

[Retrofit](http://square.github.io/retrofit/) は [**RxJava と連携できる**](https://github.com/square/retrofit/tree/master/retrofit-adapters/rxjava2)ので
RxJava を採用したメリットが活きました.

`Interceptor` よる拡張も簡単にできるので
**通信状況を判断して例外を投げたり**や
**API 共通パラメーター**を差し込んだりするのも容易です.

加えて [Gson](https://github.com/google/gson) による [`POJO`](https://ja.wikipedia.org/wiki/Plain_Old_Java_Object) 変換は
モデルクラスをすっきりとさせて
各レイヤーの結合を疎にしてくれます.
(もちろん Gson 以外も使えます)

### [Android-Orma](https://github.com/maskarade/Android-Orma)

```groovy:app/build.gradle
dependencies {
    implementation 'com.github.gfx.android.orma:orma:4.2.5'
    kapt 'com.github.gfx.android.orma:orma-processor:4.2.5'
}
```

[Android-Orma](https://github.com/maskarade/Android-Orma) (以下 Orma) は O/R マッパーで
アプリ内 DB でのデータの永続化のために導入しました.

Orma の素晴らしい点は数多くありますが
[Orma でも **RxJava と楽々使える**](https://github.com/maskarade/Android-Orma#rxjava-integration)ので
ここは大きなメリットです.

モデルクラスを定義しておけばよしなに変換してくれて
SQL を意識することがないという
O/R マッパーの利点は開発の容易さに欠かせません.

自分が定義したクラスであっても
[タイプアダプタをつくることでシリアライズ/デシリアライズできる](https://github.com/maskarade/Android-Orma#type-adapters)ので
DB のデータ型に縛られずモデルクラスをドメイン内の型で
わかりやすく記述できるのも大きなメリットだと感じました.

### [Kotlin](https://kotlinlang.org/)

説明は要らないかもしれないですね.
[晴れて Android の一級市民となった Kotlin](https://android-developers.googleblog.com/2017/05/android-announces-support-for-kotlin.html) です.

開発開始時には**まだアナウンスされておらず**
Java で書いていました.

しかしその後の機能追加時に公式アナウンスされたのを皮切りに
**他のプロジェクトでも使い始めたのを見て導入**しました.

Kotlin のメリットは数多くあると思いますが:

- 全体的にショートコーディングに向く
- [リスト処理](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.collections/index.html), [スコープ関数](https://qiita.com/ngsw_taro/items/d29e3080d9fc8a38691e)の使いやすさ
- [エクステンション](https://kotlinlang.org/docs/reference/extensions.html)による拡張性
- [Java との連携が容易](https://kotlinlang.org/docs/tutorials/mixing-java-kotlin-intellij.html) (JVM のメリット！ 罠もありますが)
- 書いてて楽しい

といったところがあるなと感じました.

### [Spek](http://spekframework.org/)

これは導入していないんですが
Kotlin のテストフレームワークの [Spek](http://spekframework.org/) が
BDD っぽくて (※) 使ってみたかったですね.

誰も使っておらずで導入を見送りました…
結局, 安定の JUnit を使っています.

--- 

※ 余談で [Spek の FAQ では BDD でも TDD でもない](http://spekframework.org/docs/latest/#_faq)ようです

> #### Q: Is Spek a BDD or a TDD framework?
>
> Spek in Dutch means Bacon, so you could think of it as a Bacon Driven Development framework. Being serious for a moment though, we (at least the original author) believe that there is a false distinction in frameworks around what TDD or BDD is. Unit tests are ultimately about defining the specifications of your system. As such, Spek is merely a specification framework if it can be called anything. For more information read [What BDD has taught me](http://hadihariri.com/2012/04/11/what-bdd-has-taught-me/).

&nbsp;

> #### Q: Spek って BDD とか TDD のフレームワークなんですか？
>
> Spek はオランダ語でベーコンって意味なので, ベーコン駆動開発のフレームワークとでも思ってくれればいいです. ちょっとマジな話をしますが, 私達 (少なくとも元々の作者)は TDD やら BDD やらはこういうもの, っていうのは間違ったフレームワークの区別だと思っています. ユニットテストっていうのはざっくりいうと, システム仕様を定義することです. とすると, Spek は呼ぶとするなら単なる仕様定義フレームワークということになります. もっと知りたければ [BDD が教えてくれたもの](http://hadihariri.com/2012/04/11/what-bdd-has-taught-me/) を読んでみてください.

### その他

- [Dagger2](https://github.com/google/dagger)
- [ButterKnife](http://jakewharton.github.io/butterknife/)
- [Picasso](http://square.github.io/picasso/)
- [Mockito](http://site.mockito.org/)
- [Robolectric](http://robolectric.org/)

等々…

多くのプロジェクトで使われているものを
使うことができたのかな, と思っています.


反省点
---

反省点としては他プロジェクトのコードレビューをしていて
実は「あ、よさそう」で設計や技術を変えたりしたので
キメラアーキテクチャになってしまったことや

深く理解せずに使っている部分もあるので
もっとよい使い方や, 正しくなく危ない方法を採用していたりしないかと
不安な部分があるということです.
(特に RxJava, ライフサイクルまわり)


感想
---

良くも悪くも1人プロジェクトで独裁政権であったので
自由に技術の選定ができたのと
全体を把握することでまんべんなく学習することができ
とても有意義な開発であったと振り返ります.

いろいろ考えると今回のようなワンマン設計/開発では
満足にいかない部分もあると思われるので
ここは今後意識して改善すべきだと思っています.

現在は少し大きめの機能追加を予定して目下開発中です.
一年ちょっとやってみてやっと開発のやりかたがつかめてきた感触がしてきました.

以上, お読みくださりありがとうございました！
勉強会等でお会いする機会がありましたらおきがるにお声がけいただけると嬉しいです.

---

**[エキサイト Advent Calendar 2017](https://qiita.com/advent-calendar/2017/excite) はまだまだ続きます.**
明日の記事は 「**Pythonでの画像処理API**」ですね.
楽しみです！