サントリーウエルネス DX推進部エンジニアリングGの坂元です。プロダクト開発マネジメントやディレクションの業務を担当しております。
現在ComadoというNativeアプリの開発を担当しており、 この記事では「思い切ってNativeアプリのリファクタリングを実施した」を紹介したいと思います。
背景
Comadoは、サントリーウエルネスのお客様が無料でお使いいただける健康行動アプリとして、2022年10月からサービスの提供を開始しました。
開発はアジャイル手法のスクラムを採用し、4週間のスプリント単位でリリースを行なっております。 サービス開始後も開発は継続し、ユーザ体験向上に向けた企画の実現と顕在化している不具合に蓋をする日々を送っておりました。
スプリントを重ねる毎に、不具合の発生件数が増加し、同時に施策実現数が減少していくことで、徐々に開発の生産性の低下を感じるようになりました。
このまま開発を継続すると、取り返しのつかない状態になるという危機感を抱くようになり、開発は継続しながらも、問題の本質がどこにあるのか分析することにしました。
問題の本質は何か?
分析結果として、初期開発時の進め方によって、コード品質が大きく低下したと判断しました。
初期開発時はとにかくリリースを優先したため、ユーザーストーリー単位で開発を終わらせることを強く意識して進行しました。
簡易に実装することが優先されたため、ロジックの共通化や当初のアーキテクチャの構造に従うことを諦め、その結果技術的負債が蓄積されてしまいました。
当初のアーキテクチャの構造について
開発初期の頃に設計したアーキテクチャは、処理の一方通行化と依存性の脱却、テスト容易性、可読性の向上を目的とし、MVVMを基準にクリーンアーキテクチャの概念を導入しました。
アプリケーションの構成(As-Is)
Presenter(プレゼンテーション層)
画面と画面操作について受け持つ階層です。
Domain(ドメイン層)
ビジネスロジックとデータ入出力を受け持つ階層です。
Infrastructure(リポジトリ層)
外部通信や永続化データとのやりとりを受け持つ階層です。
技術的負債について
ドメイン層のUseCaseがリポジトリ層からのデータの入出力を受け持つだけの状態になり、プレゼンテーション層の間で素通りするだけの存在になっていました。
そのためリポジトリ層の成否について、UseCaseの代わりにViewModelがハンドリングしなくてはならず、そのためのコードがViewModel上で増加し続け、可読性を著しく低下させてしまいました。
リポジトリ層の結果についてアプリがどう振る舞うかは本来UseCaseが決めることでありますが、プレゼンテーション層とリポジトリ層が直接依存し合うことによりテストコードの実現も困難になってしまいました。
リファクタリングの決断
サービス開始後数ヶ月経ち、これから徐々にサービスを進化させていくフェーズで、リファクタリングを決断するのはとても難しかったです。
ただ将来のサービスの成長を見据えた時に、顧客体験の向上だけではなく開発者体験の向上も必要と考え、スプリント開発を数ヶ月凍結してでも、リファクタリングを決断しました。
リファクタリングの方向性
UseCaseの形骸化とViewModelの肥大化を解決し、ロジックの専属化を行うことで、コードの可読性向上とテストコードの導入を目指しました。そのために、当初のアーキテクチャ構造に変更点を加えました。
アーキテクチャの構造の変更点について
変更点として、ViewModelMapperという概念を新設し、UseCaseからViemodelへのデータマッピング・ロジックを務めるという役割を持たせました。
アプリケーションの構成(To-Be)
Mapperという概念について
MapperはDomainModelとViewModelを把握しており、1つの「画面仕様」の役割を担うことにしました。
Domainの引数は必要な処理と型を持つ抽象化されたMapperを指定し、MapperとDomainModelの型が一致すれば、結果がどうであろうと処理ができるという風にするのが1つの狙いです。そして、DomainはMapperに対して結果を通知しますが、Domainは結果がどうなろうと関係ないものとし、依存性を切り離しています。
本設計ではデータモデルの変換を担う側の処理(ViewModel)が肥大化することを回避し、画面仕様を担うロジック部分の責務を明確化する目的でドメイン層に対して逆向きの型の移動が発生しています。本来ドメイン層に問い合わせるレイヤーがそれぞれドメインの型に従うはずなので、クリーンアーキテクチャの原則は破っています。
リファクタリングで整理・改善されたこと
プレゼンテーション層とリポジトリ層の直接依存関係の状態をMapperにより分離したことで、テストコードが実現可能になりました。 また、肥大化したViewModelのロジックがMapperとUseCaseに分散されたことで、圧倒的に可読性は向上しました。
リファクタリングを通じて、画面仕様に関わるロジックを明確にできましたが、まだViewModelの表示に関わらないロジック処理が残っており、もう少しUseCaseを見直しできると考えています。
テストコードの実現もこれからとなるため、リファクタリング後に残っている課題も継続して取り組んでいきます。
おわりに
サントリーウエルネスでは、個客の課題だけではなく、ソフトウェアの課題にも向き合っています。 ビジネス・企画・開発がフラットな関係で、見える価値と見えない価値の両軸でものづくりをするように努力しています。
サントリーウエルネスでのものづくりに興味のある方は、ぜひ弊社の採用ホームページをご覧ください。
ビジョンに共感してもらえる仲間を募集中です。 よろしくお願いします。