Galapagos Tech Blog

株式会社ガラパゴスのメンバーによる技術ブログです。

FeatureFirstなディレクトリ構成に入門してみた

サービス開発パートナー事業部 アプリエンジニアチーム 自称Flutterエンジニアの務台です。 弊社が加入している関東ITS健康保険組合では、毎年恒例のディズニーチケット割引券の申し込みがスタートしました。被保険者、被扶養者であれば3000円引きでチケットが買えるので、興味のある方は申し込みをお忘れなく!

私が今まで経験したプロジェクトでは全てLayerFirstディレクトリ構成が採用されており、体感では同様のディレクトリ構成を使用している場合が多いのではないかと思います。 しかし、以下の記事で紹介したTodoアプリの作成にあたってはFeatureFirstディレクトリ構成を使ってみました。 techblog.glpgs.com

普段はLayerFirstなディレクトリ構成のプロジェクトを触ることが多い私が、FeatureFirstなディレクトリ構成を採用してみて感じたことを共有できればと思います。

また、以前作成したTodoアプリのリポジトリこちらです。 github.com

ディレクトリ構成

まずはそもそもLayerFirstとFeatureFirstとは何か、についてです。

LayerFirst

LayerFirstなディレクトリ構成とは、そのプロジェクトで採用しているアーキテクチャのレイヤに沿ってディレクトリを分割するという方法です。 Todoアプリの依存関係は以下のようになっています。

---
title: TodoApp Dependencies
---
flowchart TB
    subgraph Presentation
        Widget
        Notifier
        Widget --> Notifier
    end
    subgraph Domain
        Usecase
        ValueObject
        Usecase --> ValueObject
    end
    subgraph Repository
        TodoRepository
    end
    subgraph Data
        LocalData
    end
    Presentation --> Domain
    Repository --> Domain
    Repository --> Data

Todoアプリには4つの階層が存在しているので、それに沿ってディレクトリを作成すると以下のようになります。

lib
  |--data
  |    └--local_data
  |--domain
  |    |--usecase
  |    └--value_object
  |--presentation
  |    |--common_widget
  |    |--todo_create
  |    |    |--todo_create_screen.dart
  |    |    └--todo_create_notifier.dart
  |    |--todo_edit
  |    └--todo_list
  └--repository
      └--todo_repository.dart

このように、どの層に属するかに着目したディレクトリ構成を、LayerFirstなディレクトリ構成といいます。

FeatureFirst

FeatureFirstなディレクトリ構成とは、アプリ内での機能毎にディレクトリを分割するという方法です。 Todoアプリにおけるユースケースを考えると以下のものが挙げられます。

  • Todoを閲覧する
  • Todoを追加する
  • Todoを削除する
  • Todoを編集する

これを大まかにTodoの管理と捉え、アプリとして動作させるために必要な機能を加えると、 Todoアプリには以下のような機能が必要になりそうです。

  • Todoの管理
  • ルーティング
  • (ローカル)データの管理

これを踏まえて、必要なレイヤー等必要なものを追加すると以下のような構成になります。

lib
  └--feature
      |--local_data
      |    └--local_database.dart
      |--router
      └--todo
          |--domain
          |    |--usecase
          |    └--value_object
          |--presentation
          |    |--todo_create
          |    |    |--create_todo_notifier.dart
          |    |    └--todo_create_screen.dart
          |    |--todo_edit
          |    |--todo_list
          |    └--common_widget
          └--repository
              └--todo_repository.dart

このように、アプリの機能に着目してディレクトリを分割する方法を、FeatureFirstなディレクトリ構成といいます。

FeatureFirstにしてみた感想

これを採用してみての感想は、LayerFirstよりも保守しやすくなりそう!ということです。

なりそう!なので実際にどうなのかは分からないのですが、 保守の面で見ると以下の点が、LayerFirstより優れているのではと思います。

  • システムの改修は機能単位で来ることが多いため、どこに手をつければいいか分かりやすい
  • 修正すべきファイルが同じディレクトリにまとまっているため、修正漏れが起きにくい
  • 機能追加時は新しくディレクトリを作れば良いため、あまり影響範囲を意識しなくて良い

またFeatureFirstを使ってみて難しかった点として、オブジェクトが使用されるスコープを意識する必要があるというのがありました。

例えば、LayerFirstではdomainディレクトリにデータオブジェクトを入れておき、それをpresentationディレクトリから使用する、となると思います。 FeatureFirstでは、各機能毎にdomainpresentationディレクトリが存在するので、それぞれで必要なデータオブジェクトだけを、適切な場所に置く必要があります。

このように新しくクラスを作成する際はどこから使用されるか、を意識する必要があります。しかしこれによって関心の分離を意識せざるを得なくなるため、良い点でもあるのかなぁと思います。

まとめ

作成したTodoアプリにFeatureFirstなディレクトリ構成を採用してみました。 正直なところ、この規模のアプリではまだFeatureFirstなディレクトリ構成の恩恵を得ることはあまりできていませんが、アプリの規模が大きくなるにつれてありがたみが見えてくると思います。

ただ、ファイルの置き場所の判断には慣れが必要そうなので、今後もチャンスがあればFeatureFirstなディレクトリ構成を使っていきたいと思いました。