#MoneyForward_Eight スマホ開発の裏側体験談をまとめてみた! マネーフォワード×Eight -モバイルアプリ勉強会-
マネーフォワードとEightのアプリの開発環境や実体験などを語るマネーフォワード×Eight -モバイルアプリ勉強会-に行ってきたのでそのまとめです。
場所は自身は今年三度目になる株式会社Sansanで行われました。
勉強会の開催数すごい多いなぁ〜。
俺が!俺たちが!Androidチームだ!
鈴木 研吾様 (株式会社マネーフォワード Androidエンジニア)
- チームとしての成長で取り組んだことの紹介
自動化
- GitLabを中心に、jenkinsやtestflight, deploygateなどを用いてCI環境を構築した
標準化
- 実装者以外の理解を進めるために設計書を書いた
- 設計や仕様書は今までなかったが、qiitaに外部仕様や内部仕様を書くようにした
- 外部仕様はユーザーのアクションでどう動くかを書いている
- 内部仕様はどこがActivityで、どこで通信しているか、どういうデザインパターンで実装しているかなどを書いている
- 基底クラス作り
- 簡単なところから基底クラスを作るようにしている
- Intentの作成を規定化して継承、実装してActivityを作ったり、Baseのフラグメントを使ってライフサイクルをいまいちにならないようにしている
- 作ったものを更に啓蒙するようにしている
- リリース当番制度
- だれでもいつでもリリースができるようにしておく
- 一人しかいないとリリースができなくなる場合があるので当番制度を採用して全員がフローを回すようにしている
- リリースノートの作成、動作テスト、ドキュメントの更新などを当番の人がやる
継続的改善活動
- androidエンジニア座談会というKPTを実施して、毎週金曜日30minで話したいことを話す。テーマは決まってない
- 改善案、試したいこと、気にになるライブラリ、新しく入社した人向けの説明など
他部署(CS)との連携
- それぞれ思っている・伝えたいことの共有する
- ユーザーの声を直接聞く人(CS)からフィードバックをもらう
- 毎日決まった時間に1人、聞きに行く
- 新機能リリース時、形ができた時点でテストに参加してもらう
- bugを早い段階で発見・対応できる
- 外部仕様の共有ができる
セキュリティ診断
- 年2回の診断を別の会社に依頼して水準を保っている
iOSアプリエンジニアの最近
浅井 勇樹様 (株式会社マネーフォワード iOSエンジニア)
Merge Request (Pull Request)
- MR体制を強化している
- 少なくともエンジニア5人中2人がレビュー
- 細かいことでも指摘、質問する
- 精一杯優しく。下から下から言うように心がける
- リクエスト単位
- バグ単位、タスク単位、機能単位でやっているが、機能単位だとすごい大きさになる
- 機能単位はでかすぎるので最近WIP(Work In Progress)とつけてRequestを出している
- 約束として、作業中のコードを晒し、WIPはマージしない
- 目的として、実装方針の議論、問題の早期発見、他部署からの指摘もある
Refactoring & Code Review
- リファクタリング、コードレビュー会というのを定期的に開いている
- 毎週金曜の16-17時にMTG部屋にスマホエンジニアが集まってリファクタリングとコードレビューをやる
- 終了後に成果を報告する
- やることと成果をスプレッドシートにかいたりしている
目的
- 定期的に負債を返済
- 他人のコードを見てなおした方がいいと思うことを指摘したりする
- スコープ小さくしたり、再利用性を高めたり
- 知見の共有
- 良いライブラリがあったよと教えたりする
- ライブラリのコードリーディングしたり
- 最近の悩み相談
- 個々の実装もっとシンプルにできませんか?
- 勉強会で何話したらいいですか?
ライブラリへMRしてみた
- いいライブラリを見つけたが、このライブラリを使うにはこの機能の実装が欲しいと思った時にMRを出してみたりした
- 最近だとパスコード機能を実装するために、SwiftPasscodeLockというライブラリを使ってみた
- 具体的にはパスコードの保存先をキーチェーンだけではなく他の保存先も拡張できるようにMRした
Swift
- Pure Swiftを目指して開発している
- 新規コードはSwiftで記述、既存コードも気づいたらSwiftへ移行している
- 只今のSwift率は33%
- Swift移行への落とし穴
- Obj-cとのインターフェースが大変
- Optionalの扱いが雑
- OptionalなIntなどを参照不可
- NSArrayなどの扱いが面倒
- 話題のObjective-C to Swift Converterを試してみた
- 使用感はまだ厳しい
- ところどころ変換がおかしい
- .hと.mをマージしないといけない
- webサービスなので怖い
EightのiOS開発 本当にあった怖い話
坂本 和大様 (Sansan株式会社 アプリエンジニア)@kazu0620
恐怖!仕様変更の回!
- 企画職が仕様を決めて仕様書を作ってエンジニアに渡す
- それをもとにエンジニアが作って確認してもらうと思ってたのと違うといわれ修正出される
- しかし修正を出してもまた修正
- Eightでは3ヶ月かけて作ったものが世に出なかった事がある
- どこに問題があるか
- どんなに企画段階で練っても仕様変更は起こりうるので、起こる前提でどういうふうに対処するかが大事
- 問題は確認のサイクル
- 仕様策定 -> 実装 -> 動作チェックのサイクルで実装にすごい時間がかかると出戻りが大変になる
- Eight version 6.3は、仕様を決めプロトタイピングに一ヶ月半、開発に1ヶ月でリリースできた
プロトタイピング
- サイクルを早くするためにプロトタイピングをしっかりする
- flintoというプロトタイプツールを使っている
- 画像にタップイベントと遷移を追加できる
- ブラウザで動く
- flintoで動作チェックをしてデザイナーがまた修正をして、完成したところで実装を進めるので最終チェックで差し戻しを少なくできる
- しかしこれでも仕様変更がなくなるわけではない
- リッチなインタラクションやアニメーション出演などは再現できない
- UI実装の工数などは実装してみないとわからない部分がある
- 触る人の気持ちの問題もあり、動きが省略していると、脳内で勝手に補完してしまって、実際に触ると思っていることとの差異が生まれたりする
hotmock
- 動きを確認するための最小限の機能を備えた実装に動くアプリ(hotmock)を作ってみた
- model周りは代わりのデータを作り、viewのものだけを作ったもの
- サーバーとの通信などは実装しないがUI周りについてはすべて動く状態を実現する
- これですべてが終わってから差し戻しというのをなくせた
- prototypeとhotmockのサイクルをまわしてから最終的に実装した
- hotcmockの作成がわりにあうかどうかは変更の大きさにもよる
- 手戻りのリスクが大きい改修ならペイする可能性が高い
- それほど大きな改修でなければプロトタイプだけでも良さげ
- ただ、作ったhotmockはそのまま実装にも使えるので作る手はあり
最後に
- プロトタイピングやhotmockを使うことで仕様変更をなくせるわけではないが、手戻りリスクは抑えられる
- 仕様変更が発生した時は迅速にほかチーム・メンバーに共有
- iosで仕様変更したときはandroidにも行く事が多いので、共有が大事
- 仕様が変わった時はslackで流してチェックするようにしている
- サイクルごとに合意を取っていくことでどんでん返しを防げる
怪奇!巨大モデルクラス!
※ここから懇親会で聞いた内容になります
- DataManagerという数千行にも及ぶ巨大モデルクラスがあり、Data関連のことをいじるにはすべてそのモデルクラスを扱っているものがあった
- Realmを使ってEntityごとに切り出しを行い、DataManagerを使わないようにリファクタリングした
不思議エラー処理!
- サーバと通信するのにAPIClientというクラスが存在していて、全ての通信はこのクラスを通して通信している状態で、成功した時の処理はあるが、エラーの時の処理がなかった
- 掘り進めてみると、サーバに投げる時にパラメータの一つに定数でエラーを投げるようにリクエストをするとサーバがエラーを返してくれるようになっていて、それでエラーハンドリングをしていた
- APIClientを修正するには影響が大きすぎたため、Promiss Kitを使った方法を使えるようにラッピングして使う側はAPIClientの仕様を知らなくても自然にエラー処理をできるようにリファクタリングした
[Android] レガシーコードと戦うためのリファクタリング
山本 純平様 (Sansan株式会社 アプリエンジニア) @boohbah
はじめに
- 入社後、2日で前任者から引き継ぎを行った
- 1日目はまずは残タスクの洗い出しや、スケジュールの確認
- 2日目は仕掛中のタスクを丸一日ペアプロして一緒に実装した
- タイトなスケジュールの中でもリファクタリングを実施したが、なぜリファクタリングするのか
- リファクタリングはソフトウェアを理解しやすくする
- 複雑なコードを理解しながら開発を進めるにあたってリファクタリングがもっとも効率よく進められると考えた
名前をつける
- 例えばswitch文にマジックナンバーが使われていたりしたらenumで名前をつけていった
- javaのenumは条件判定などのメソッドも入れられる
- 統一した名前をつける
- 運営からのお知らせという機能がServiceMessage, ConductNews, FeedAnnoucement…と、同じ機能なのに違う名前がついていることがあってわかりにくかった
- ユビキタス言語や単語帳を作ったりした
- プロジェクトの中にも日本語としては共通の単語のコンセンサスはとれていたが、英語に訳す段階で用語がバラバラになっていた
- 単語帳にも英訳が必要!
- ios – androidで命名を合わせるようにコミュニケーションを取る
FatなActivityと戦う
- 2000行を超えるActivity/Fragmentがあり、そのメンテナンスと変更が非常に困難だった
- activityでは何をするべきか?
- ドメイン駆動設計のレイヤアーキテクチャで考えた時、Activityはアプリケーションの活動を調整する薄いレイヤであるApplicationLayerに属するのではないかと考えた
- これはビジネスロジックを含まず、ビジネスオブジェクトの状態を保持しない
- そう考えた時、activityはライフサイクルの管理と画面遷移のハンドリングに集中すべきと考えた
- Presenter, use-caseをActivityが包括してしまっているので、どうやってこの部分を切り出すかを考えた
ActivityからUse-caseを切り出す
- メッセージをやりとりする画面
- メッセージを投稿する、定期的にサーバーに更新をチェックするという機能
- ボタンをクリックしたらMessageをポストして結果を保存するソースについて
- sendMessageというメソッドを別クラスに持っていった
- インサートが終わったら表示という処理もまたRepositoryというクラスにわけ、viewはそのクラスをlistenするようにして更新を行う
ActivityからPresenterを切り出す
- これまではactivityにviewを制御するコードが全てあり、viewからのonclickのイベントもactivityが受け取って実装するということが多かったと思う
- MVVMパターンを使った
- DataBindingというAndroid Studio1.3から使える機能をうまくつかった
- activityにviewmodelというオブジェクトを持たせてそこに表示するためのデータだったりイベントだったりのハンドルを持たせてviewとのやりとりはすべてviewmodelに任せる
- こうすることでactivityからviewに関する処理は全て排除できる
@mogmetの所感
リリース当番制度や、CSとの関わり方、コードレビュー会、iosとandroidで命名を揃えるなど、運用として取り入れていきたいとおもう方法が多数紹介されていてとてもいい勉強会でした
hotmockの作成については、自分はいつもunit testを作ってそれを元にモデルを作成し、viewを作成・・・といったことをしていて、手戻りが多くなるような手順を踏んでいたので、先にviewを作ってしまって企画職などの人に見せるようにするのはとてもいい方法に感じました。
また、最後のfatなactivityについても考え方としてはiosでもview-controllerでも通じるものはあるのでPresenterへの切り出しなどの考えは非常に参考になりました。
※16回目のpotatotipsでもMVPについて話されていた方がいらっしゃったので合わせて参考になるかと思います。