will and way

ただの自分用メモを人に伝える形式で書くことでわかりやすくまとめてるはずのブログ

Androidのコードを書く前にコーディングに集中できる状態を作る

はじめに

この投稿はAndroid その3 Advent Calendar 2016 - Qiitaの5日目の記事です。

4日目はkimukouさんのrealm-gradle-plugin 2.2.1 と Android Realm Browserでした。
6日目はkimukouさんの2016年末のAndroidでのSSL対応に関してです。

Androidのコードを書く前にコーディングに集中できる状態を作る

今年のAdvent CalendarはAndroidでKotlinを導入する話がかなり多くて、Kotlinが浸透しているんだな〜と感じています。
かくいう私もKotlinを使ってみた所感やテクニックのネタを考えてたんですが、Kotlinは愚かAndroidを本格的に開発し始めて2ヶ月ですので、エキスパートな部分は先人達にお願いするとします。

最近異動して、0からのプロジェクトに携わらせてもらっていて、コードを書く前に環境を整えることを最初にやりました。その時のまとめになります。

目次

  • なぜやるべきか。ずばり何をするのか
  • 命名規則, Code Style
  • プロジェクト構成, BuildType/Product Flavor, DI
  • データ層からプレゼンテーション層のサンプル実装
  • CI
  • プルリクのルールを作る
  • 必ず使うSDK, ツールの導入
  • テンプレートコード・スニペットをつくる
  • 開発環境のプロビジョニングをつくる

なぜやるべきか。ずばり何をするのか

プロジェクト初期になぜやるべきか。
先に決めて開発期〜リリースの間にコーディングに集中できる環境があると、エンジニアの精神衛生が良い状態が保たれるからです。 そして、プロジェクトが発足したての頃は仕様が 無い or 部分的 or 一朝一夕で変わるが当然なので機能実装以外に時間を割く時間が作りやすいです。

ずばり何をするのか。
ルール化自動化です。
プルリクを前提とした開発では、コードレビューのコストを大幅にされるでしょう。ルールと自動化をメンテしましょう。コードレビューで主観的(書き方の好み)な議論をするのは楽しいですが開発スピードとのトレードオフになります。世に出ていないサービスはスピードの方が重要でしょう。

では、さっそく各項目について、まとめをつらつらと書いていきます。

命名規則, Code Style

命名規則

大雑把なルールを作り、必要になったらルールを追加していきます。

接頭辞 or 接尾辞

リソースは接頭辞ベース、クラスは接尾辞ベース
Android Best Practices#Resourcesをベースにすると良い。日本語にも翻訳されています。

レイアウトの変数に名前をつける

レイアウトの変数名に概念や機能性をもたせることで、デザイナーと列挙された数値の共通認識をもつことが出来ます。 Androidはldpi(x0.75)を考慮して4の倍数でレイアウトをする必要があるので、そこだけ3dpみたいなことは極力避けたいです。

現在のプロジェクトではマージンやパディングの数値(4, 8, 16, 24)にspacing_s, spacing_m ... と名前をつけてます。

フォントのサイズにはHTMLのタグ名を参考にすると良いかもしれません。
title, header, body, paragraph ...
コンテンツの優先順位でフォントサイズを変えるということが直感的になります。

※ルール化することでデザイナーの発想の範囲を狭めることがあります。

Code Styleをととのえる

スペースや改行は好みが分かれるので、先にルールを決めるのがいいです。
Code StyleはAndroid界隈の神らしい、Jakeが在籍するSquareのコードフォーマットを拝借しましょう。

フォークして微調整してプロジェクトのルールとするのが手っ取り早いです。Google Java Style Guideをベースにチューニングします

プロジェクト構成, BuildType/BuildVariants, DI

プロジェクト構成をつくる

いわゆるアーキテクチャです。MVP/MVVM/MVCなどのパターンから、どれで実装していくかを決める必要があります。

BuildType/Product Flavorを追加する

ビルドタイプを分ける(Debug, Release)
  • ロギングの切り替え(コンソールログ/クラッシュログをサーバーに転送する)など
環境を分ける(development, staging, production)
  • Endpointの切り替え
  • アプリアイコンなどのリソースを環境毎に変える
  • KeyStoreの切り替えをtaskに含める

DIを導入する

上記のアーキテクチャとビルドタイプを統合した構成を考える必要があります。 勘所はAPIのエンドポイントやログ、モックデータを返却するAPIなどを切り替えられるように意識しましょう。

例えば、Retrofitを使っているプロジェクトでdebug/release毎にRetrofitのインタセプタのDIの戦略を変えるというような事です。 debug時だけloggerのインタセプタのDIを有効にしてAPIアクセス時のに詳細なロギングをするといったことが可能です。

現プロジェクトではDIにDagger2を使っており、インスタンス戦略は

  • Context(Application)スコープ
  • View(Activity/Fragment)スコープ

の2つに着地しています。Contextレベルなのはドメインレイヤーから下です。

データ層からプレゼンテーション層までの一気通貫サンプルを実装する

プロジェクト構成が出来たら、その構成が本当に使いやすいか検証する必要があります。自分で実装してみるのが一番です

サンプル実装でマニュアルも同時に終わらせることが出来ますし。そして、Android初心者な私にとって一気通貫させるのは実装イメージを沸きたてるにはベストでした。

CIを導入する

とりあえずFastlaneを導入してFastfileで各環境のビルドをできるようにしておくことが重要。

Gemfileも定義して、bundle exec fastlane [ENV] type:Debugくらいのコマンドでビルドできるようにしておけば、Circle CIを導入してもdeploymentディレクティブでの細かな設定が不要になります。

実際に運用しているのは

  1. Circle CIでbundlerをつかってfastlaneをフック
  2. ターゲットとなる環境のアプリをビルド
  3. Crashlytics Betaにアプリをポストし、テスターグループにアプリを公開
  4. Slackにビルド完了通知

Fastfileにはフローを定義し、Contextにプロジェクト情報を埋め込む形に着地しています。

※FastfileはBuildType, BuildVariants, Keystoreの設定と合わせる必要があります。

プルリクエストルールを作る

前のプロジェクトのチームのプルリクにはルールが定められていて、1年以上つづけていて、とてもよかったたので概要を紹介。

  1. プルリクのフォーマット化
    1. 概要、バグフィクスの原因など
    2. 目的やアクションを記載する(仕様を含む、編集の意図をソースコードから汲み取らない)
    3. 修正の影響範囲がわかるURLを含める(開発ロードマップやCSのバグチケ)
  2. UI変更はBefore/Afterのスクショ必須
  3. インタラクションならGIFアニメ必須

詳細は割愛します。Cookpadさんの開発速度を上げるための Pull-Request のつくり方に近いです。

必ず使うSDK, ツールの導入やリスト作成する

仕様にかかわらず必要となる機能やツールは少なくとも決まってるので時間があるときに導入だけしておくことで、終盤で導入して急遽Multi Dex対応が必要になるみたいな事が減らせると思います。

  • 認証(Firebaseなど)
  • ログ/解析(Timber, Crashlytics, Google Analytics)
  • デバッグ(Stetho, Crashlytics, leakcanary, Pidcat)
  • 時間(Three-Ten)
  • 暗号化(conceal)
  • βテスト(Crashlytics)
  • ORM(ormaなど)
  • Parcelable Generatorなどのプラグイン導入

テンプレートコード・スニペットをつくる

Dagger2を使う場合にはComponent, Module, Scopeを大量生産するでしょう。
IntelliJにはファイルテンプレート機能があり、予めApache Velocityのフォーマットに従った形式でソースコードを書いておけば、ファイルの新規作成時に選ぶことが出来ます。 テンプレート化によって、フレームワークを使うときのフットワークを軽くすることが出来ます。

#if (${PACKAGE_NAME} && ${PACKAGE_NAME} != "")package ${PACKAGE_NAME}

#end
#parse("File Header.java")

import javax.inject.Scope
import kotlin.annotation.AnnotationRetention.RUNTIME

@Scope
@Retention(RetentionPolicy.RUNTIME)
annotation class ${NAME}

開発環境のプロビジョニングをつくる

AnsibleでAndroid SDKのインストールを図る。

Android Studioがよしなにやってくれることも多いので、ツール群の導入くらい。

まとめ

プロジェクトを始める発射台となるような手順をまとめた。とにかく最初は開発しやすいように、大雑把なルールや開発を加速させる周辺を整える事が重要。

そして、ユニットテストやUIテストの導入がまだできてないので、これからやりたい。

あわせて読みたい

blog.matsuokah.jp