フロントエンドにクリーンアーキテクチャを導入

ちゃんとしたクリーンアーキテクチャというよりはそれっぽくした話です。

きっかけ

フロントエンドの実装をあまりしないのですが、プロジェクトで担当することになりました。 以前関わった別のプロジェクトでのフロントエンドの実装は、特に設計方針とかアーキテクチャとかをちゃんと決めずに進めた結果、画面のどの処理をどのファイルに実装したかなどを追うのが辛い状態になりました。 そんな経験があり、アーキテクチャをどうしようかと困ったときに調べてみたところ、クリーンアーキテクチャでの事例があったので導入しました。

フロントエンドの技術要素

以下

  • Vue.js
  • Vuetify
  • Twilio Video Client
  • その他諸々

ディレクトリ構成

project/
├── public
│   └── index.html
├── src/
│   ├── assets/
│   ├── components/
│   │   ├── atoms/
│   │   ├── molecules/
│   │   ├── organisms/
│   │   ├── templates/
│   │   └── pages/
│   ├── domain/
│   │   ├── repository/
│   ├── infrastructure/
│   │   ├── datamodel/
│   │   │   ├── api/
│   │   │   └── twilio/
│   │   ├── driver/
│   │   │   ├── api/
│   │   │   └── twilio/
│   │   └── inmemorystorage/
│   │       ├── twiliotextchat/
│   │       └── twiliovideo/
│   ├── service/
│   ├── main.ts
│   ├── plugins/
│   ├── repository/
│   ├── router/
│   │   └── index.ts
│   ├── App.vue
├── babel.config.js
├── tsconfig.json
├── tslint.json
├── vue.config.js
├── package.json
├── package-lock.json
└── README.md

クリーンアーキテクチャのレイヤーに合わせた考えるとこんな感じです

  • Entities → project/src/domain
    • 画面で扱いたい概念などをクラスとして表現
  • Presenters → project/src/components
    • domainを画面に反映
  • Use Case → project/src/service
    • だいたい画面の操作ごとにメソッドを実装
  • Interface Adapters → project/src/repository
    • 外部のデータをフロントエンドで扱いたいクラスに変換
  • infrastructure → project/src/driver, inmemorystorage
    • 外部とのデータ通信

良かったこと

  • どのような処理をどのレイヤーに存在させるか決まっているので実装を追いやすい
  • ソースコードをメンテしやすい

悩ましいこと

  • 一部の描画処理をinfrastructureで行っている。その描画処理はSDK(Twilio Video Client)に依存するので、移動させたいが難しい