こんにちは。 Androidエンジニアの @syarihu です。 私が入社したのは2017年10月で、入社してから約1年半以上が経ちAndroid開発周りの環境がだいぶ良くなってきたなあと感じています。 そこで、今までやってきたことの振り返りを書いていこうかなと思います。
syarihuが普段やっている業務
はじめに、私が普段何をやっている人なのかを紹介します。
私はPFM本部のサービス開発部というところに所属しています。 基本的には マネーフォワード MEのAndroidアプリ開発 を主に担当していますが、全社的に関わることもときどきやっています。
マネーフォワード MEのAndroidアプリ開発
私が普段マネーフォワード MEのAndroidアプリ開発周りでやっている業務を箇条書きにすると次のとおりです。
- 機能開発
- 技術的負債の改善
- 開発環境整備
- 開発・運用フロー
- アプリ設計
- CI / CD
- 新卒育成
- 困ったときにフォローする
- 厚めのコードレビュー
新卒がチームにジョインしてからは機能開発よりは技術的負債の改善や開発環境整備周りのことをやっていることが多いです。
全社的にやってること
全社的にと言ってもAndroidエンジニアなのでAndroid関連のことをやっているのですが、部署に関係ないところでやっている業務は次のとおりです。
- Androidに関する技術・知見の共有
- SlackのAndroidチャンネルへの共有
- Android周りの全社の方針の整備
- Androidエンジニア中途採用
- 他のプロダクトのお手伝い
- コードレビュー
- 困ってそうなときにアドバイスしたり
他のプロダクトのお手伝いは最近はたまにやっている程度ですが、技術・知見の共有は私の趣味みたいなものなのでAndroidチャンネルに雑にたくさん投稿したりしてます。投稿する時点では実際の業務に関係が無くても、後からそういえば見たなと思ってSlack検索して役に立つことがわりとあるので結構便利です。
ここからは、開発時期別にやってきたことを振り返っていきます。
2017年10月 〜 2018年01月
この時期にマネーフォワード MEのAndroidアプリの開発で主にやっていたのは次の2つです。
- MfCoreさようなら大作戦
- ホームリニューアル
MfCoreさようなら大作戦
入社し始めの頃は仕事に慣れるために、Issueをちょこちょこ潰すみたいなことをしていました。 その中で、「MfCoreさようなら大作戦」というIssueを見つけました。
当時の私は何を考えていたのか分かりませんが、いけると思ったのかあんまり深く考えずにこのIssueに手を出してしまいました。 名前からしてヤバそうですが、MfCoreがいろいろなところに依存している激ヤバ神クラスだったので対応に結構な時間がかかりました。 結果、14個のPRに分けて対応することになってしまいました。
差分も大変なことになりました。
かなり多くのクラスに依存していたことが分かりますね。 入社時の勢いでやったものの、最終的にはこのときに神クラスを倒して良かったなあと思ってます。
ホームリニューアル
Issueなどで業務に慣れてきて1ヶ月ほど経ってから、ホームリニューアルという非常に大きなリリースを担当することになりました。 ホームリニュアルで行った改修は主に次の4つです。
- ホームのレイアウト変更
- MY通知、入出金履歴を全面に
- MY通知のデザイン変更
- ドロワーのレイアウト変更
- その他・お知らせの見直し
MY通知をホームの1つのタブとして、自身の口座のお金の変化がタイムライン形式で見やすくなったり、入出金履歴がホームの1つのタブとなり、入出金履歴へのアクセスがかなりしやすくなりました。
入出金履歴 Before | 入出金履歴 After |
---|---|
MY通知 Before | MY通知 After |
---|---|
私が担当したのは入出金履歴とMY通知の部分です。 入出金履歴はコードの負債が溜まっていたのに加えて振替周りの仕様が特に複雑で、仕様の把握をするところがかなり大変でした。 MY通知はユーザーごとに表示する通知が違うので表示はそんなに複雑そうに見えないのですが、実際は通知の表示パターンがかなり多く存在していて、それをいかにきれいに整えるのかを考えるのにとても時間がかかりました。時間が無い中で実装したにしては割ときれいに実装できたと思っていたのですが、いま見るともっとうまく実装できたかもと思ったりもするので、そろそろリファクタをしたほうが良いのかなと思っています。
全体的に改修を行ったので差分もかなり大きくなりましたが、大きな問題もなく無事に終えることができました。 ちなみに全部で547commitsでした。
AndroidのSlackチャンネルの作成
もう一つ、この時期にやったこととしてAndroidのSlackチャンネルの作成があります。
私が入社した当時、Androidエンジニア間の横の繋がりがあまりありませんでした。iOSやRailsのエンジニアは座談会という形で週1回、今やっていることの共有や技術共有などをしていて、Androidも以前はやっていたそうなのですが目的が曖昧になってきて開催をやめたそうです。 その経緯もあって、ただなんとなく復活させても良くないなあと思いつつも、横の繋がりはあったほうが良いだろうなとも思っていたので、Androidの技術・知見を共有するSlackチャンネルを作ることにしました。
私が勉強会やTwitterで拾ったAndroid関連の情報を雑に投稿したり、Android DevelopersのブログのRSSを自動で流したり、 ReleasesHub のようなライブラリの新しいバージョンを通知してくれる系のbotの投稿を自動で流したり、AndroidDagashi の投稿を自動で流したり、Androidの技術・知見がAndroidチャンネルに溜まっていくようになりました。また、ときどき他部署のエンジニア同士で会話もするようになりました。
チャンネルを作った当時は10人もいないくらいだったのですが、会社のエンジニア総会で宣伝したりなどもしたおかげで、今ではAndroidエンジニアだけでなくAndroidに興味があるエンジニアも含めてチャンネル参加者が32人にもなりだいぶ賑やかになってきました。 Androidエンジニアが新しくジョインしたらAndroidエンジニアランチを開催するなどもしており、技術・知見の共有だけでなく部署間の横の繋がりもできました。チャンネルを作って良かったなと思っています。
2018年02月 〜 2018年05月
ホームリニューアルまで一緒に開発していたメンバーが他部署に異動することになったため、この時期のマネーフォワード MEのAndroidアプリ開発のメンバーは私1人でした。 1人だと結構大変なんですが、1人は1人でわりと自由にできるので楽しく仕事していました。ちなみにコードレビューはノーレビューだったわけではなくて、銀行向けのマネーフォワードを開発している社員にレビューしてもらっていました。 細かいこともたくさんやっていたんですが、主にやっていたのは次のとおりです。
- RxJava 2.0へのアップグレード
- パスコードロックの指紋認証対応
- デバッグメニューの実装
- 開発フロー整備
- 新卒受け入れ準備
RxJava 2.0へのアップグレード
2018年3月31日でEOLになりました。入社後すぐにまだRxJava 1.xだったことに気づいてIssueは立てておいたのですが、ホームリニューアルがあったのですぐに対応できませんでした。 2月頃になってホームリニューアルがだいたい落ち着いてきたので、対応することにしました。 RxJava 2.xでは、1.xからパッケージが変わったり、クラス名・メソッド名が変わったり、onNextにnullが許容されなくなったりしました。マネーフォワード MEではRxJavaへの依存度がわりと高かったので、全体的にコードの改修をすることになり非常に大変でした。しかし、ここまでの大規模改修をすることはなかなか無いため良い機会だと思い、通信周りで使っているクラスをKotlin化したり、同じような機能を持った2つのクラスを1つにまとめたりなど、アプリ全体に関わる処理をきれいにしました。
差分がずいぶんと大きくなってしまったものの、大きな問題もなく無事にリリースすることができました。
パスコードロックの指紋認証対応
指紋認証は個人的にどうしても入れたかったのとレビューなどでも要望があり需要がありそうだと思ったため、自分でIssueを立ててPMにもお願いして導入に至りました。
Before | After |
---|---|
パスコードロック画面全体のデザインも刷新し、利便性が向上しました。 指紋認証のデザインプロセスについてはデザイナーの池内が書いたnoteがあるので、よろしければご覧ください。
マネーフォワードAndroid版の指紋認証デザインプロセス|池内健一|note https://note.mu/kenichiikeuchi/n/nc64e5c06142c
リリース後にはユーザーからのフィードバックで嬉しい声をたくさんいただいたので、導入して良かったなと思っています。
デバッグメニューの実装
2017年の年末に開催されていたAndroidの勉強会の shibuya.apk #20 にて、@takahirom さんの コードを変更せずにデバッグメニューでAndroidアプリの動作を変更する という発表を見ました。 勉強会で話を聞いたあとにすぐには実装できなかったのですが、ここで紹介されている debug-alter というライブラリがとても良さそうでした。 ホームリニューアルもRxJava 2.x対応も終わって余裕ができてきたので、debug-alterを使ってデバッグメニュー実装してみることにしました。
社内に共有してみた(実際はgif動画です)ところ、とても良さそうな反応が得られたのでそのまま導入しました。 その後、社内向けに資料を書いたのですがエンジニアブログに持っていこうという話になり外向けに調整してエンジニアブログの公開をすることになりました。
というわけで公開した記事がこちらです。
Androidアプリのデバッグメニューを作ろう | Money Forward Engineers' Blog https://moneyforward.com/engineers_blog/2018/04/11/android-debug-menu/
導入してから結構経ちましたが、デバッグ時にとても便利なのでかなり役に立っています。 いまでは Hyperion Android と併用して使っていますが、どちらもかなり便利なので使ったことが無い方はぜひ使ってみて下さい。
新卒受け入れ準備
4月に新卒が入社し、マネーフォワード MEにも新卒エンジニアが入ってくることになりました。 いままでは中途の社員しか居なかったため、ドキュメントなどがほぼ無かったので、これを機に整えることにしました。 Android Studioの導入手順から開発環境の構築手順、Androidアプリ開発における基礎、応用、実践の研修資料などを作成しつつ、それを使って新卒にAndroidの基礎から教えました。 Androidの基礎を教える前に歴史も一応知っておいたほうが良いだろうなぁと思い、Androidの歴史の話を書いたらエンジニアとか関係なく社内の色んな人に見てもらえたので、いろいろな人に興味を持ってもらえてよかったです。
また、開発フローやリリースフローなども今まで明文化されていなかったのもあり、分かる人がなんとなく運用していたのを整理して明文化しました。 ドキュメントがほぼ存在しない状態だったので、いろいろと整理する良い機会だったかなぁと思います。
2018年06月 〜 2018年12月
この時期は新しく入ってきた新卒が配属されたのと、銀行向けのマネーフォワードを開発していた部署から1人異動してきてくれました。 私が主にやってたのは次のとおりです。
- アプリ設計見直し
- Dagger2導入
- テストコードを書く環境の整備
- 手入力改善(UI刷新・リファクタ)
- TransactionDetailFragment.javaとTransactionEditFragment.javaの削除
- 入出金履歴リファクタ
- 家計簿詳細画面リファクタ
- カテゴリ一括変更
- CI環境整備
- 運用見直し
- 各環境のapkをDeployGateに自動デプロイ
- SonarQubeで静的解析
- レシート項目編集面のリファクタ
アプリ設計見直し
6月はまだ新卒エンジニアは少しずつIssueをやって仕事に慣れてもらっている頃で、ガッツリ機能開発をしている感じではありませんでした。 なので、新卒が開発に本格的に参加する前に設計を整えておく必要があるだろうと思い、設計を整えることにしました。 いままでの設計は設計と言えるほどきれいに整っていたわけではありませんでしたが、まとめるとだいたいこんな感じでした。
人によって設計がばらばらで全体的に整っているわけではありませんでしたが、MVVM的な設計に寄せていくのが良さそうだと判断し、設計を次のようにしました。
Android Architecture ComponentのViewModelとLiveDataを使ったよくあるMVVMのシンプルな設計にし、DIを導入することでテストもしやすいようにしました。 DIツールは今まで導入されていなかったため、いろいろと検討をした結果Dagger2を導入することにしました。 新卒に関しては新しい設計を使って初めて機能実装をする際にペアプロを行って順番に説明することで、新しい設計での開発を覚えてもらうことができました。 まだプロジェクト全体で新しい設計に整っているわけではありませんが、新しい設計を導入してから1年ほど経過しているためチーム全員が新しい設計を理解して機能を実装することができており、うまく浸透させることができました。
テストコードを書く環境の整備
Robolectricは入ってはいたものの、使える状態になっていなかったので使える状態にしました。
使える状態にしただけでは意味が無いので、あまり変わる予定のない画面である登録画面、ログイン画面のUIテストをサンプルとして書いて、テストコードを書きたくなったときに誰でも書けるようにしておきました。 全部一気に整えたわけではないのですが、MockWebServerを使えるようにしたりLiveDataやViewModelのテストを書けるようにしたりなど、必要都度徐々に整えたことで今では新卒も積極的にテストを書いてくれるようになりました。
手入力改善(UI刷新・リファクタ)
手入力画面のUIを大幅に刷新することになりました。
画面全体を変えることになるため、コードも全体的に改修する必要がありました。 新しい設計を適用する良いタイミングだったので、Dagger2の導入を頑張って先に終わらせてから手入力改善に新しい設計を適用してリファクタしました。 実際に導入してみて、ApiServiceとViewModel(AAC)をinjectすることによってActivityやFragmentなどのViewが介入する余地がなくなり、自然にViewとViewModelが分かれるようになりました。 また、ApiServiceをinjectしているため簡単にテスト用のモックサーバーに差し替えてテストすることが可能になり、テストコードが非常に書きやすくなりました。 新しい設計やテストコードを書くためのチーム向けの良いサンプルにもなったので、手入力改善のタイミングで実装したのは正解だったなと思っています。
TransactionDetailFragment.javaとTransactionEditFragment.javaの削除
手入力画面のUI刷新に伴い、電卓のデザインが変わりました。
入出金履歴詳細画面にも電卓機能があり、刷新した手入力画面のUIに合わせる必要がありました。 入出金履歴詳細画面はTransactionDetailFragment.javaとTransactionEditFragment.javaという1400行のFragment2つで構成されており負債が大きく、改修がかなり難しかったため全体的にリファクタすることにしました。 負債が大きいだけでなく振替機能などの仕様が複雑で、コードから仕様を読み取るのが大変でした。 リファクタを完全に達成するために4ヶ月ほど経ってしまいましたが、なんとか無事に終えることができました。 TransactionDetailFragment.javaとTransactionEditFragment.javaと完全に削除するまでの話については Android Reject Conference 2019/2 というAndroid勉強会で発表したので、よろしければ資料をご覧ください。
カテゴリ一括変更
いままでカテゴリを変更したい場合には入出金を1件ずつ変更する必要がありとても手間でした。 それを解決するために、家計簿詳細画面からカテゴリを一括で変更する機能を実装することになりました。
家計簿詳細画面は非常に古い画面で、単純に一括変更機能を付け加えるのが難しい状態でした。 家計簿詳細画面のグラフ以外の部分は入出金履歴画面と同じレイアウトのため共通化したほうが良いだろうと判断し、これらに関連する画面を次の手順で一気にリファクタすることにしました。
- 入出金履歴のリファクタ
- 家計簿詳細画面のリファクタ
- 家計簿詳細画面にカテゴリ一括変更機能をつける
入出金履歴はホーム、新着、口座別の入出金、検索など各画面で同じレイアウトで違うデータが表示されているだけで基本的には一緒なので、共通化したことによりコードが全体的に見やすくなりました。 これをベースとして家計簿詳細画面をリファクタしたことで、カテゴリ一括変更をスムーズに実装できました。
CI環境整備
新卒が入ってきて徐々に新卒が機能開発をするケースが増えてきて、明らかにレビューの負担が増えてきました。 私自身ももう1人のチームメンバーも単純な実装以外の業務もあるため、新卒が上げてくるPRに対してレビューが間に合わないみたいな状況が多々発生してきていました。 今では開発するときに当たり前の存在になっているCIですが、ここまでCIを回していませんでした。 そのため、良い機会なのでせめてlintが警告してくれるようなことは自動で指摘させたいという思いからCI環境を整えることにしました。 ktlintを新たに導入し、ktlintとandroid-lintの警告をDangerに指摘させることにしました。 CIはサーバーサイドでも利用していて知見が多そうというのと導入自体もすぐできそうだったためCircleCIを利用しました。 CIを導入したことで、人間が何度も指摘すると面倒になってくることでもDangerが容赦なく指摘してくれるので負担が減り、機能や仕様に関するレビューに集中できるようになりました。
運用見直し
いままでの進捗管理は、milestoneによるリリース管理と私が個人的にIssueを管理するためにはじめたGitHub Projectによって行っていました。 もともと1人で運用していたので特に問題が起きていなかったのですが、それを流れでそのままチームで利用するようになってから管理がだいぶしづらくなってきました。 そこで、milestoneの代わりにProjects使ってバージョンごとにProjectを作成してIssueを管理するようにしました。また、Automated kanban with reviewsのテンプレートによって自動でカードを動かすようにして、あまり人間の手を加えずに進捗が追えるように運用を見直しました。 レビューの状態やIssueの進捗状況などの進捗管理が以前よりもだいぶ分かりやすくなったため、PMもとても喜んでくれました。 また、意図的では無いもののiOS側も同じ運用に巻き込めたのでプラットフォームでも統一できたので、運用を変えてよかったです。
各環境のapkをDeployGateに自動デプロイ
Androidエンジニア以外のエンジニアなどから、検証用にテスト環境向けのapkを用意してほしいと言われることがあります。都度ビルドすれば良いものの、ビルドにはそれなりに時間がかかるためすぐ用意できないので自分も依頼してきた人も待ちが発生するのは良くないなと思いました。 そこで、マージした際にapkをビルドしてDeployGateに自動デプロイできるようにしました。
GitHubのREADMEにQRコードを載せておくことで読み取ってダウンロードすればすぐに使えるようになり、Androidエンジニアにビルドを依頼して待つ必要が無くなりました。
SonarQubeで静的解析
テストコードが少しずつ増えてきたことと、CIを導入したのもあってテストコードのカバレッジやコードの品質を見てみたいなという気持ちになりました。 社内の別のプロジェクトでSonarQubeを使っていたというのもあり、それに載せてもらう形でシュッと導入しました。まだこれを使ってなにかアクションを起こしたりはしていないんですが、カバレッジがいつでも見れる状態になったのでテストコードを書くモチベーションが上がりました。
2019年01月 〜 現在
この時期に私が主にやってたのは次のとおりです。
- 年額課金
- AndroidX対応
- PRへのpush時にDeployGateのDistributionURLをコメントする
- 自動リリース
年額課金
マネーフォワード MEにはいままで月額プランしかありませんでしたが、2019年の3月に 年額プランがリリース されました。 いままでの実装ではAIDLを使って課金が実装されており、最初に実装してからほぼ修正が加えられていない状態でかなり複雑な実装になっていました。 まずはAIDLからGoogle Play Billing Libraryによる実装に変更し、その後年額課金を実装するという手順で改修を行いました。 課金周りはネットにあまり知見が共有されておらず、Androidも大変でしたがiOS側も相当実装が大変そうでした。 年額課金でだいぶ知見も溜まってきていたので、課金周りの知見を共有する勉強会を開催したいなと思いSlackにつぶやいてみました。
面白そうだねという話になり、年額課金のリリースが落ち着いてから課金の勉強会を開催することにしました。 このような経緯で開催されたのが In-tamachi Billing Night です。 Androidの課金の実装の話は私も行ったので、よければ資料をご覧ください。
勉強会の開催もまた大変で、新オフィスでの技術系の勉強会の開催実績が少なかったこともあり知見が無く非常に苦労しました。 なので、私みたいに勉強会を開催したいと思った人が同じ苦労をしないように、ここで得た知見を社内ドキュメントに書いて、手順通りにチェックリストを埋めていけば開催できる状態にしておきました。 集まった人数は少なかったものの、コアな層が集まって濃い話がたくさんできたので開催して良かったなと思います。次回開催を望む声もあるので、次も開催したいなと思っています。
AndroidX対応
年額課金のリリースがだいたい落ち着いてきたので、そろそろAndroidX対応しないとまずいだろうなぁと思いやることにしました。 Android Studioに「Migrate to AndroidX」というマイグレーションツールがあるのですが、これを押すとパッケージフルでクラス参照されてしまう箇所がたくさんあり、import文以外の差分もたくさん出てしまうという問題がありました。 これをスルーしてそのままマージすることもできたのですが、ここでスルーしてしまうと誰かがそのソースコードを触るときに修正したり気づいた人が指摘するという手間が都度発生してしまうことが予想できたので、手作業で全部潰すことにしました。 手作業で直すのはだいぶ大変でしたし差分も大変なことになったのですが、ほぼimport文だけの差分になったので、ここで対応しておいて正解だったと思っています。
PRへのpush時にDeployGateのDistributionURLをコメントする
DroidKaigi 2019のPull Request では、push時にビルドして生成されたapkをDeployGateにアップロードし、そのDistribution URLをコメントするようになっています。 同じ機能がずっとほしいなと思っていたんですがなかなか時間がとれずにできませんでした。 ようやく落ち着いてできる状態になったので、DroidKaigiのスクリプトを参考に対応することにしました。 構成が違うのでコピペで済むようなものではなく、そのスクリプトが何をやっているのか理解するのに若干苦労しましたが、なんとか実装できました。
導入後、自分自身も役に立ちましたが、デザイナーさんにもお礼を言ってもらえたので良かったです。
自動リリース
最近ようやくGoogle Play App Signingを有効にしたのに伴って、アップロードキーをつかってCircleCIからGoogle Playに自動でリリースできるようにしました。 仕組みとしてはこんな感じです。
- エンコードしたアップロードキーをCircleCIの環境変数に入れておく
- releaseブランチへのマージ時にreleaseのワークフローを開始
- Google Playにリリースをして良いかの承認をSlackに通知
- CircleCI上で承認
- 承認がされたらリリースビルドを走らせる
- Google Playのベータトラックに自動リリース
- 生成されたapkを元にバージョンを取得し、GitHubにreleaseタグをつける
マージ後にそのままGoogle Playにリリースすることもできるのですが、意図しないリリースを防ぐために念のため承認制にしています。また、同じ理由で製品版に直接リリースすることはせず、必ずリリース権限を持つ人間の承認を経て製品版のリリースを行うこととしました。 そのため、全社的にPlay Consoleのアカウント権限の整理を行ったりなどを先に行ってからリリースの自動化をしました。 リリースノートについても、いままではgit管理されていなかったものをgit管理するように変更し、ベータトラックへの配信時に一緒にリリースノートを入れるようにすることで差分が分かりやすくなりました。 タグについてはいつもreleaseブランチへのマージ時に手動でつけていたのですが、Android SDKに含まれているaaptを使うことでapkからバージョン情報を取れることに気づき、それを使って自動でタグをつけるようにしました。 以上に対応により、リリースフローの手動作業をほとんど自動化することができました。
まとめ
入社してから今までたくさんの機能開発や負債改善、開発環境整備などを行ってきました。 普段の業務を行っていて、何らかの課題を感じたら必要に応じて何か解決策を考えて解決していくということを地道に続けてきました。 その結果、新しいメンバーが入ってきてもドキュメントを見ればすぐに開発を始められるようになったり、開発がしやすい設計が浸透してきたことにより生産性が上がったり、CIの整備によりすぐにアプリの動作を確認できるようになったり設計・仕様のレビューに集中できるようになったり、様々な環境を改善することができました。 他の会社では当たり前になっていることでも、自分の会社ではすぐに導入できないこともあると思います。それでも、課題を1つずつ解決していき改善を続けていけば開発環境は良くなっていくのだということが約1年半を振り返ってみてとても感じました。 これからも、良いサービスをスピード感をもって提供できるように開発環境を改善しつつ自分自身も機能開発をやっていきたいと思います。
最後に
マネーフォワードでは、エンジニアを募集しています。 ご応募お待ちしています。
【採用サイト】 ■マネーフォワード採用サイト ■Wantedly
【マネーフォワードのプロダクト】 ■お金の見える化サービス 『マネーフォワード ME』 iPhone,iPad Android
■ビジネス向けバックオフィス向け業務効率化ソリューション 『マネーフォワード クラウド』