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