2024.10.10
将来は卵1パックの価格が2倍に? 多くの日本人が知らない世界の新潮流、「動物福祉」とは
ZOZOTOWN AndroidへのJetpack Composeの導入 (全1記事)
リンクをコピー
記事をブックマーク
高橋啓太氏(以下、高橋):「ZOZOTOWN AndroidへのJetpack Composeの導入」ということで、発表します。まず自己紹介ですが、株式会社ZOZOテクノロジーズ(※取材当時)で「ZOZOTOWN」のAndroidエンジニアをやっています、高橋といいます。2020年の新卒入社で、今年で2年目です。
簡単に、ZOZOTOWNについて紹介させてください。ZOZOTOWNは、日本最大級のファッション通販サイトで、2021年の3月にはコスメ専門モールの「ZOZOCOSME」がオープンしました。
さっそく、今回のテーマとなるJetpack Composeについて簡単に説明していきます。Jetpack Composeとは、宣言的UIのツールキットで、Kotlinのコード上でUIの実装が可能になります。また、XMLを用いた既存のレイアウトとも相互運用可能となっています。つい最近、1.0.0のstableがリリースされました。(※取材当時)
Jetpack Composeでは、Composableアノテーションを付与した関数でUIを定義します。
そんなJetpack Composeについて、ZOZOTOWN Androidへの導入時に行った作業を順に説明していきます。
導入のステップは、大きく分けて3つあります。1つ目は、開発環境の整備。2つ目は、Compose導入時の課題の洗い出し。3つ目は、その課題の解決です。
まず、1つ目の開発環境の整備について説明します。Composeを使用した開発の前に、Android Studio Arctic Foxで既存プロジェクトのビルドを行いました。Android Studio Arctic Foxでは、Jetpack Composeの開発のサポートが強化され、Compose UIのプレビューなどが実装されました。
また、ZOZOTOWN Androidでは、Arctic Foxの導入と同時に、Android Gradle プラグイン 7.0.0へのアップデートと、JDK 11の導入を行いました。さらに、Dagger Hiltのアップデートも行いました。この環境で、一度ZOZOTOWN Androidをビルドし、問題なくビルドできることを確認しました。
Jetpack Compose beta08からはKotlin 1.5が必要となるため、Kotlinのアップデートもしました。アップデートの実施に際しては、リリースノートなどのドキュメントの確認とZOZOTOWN Androidへの影響箇所の調査を行いました。
ドキュメントの確認は、チームメンバーで読み合わせるかたちで行いました。のちほど登場するのですが、Composable内でFlowを利用するために、androidx.lifecycleのアップデートも行いました。
次のステップでは、Compose導入時の課題の洗い出しを行いました。課題を洗い出すため、Composeを使ったプロトタイプ実装とレビューを繰り返し行いました。プロトタイプ実装とレビューによって、大きく2つの課題が明らかになりました。
1つ目が、既存のZOZOTOWN AndroidのUI状態管理方法が、Composeに適していないということ。そして2つ目が、無秩序なComposable作成による、Composableの再利用性・可読性の低下です。
では、その2つの課題の解決に向けて、それぞれどのようなアプローチを取ったのかを説明していきます。
1つ目の課題は、既存のZOZOTOWN AndroidのUI状態管理方法が、Composeに適していないというものですが、この課題の解決に向けて、まずComposeが採用されているプロジェクトの実装を調査しました。そしてそれをもとに、Composeに適した設計を検討しました。
Composeは、公式のページにもあるように、UIの差分更新を自動で行います。なので、開発者は差分を意識してUIにデータを通知する必要がありません。
ここで、既存のZOZOTOWN Androidのうち、今回問題となった部分を説明していきます。ZOZOTOWN Androidでは、アプリケーションの状態に変更があると、ViewModelはその更新差分をFragmentに対して通知します。Fragmentはその内容をもとに、更新が必要なViewの更新を明示的に行います。
プロトタイプ実装とレビューによって、この更新差分を通知する部分が、Composeには適していないということが今回わかりました。
この問題についてコードレベルで説明します。ZOZOTOWNのUIの状態管理には、主に2つのオブジェクトが登場します。1つ目が、ViewDataです。ViewDataは、UIに表示するデータをまとめたデータクラスで、カスタムビュー単位で作成します。
2つ目が、ViewStateです。ViewStateはUIの状態を表すsealed classで、画面単位で作成します。ViewStateはそれぞれ、ViewDataを保持します。ZOZOTOWN Androidでは、ViewStateの切り方について明確なルールがこれまで存在しませんでした。
これらのViewData、ViewStateは、ViewModelの中でこのように扱われます。上から説明していこうと思います。
まずViewModelには、Activity/FragmentにViewStateを通知するFlowまたはLiveDataが定義されています。次に、そのデータの更新と、ViewStateを先ほどのFlowやLiveDataに流すメソッドが定義されています。そして最後に、ViewStateが定義されています。
それぞれのViewStateでは、更新差分のあるViewDataのみを保持しています。これがComposeでは扱いづらいということがわかりました。
先ほども紹介したように、Composeでは、差分を意識してUIにデータを通知する必要がありません。裏を返せば、これを活用するためには、画面全体の状態を1つにまとめる必要があるということです。
その点を踏まえ、UIの状態管理方法を見直しました。さらに、Eventの処理方法についても見直しを行いました。
まず、UIの状態管理方法の見直しについてです。設計を検討するにあたって、事前に参考実装の調査を行いました。そのうちの1つが、tiviというプロジェクトです。tiviは、Jetpack Composeで実装されたプロジェクトで、既存のZOZOTOWNと近いアーキテクチャであるため、今回の設計検討はtiviを参考にして行いました。
参考実装をもとに、まずは画面全体のViewDataを1つのViewStateに統合しました。そして、これまで差分のみを保持していたViewStateを削除しました。
次に、アプリケーションの状態を管理するFlowを用意しました。それらのFlowを、combine、そしてtransformすることで、アプリケーションの状態に変更があった時に、画面全体の状態を持った先ほどのViewStateを作成し、通知することができるようになりました。
そうすることで、Composable側では常に画面の全体の状態を受け取ることができ、ComposeのUIの差分更新を利用できるようになりました。
全体の流れは、このようになります。アプリケーションのStateが変化すると、ViewModelではそれを1つのViewStateにまとめ、Composableに通知します。
次に、Eventの処理方法についてです。ViewModel以下のEventの扱いに関しては、既存のZOZOTOWNと大きく変わる点はありませんでした。既存のZOZOTOWNにもあるのですが、ViewEventという、ユーザーインタラクションによって発生するEventを定義したsealed classを作成しました。ViewEventは、Flow/LiveData、LiveDataの場合はSingleLiveEventでViewEventを通知するようにしました。
ComposableからのViewEventの発行は、このようになりました。ViewEventは、各画面のトップレベルのComposableから発行するようにしました。そうすることで、下層のComposableは、ViewEventへの参照を持たず、ViewEventを意識しないかたちとなりました。これによって、下層のComposableの再利用性を上げることができました。
ここまで説明したViewState、ViewEventについて、ViewEventの発生から UIの更新までの流れはこのようになります。
画面上で、ユーザーインタラクションなどによってEventが発生すると、そのEventはLambdaを介して、上層のComposableへと伝搬されます。そして上層のComposableは、ViewModelに対して、ViewEventの発行を行います。
ViewModelは、ViewEventを受け取るとアプリケーションのStateを更新し、それらの状態を1つのViewStateというオブジェクトにまとめてComposableへと通知します。
ComposableはViewStateを受け取ると、UIの描画に必要なデータを下層のComposableに伝搬します。各Composableは、渡されたデータをもとに、UIの更新が必要だった場合に自動的に差分更新を行います。
このように、UIの状態管理、Eventの処理方法を見直し、1つ目の課題である、既存のZOZOTOWNのUI状態管理方法がComposeに適していないという問題を解決しました。
次に、2つ目の課題についてです。今後、チームでComposeを使用した開発を進めていくと、無秩序にComposableが作成され、Composableの再利用性・可読性が低下する懸念がありました。
そこで、ReactなどWebフロントの宣言的UIフレームワークではどのようにUIの要素を分割しているのか、事例を調査し、チームでの開発に備えたComposable設計ルールの検討を行いました。その調査の中で登場したのが、Atomic Designです。
Atomic Designは、主にWebフロントの世界で用いられるデザインシステムで、堅牢性の高いUI実装を実現できます。Atomic Designでは、コンポーネントと呼ばれるUIの要素を、Atoms、Molecules、Organisms、Templates、Pagesに分類し階層化します。
Atomic Designで定義されるコンポーネントの階層構造は、このようになっています。PagesはTemplatesへの依存を持ち、TemplatesはOrganismsへの依存を持ち、OrganismsはMoleculesやAtomsへの依存を持つというように、上層のコンポーネントが下層のコンポーネントへの参照を持ちます。
逆に下層のコンポーネントは、上層のコンポーネントに依存できません。これにより、下層のコンポーネントの変更による上層のコンポーネントへの影響を抑えることができます。
ZOZOTOWN Androidでは、このAtomic Designをベースに、Composable設計ルールを制定しました。それぞれのコンポーネントについて、ZOZOTOWN Androidでどのように定義したかを説明していきます。
まずAtomsですが、Atomsは機能的に分割できる最小のUI要素です。ZOZOTOWN Androidでは、Text、Button、Row、Columnなど、Composeで提供されているComposable、また吹き出しやアイコンなど、ZOZOTOWN Android独自に作成したComposableのうち、それ以上分割できないものをAtomsとしました。
命名規則というよりは方針なのですが、すべてのアプリケーションで利用できるように可能な限り抽象的な名前としています。
次に、Moleculesです。Moleculesは、ユーザーに対して目的・動機を提供する最小のUI要素です。ZOZOTOWN Androidでは、TextやRowなどのAtomsを組み合わせて作成したComposableです。
命名に関しては、ユーザーが何を実現したいのかを表す名前とします。右の例だと、これはドロップダウンメニューです。ドロップダウンメニューは、Moleculesとして定義しています。
Organisms。Organismsは、独立して成立するコンテンツです。ZOZOTOWN Androidでは、Atoms、Molecules、そしてほかのOrganismsを組み合わせて作成したComposableを、Organismsと定義しています。命名に関しては、そこに表示する情報自体を表しました。
そして、Templates。Templatesは、ページのコンテンツ構造を明確にするオブジェクトです。ZOZOTOWN Androidでは、画面全体のレイアウトを管理し、各UI要素に必要なViewDataを分配する役割を持ったComposableがTemplatesとなっています。Templatesは、1画面に対して1つ作成することとしました。
命名に関しては、頭に画面名がきて、サフィックスにScreenがくるかたちにしました。
そして、Pagesです。Pagesは、実際のデータを画面に反映するオブジェクトです。ZOZOTOWN Androidでは、ViewModelへの依存、つまり動的なデータへの関心を持つComposableをPagesとしています。
また、先ほどのViewEventのところでも出てきたように、ViewModelに対してViewEventを発行するComposableも、このPagesです。
また、1つ下のレイヤーにあるコンポーネントであるTemplatesに、実際のデータを提供する役割も、このPagesのComposableが担っています。
命名に関しては、Templatesと同じように、画面名そしてサフィックスにScreenとなります。引数が違うかたちです。
ZOZOTOWN Androidのデバッグメニューの例では、このようになっています。TextやButtonは、Atoms。SpinnerはMolecules。そして、それらを束ねたものが、Organisms。画面全体がTemplates、またPagesとなります。
以上のように、Composable設計ルールを制定することで、2つ目の課題である、無秩序なComposable作成による、Composableの再利用性の低下、また可読性の低下という問題を解決しました。
まとめです。まず、ZOZOTOWN AndroidへJetpack Composeを導入しました。Compose導入のための課題を洗い出し、それぞれ解決していきました。
1つ目は、UIの状態管理、Eventの処理方法の見直しです。そして2つ目が、Atomic DesignをベースにしたComposable設計ルールの制定です。
今後の課題は、いくつかあります。1つ目は、UIの状態管理方法のルール化です。今回検討したUIの状態管理方法は、まだルール化まで至っていません。今後はチームでよりスムーズに開発を行っていくため、今回の検討内容をルールに落とし込んでいきたいと考えています。
2つ目は、より複雑な画面でのStateの扱いです。今後は、より大きく複雑な画面でComposeを使用して開発していくことを検討しているため、UIの状態管理に関して、今回検討した設計ではカバーできないユースケースの登場が考えられます。そういったユースケースへの対応も考えていきたいと思っています。
3つ目は、Composable設計ルールのブラッシュアップです。今回制定したルールを、実際にチームで運用して、よりZOZOTOWN Androidに適したかたちに変えていこうと考えています。
最後に、デザイナー・エンジニア間のユビキタス言語としてのAtomic Designの活用です。Composableの設計だけでなく、デザイナーとエンジニア間の共通言語として、Atomic Designを活用し、デザインに関するコミュニケーションをよりスムーズにしていきたいと考えています。これらの課題についても、今回のプロトタイプ実装とレビューを繰り返して行ったように、実装と検証を繰り返して改善していこうと考えています。
以上です。ありがとうございました。
関連タグ:
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.11
気づいたら借金、倒産して身ぐるみを剥がされる経営者 起業に「立派な動機」を求められる恐ろしさ
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.12
先週まで元気だったのに、突然辞める「びっくり退職」 退職代行サービスの影響も?上司と部下の“すれ違い”が起きる原因
2024.11.14
よってたかってハイリスクのビジネスモデルに仕立て上げるステークホルダー 「社会的理由」が求められる時代の起業戦略
2024.11.13
週3日働いて年収2,000万稼ぐ元印刷屋のおじさん 好きなことだけして楽に稼ぐ3つのパターン
2024.11.11
自分の「本質的な才能」が見つかる一番簡単な質問 他者から「すごい」と思われても意外と気づかないのが才能
2024.11.13
“退職者が出た時の会社の対応”を従業員は見ている 離職防止策の前に見つめ直したい、部下との向き合い方
2024.11.12
自分の人生にプラスに働く「イライラ」は才能 自分の強みや才能につながる“良いイライラ”を見分けるポイント
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
2024.11.11
気づいたら借金、倒産して身ぐるみを剥がされる経営者 起業に「立派な動機」を求められる恐ろしさ
2024.11.11
「退職代行」を使われた管理職の本音と葛藤 メディアで話題、利用者が右肩上がり…企業が置かれている現状とは
2024.11.18
20名の会社でGoogleの採用を真似するのはもったいない 人手不足の時代における「脱能力主義」のヒント
2024.11.12
先週まで元気だったのに、突然辞める「びっくり退職」 退職代行サービスの影響も?上司と部下の“すれ違い”が起きる原因
2024.11.14
よってたかってハイリスクのビジネスモデルに仕立て上げるステークホルダー 「社会的理由」が求められる時代の起業戦略