CLOSE

急成長中のレシピ動画サービス『クラシル』を運営するdelyが、 これまでのグロース戦略、エンジニアリング方針、ユーザー調査手法等についてお話しします!(全6記事)

サービスの成長に合わせてアーキテクチャを改善 「クラシル」Androidアプリにおける試行錯誤を振り返る

2018年7月12日、レバテックが主催する渋谷ヒカリエを中心としたエンジニア向け勉強会「ヒカラボ」が開催されました。今回のテーマは「急成長中のレシピ動画サービス『クラシル』を運営するdelyが、 これまでのグロース戦略、エンジニアリング方針、ユーザー調査手法等についてお話しします!」。急成長ベンチャーとして随所で注目を集めているdelyの急伸の秘密を、現役エンジニアリーダーたちが余すところなく語ります。続いて登場したのはdely株式会社のリードエンジニアでAndroidアプリ開発担当の梅森翔氏。サービスの成長に合わせたアーキテクチャ改善の歴史を振り返ります。

継続的なアーキテクチャ改善の理想と現実

梅森翔氏(以下、梅森):こんばんは。Androidエンジニアをやっています。今テックリードと紹介いただきましたが、テックリードみたいなこともやりつつ、Androidエンジニアをやっています。

今日はテックリードっぽい話はしないんですが、Androidの開発についての話をしたいと思います。タイトルとしては「継続的なアーキテクチャ改善の理想と現実」というタイトルで発表します。

自分がdelyに入って1年と2ヶ月経ちました。入社時はテレビCMをやって一気にアプリがグロースした時期でした。今年のDroidKaigiで登壇したりしています。

今日発表する内容としては、今のdelyのAndroidのアプリケーションがどんなアーキテクチャであるかということと、自分が入った頃はどんな感じだったか。そしてそれをどうやって改善したかという話をしたいと思います。

2018年7月現在のAndroidアプリケーションのアーキテクチャはこんな感じになっています。Activity、Fragmentがあって、Viewの層があって、あとで細かく説明はしますが、Applicationがあって、Data層、Infra層があって、4層のレイヤードアーキテクチャになっています。

サービスもあるのでServiceが左のほうにありますが、Serviceがあり、それらがData層、Infra層に紐付いているという実装をしています。現在は一般的なアーキテクチャなのかなと思っていますが、こんな感じでやっています。

理想はこんな感じです。現実としては若干アーキテクチャのルールを守っていないコードがあったりするのですが、こんな感じでやっています。

現状のアーキテクチャ

先ほどざっくり説明したのですが、4層のアーキテクチャでやっています。View層、Application層、Data層、Infra層、Service。+1というのは、Serviceは厳密にいうとActivityやFragmentのライフサイクルとは違うものなので分けています。

ViewはMVVMを採用しています。だいぶ前にAndroid ArchitectureのComponentsが出てきて、ViewModelというのが出てきたんですけど、みなさんこれはどうしていますか? けっこう名前に困ってます?

Android Data Bindingを活用して実装しています。ViewModelでイベントハンドリングとプロパティバインディングをやっているというスタンダードな感じですね。

Application層はViewModelのイベントを受け取って、Data層を操作し、そのデータをViewModelに返す。ここはまだ実装中、未完成なんですけど。

Data層があります。右に書いてあるのは、クラス名に末尾にこんなことをつけたりする、という決まりになっていたりします。ローカルの永続化周りの操作やWeb APIの呼び出し、メモリ上の一時的なデータの取り扱いなどを行っているような層ですね。

Infra層、その他すべて。今話したことに関わらないところは全部ここに押し込めるみたいな感じで今はやっています。DI周りだけはパッケージを分けていますが、それ以外は一緒くたになっている感じですね。

最後にServiceですが、これはいわゆるAndroidのServiceなので、Activityのバックグラウンドで起動したりするものです。直接Data層にアクセスしてて、ほぼApplication層のようなものだから、Data層にアクセスしてるみたいな感じでやっています。ここは実装しながら悩んでいる感じですね。

いいところとしては、それぞれの層の役割が明確になっています。最悪Infra層に閉じ込めておけばなんとかなるだろう、みたいな感じで実装できるのがいいところです。複雑な機能もRepositoryとApplicationにうまく分割すれば整理しやすいのがいいところです。

現状のよくないところとしては、大規模にパッケージをリファクタリングしたところでヒストリが途切れているところがあったりして、そこはよくなかったり。先ほど見せたとおり、完全に設計どおりのつくりにはなっていないので、そういうところはよくないですね。

まだ移行しきれていない実装もところどころ残っていたりします。でも、悪くはないレベルになってきています。

アーキテクチャを改善するきっかけ

自分が入った頃のアーキテクチャはこんな感じでした。登場人物がとても少なくてシンプルですね。入った時に「このままだとまずそうだな」と思いました。とくに設計思想もなく、いろいろな人の手を渡ってきた感じのするコードでした。

その頃、ユーザー数はグロースしていたんですが、開発チームはスケールしなそうだと思ったので、その当時もう1人いたAndroidエンジニアに協力してもらってアーキテクチャ改善に取り組むことにしました。

アーキテクチャといえば、みなさんご存じだと思いますが、コンウェイの法則というものがあります。「システムを設計する組織は、その構造をそっくり真似た構造の設計を生み出してしまう」。つまり、システムのアーキテクチャは組織構造に従うという法則ですね。

逆に言えば、悪いアーキテクチャは組織構造を悪くするし、良いアーキテクチャは組織構造を良くする。これは逆コンウェイの法則と言ったりします。

というわけで、サービスと一緒に成長するためにアーキテクチャを改善しました。

改善するためにやったこと

まずやってみたことです。とりあえずActivity、Fragmentがここで一緒くたになっていたので、Viewを分離したいと。幸いなことに当時Data Bindingを使っていたので、Butter Knifeと同じような使い方をしてましたが、MVVMを導入しました。

ちょうどその頃まったく新しい機能の実装を任されたので、サンプル的に画面をいくつか作ってもう1人のAndroid開発者に共有をし、小さく始めました。

たしか、6〜7月ぐらいに第1段階が完了したと思います。9割ぐらいの画面を、実際にView層を作ってMVVM化することができました。

次に、View・Infra層を整理しました。

同じ画面を構成しているViewModel、あるいはActivity、Fragment。この画面は動画の一覧の画面なんですが、実際にはその画面を構成しているコンポーネントはもっといろいろあります。ListだったのでAdapterがあったり。そういったものを一緒くたに同じパッケージ構造に置いたり。

そして、9割ぐらいのAndroid SDK API呼び出しをInfra層に切り離しました。

その結果、若干整ってきました。でも、まだ層としては少ないので、ViewModelに複雑な処理が残っているという感じです。

次にData層を切り離しました。APIへの通信やローカルのSharedPreferenceの書き込み、呼び出しなどを〇〇Repositoryに切り出しました。ローカルとリモートを切り分けて、そこでざっくり分けたような感じでやりました。

もともとUseCaseという名前でAPIの通信が切り離されていたので、それのリネームがメインでしたが、いろいろと整理しました。

そういうことをやった結果、View層からIO関係の処理が消えました。ただ、新しく作ったData層に今度は複雑な処理が集中してきました。

というわけで、Application層を切り離すことにしました。Data層で扱っている複雑めな処理をApplication層に移動。Serviceも、これとは別なんですけど、Data層を参照するように切り替えました。

グロースに合わせて価値を届けるために

12月ごろにほぼ現在に近いかたちになって、今もすこしずつ、構造はできたので改善しているという感じです。

ほかにもいろいろやったんですが。Dagger2のライフスコープを切り分けたり、イベントハンドリング用のイベントバス作って導入したり、RxJavaを導入したり、いろいろやりました。

1年ぐらいやってみた感じですね。これがコントリビューションの結果なんですが、25万行足して17万行減らしています。

感想としては、なかなかつらかったですね。最初はあまりいいコードではなかったですし、今でも完全によくできてはないし、最初からきれいだったらもちろんよかったと思います。

でも、サービスの成長段階によって必要となるアーキテクチャは違うと思います。価値がすばやく届けられるのが大事だし、グロースする前にオーバーキルのアーキテクチャはいらない。なので、人が増えていくタイミングやアプリが複雑化するタイミングで変えちゃえばいいじゃないかと思います。

それはけっこうつらいんですが、そのときに苦しめばいいし、今日説明したようにちょっとずつレイヤーを増やして移行することもできます。

というわけで、クラシルはこれからも成長していくので、サービスの成長と一緒に成長するプロダクト、そしてアーキテクチャを育てるAndroidエンジニアを募集しています。ありがとうございました。

(会場拍手)

続きを読むには会員登録
(無料)が必要です。

会員登録していただくと、すべての記事が制限なく閲覧でき、
著者フォローや記事の保存機能など、便利な機能がご利用いただけます。

無料会員登録

会員の方はこちら

関連タグ:

この記事のスピーカー

同じログの記事

コミュニティ情報

Brand Topics

Brand Topics

  • 今までとこれからで、エンジニアに求められる「スキル」の違い AI時代のエンジニアの未来と生存戦略のカギとは

人気の記事

新着イベント

ログミーBusinessに
記事掲載しませんか?

イベント・インタビュー・対談 etc.

“編集しない編集”で、
スピーカーの「意図をそのまま」お届け!