こんにちは。GMOメイクショップの黒木です。
弊社の makeshop というサービスでは、2024年12月11日(水)に新管理画面の注文詳細のリニューアルを行いました。
新注文詳細は、アーキテクチャから見直して、将来的なデザイン変更にも柔軟に対応できるような設計を目指しました。この記事では、そんな新注文詳細のアーキテクチャについて、詳しくご紹介します。
旧注文画面の課題
新注文詳細のアーキテクチャを紹介する前に、まず旧注文詳細が抱えていた課題についてお話しします。
今回、新注文詳細を実装するにあたり、ゼロから再実装する選択をしました。その理由は、旧注文詳細は密結合な設計となっており、変更を加えることが難しかったためです。
旧注文詳細の依存関係
以下は、Vue DevTools で確認した旧注文詳細の依存関係を示した図です。一目でわかる通り、多くのモジュールが複雑に依存しています。
コンポーザブルの依存関係が強すぎた
makeshop ではフロントエンドに Vue.js を採用し、ロジックをコンポーザブルとして切り出す設計をしています。
Vue.js 公式ガイドによれば、コンポーザブルは「状態を持つロジックをカプセル化して再利用するための関数」として使うことが定義されています。
Vue アプリケーションの文脈で「コンポーザブル(composable)」とは、Vue の Composition API を活用して状態を持つロジックをカプセル化して再利用するための関数です。
しかし、旧注文詳細では、API 通信や汎用メソッドまでもコンポーザブルに含めており、密結合な設計となっていました。そのため、特定のロジックを変更すると他の箇所にも影響が及ぶ可能性があり、手を加えるのが難しい状態でした。
新注文詳細のアーキテクチャ
この課題を踏まえて、新注文詳細はアーキテクチャから見直しを行い、ゼロから再実装を行いました。
アーキテクチャを考える上で重視した点
アーキテクチャを考える上で重視したことが、2つあります。
将来的なデザイン変更にも柔軟に対応できる構成
makeshop では、ショップ運営者様から日々寄せられるご要望に応じて、機能の改善を行っています。デザインに関するご要望も多く、新注文詳細リリース後も、さらに改修が求められる可能性が高いと考えられます。
そのため、今回の新注文詳細では、将来的なデザイン変更にも柔軟に対応できる設計を目指しました。その中で、これまでの課題であった密結合の設計を避け、可能な限り疎結合な設計にすることを重視しました。
Story に定義しやすい構成
makeshop では、UI カタログとして Storybook を採用しています。
旧注文詳細では、ページ描画時に API 通信が発生するため、Story に定義するにはモックデータを用意する必要があり、ややハードルが高い状態でした。
そこで、今回の設計ではモックデータを用意しなくても Story に定義できるように、アーキテクチャを工夫しました。
具体的なアーキテクチャ
以上の2点を踏まえて、コンポーネント設計では Container / Presentational パターンを、API 呼び出し設計では Repository パターンを採用しました。さらに、密結合になりがちだったコンポーザブルは、状態管理のみに責務を限定しました。
Container / Presentational パターン
旧注文詳細の課題を踏まえて、将来的なデザイン変更にも柔軟に対応しやすいという点から、Container / Presentational パターンを採用しました。
このデザインパターンは、ロジックを Container に、UI を Presentational に分離することで、関心の分離を図ることができます。これにより、デザイン変更が必要になった場合でも、ロジック部分(Container)を変更せずに、UI 部分(Presentational)を差し替えるだけで、デザイン変更が可能です。
さらに、Pages 層を新たに設け、モックデータなしで Story を定義できるようにしました。
この層は Atomic Design の "Pages" の概念に近く、最上部の Container をラップして API とやりとりをする役割を持ちます。
これにより、Pages 配下の Container を Story に定義することで、モックデータなしでページ全体を Storybook 上で確認できるようになります。
Repository パターン
これまで、コンポーザブルに定義されていた API 周りの処理を Repository パターンを用いて関心の分離を図りました。
しかし、makeshop は多機能であるがゆえに処理が複雑で、Repository パターンだけではその複雑な処理を完全に吸収することができませんでした。そのため、Service 層を追加し、DDD(ドメイン駆動設計)ライクな構成を採用しました。
また、これまでコンポーザブルに定義されていたリクエスト・レスポンスの整形処理は、Mapper 層を設け、Repository から呼び出す設計に変更しました。
これにより、肥大化・密結合になっていたコンポーザブルがシンプルになり、疎結合な設計を実現することができました。
コンポーザブル
コンポーザブルは、状態管理のみに責務を限定しました。
具体的には、これまでコンポーザブルに定義されていた処理を以下のように分離しています。
このように関心の分離を図ることで、コンポーザブルをよりシンプルに、より扱いやすくしました。
旧注文詳細と比べて
Vue DevTools で確認した新注文詳細の依存関係を示した図です。
Pages の依存関係
最上部のコンポーネントである Pages の依存関係です。旧注文詳細と比べて、はるかに依存関係が減ったことがわかります。
Pages 配下の Container の依存関係
Pages 配下の Container です。こちらも、かなり依存関係が減っていることが確認できます。
さらにより良い注文詳細にするために
今回、新注文詳細をリリースしましたが、これですべての課題が解決したわけではありません。まだまだ改善の余地があります。
そのためには、実際にご利用いただいているショップ運営者様の声を積極的に取り入れることが重要です。
今回採用した Container / Presentational パターン は、A/B テストが非常にしやすいデザインパターンです。この特徴を活かすことで、さらなる改善を目指すことができます。
A/B テストの例
例えば、複数の Presentational を用意して、ショップ運営者様に好きなデザインを選んでいただけるようにします。そして、どのデザインが最も多く使われているかを分析します。
こうした結果をもとに、継続的に改善を行うことで、さらに使いやすい注文詳細を作り上げていくことも可能だと考えています。
まとめ
今回は、新注文詳細のアーキテクチャについてご紹介しました。
アーキテクチャを見直したことで、新注文詳細は柔軟にデザイン変更できるようになりました。
今後は、ショップ運営者様からいただいたご要望をできるだけ早く取り入れられるように努めて参りたいと思います。