🌈

featuresディレクトリに学ぶディレクトリ構成の考え方

に公開

React界では数年前にfeaturesディレクトリというディレクトリ構成が登場しました。

featuresディレクトリとは一つのディレクトリ構成の方法です。機能単位(feature)でコードを整理する方法で、featuresというディレクトリを作成します。

以下のような構成となります。

日本ではこちらの記事がその火付け役だったんじゃないでしょうか。

https://zenn.dev/manalink_dev/articles/bulletproof-react-is-best-architecture

他にもfeaturesディレクトリについてたくさんの記事が書かれ、多くのプロジェクトで採用されていると思います。私も採用しています。つまり一時的な流行ではなくエンジニアに受け入れられたアイディアだと思っています。

この記事では、なぜfeaturesディレクトリがなぜエンジニアに受け入れられたのかを考察し、フロントエンドだけではく一般化したディレクトリ構成を考え方を検討してみたいと思います。

ディレクトリ構成 = コードの属性とその優先順位

featuresディレクトリが登場する以前のReactプロジェクトでは、次のようなディレクトリ構成が多かったと思います。

このディレクトリ構成は、コードを言語の構文やライブラリーの使用方法など、コードのパターンに着目して分類したものでした。

一方、featuresディレクトリでは、最初にコードがどの機能に関わっているのかに着目して分類します。

featuresディレクトリの登場により、コードがもつ色々な属性のうちどの属性に着目するのかという視点の数だけディレクトリの切り方が考えられるということを私は学びました。そして、ディレクトリはネストした構造を持つことができるので、着目するコードの属性の数とその優先順位によって、ディレクトリ構成のルールが考えられます。

ルール パス
パターンに着目 src/パターン名/様々な機能が混ざったコードのファイル
機能に着目 src/機能名/様々なパターンが混ざったコードのファイル
機能、パターンの順に着目する src/features/機能名/パターン/機能、パターンで整理されたファイル

featuresディレクトリがなぜエンジニアに受け入れられたのか

2つの理由があったと考えています。

  • 開発作業は機能単位で管理されているケースが多い
  • パスが適切に分散するのでファイルが探しやすい

開発作業は機能単位で管理されているケースが多い

featuresディレクトリにはさまざまなメリットがありますが、機能単位で考えることが開発チームにとって自然だったからfeaturesディレクトリが広まったのではないかと私は考えています。

アプリケーション開発では特定のパターンに着目したPRより、機能やバグに着目したPRの方が多くが作られます。そのため作業、PR、レビューにおいて、featuresディレクトリによる構成は自然だと感じられます。

もしも将来、機能とパターン以外のコードの属性としてAという属性に着目してディレクトリ構成を検討するとします。開発作業で考慮する優先順位が「機能 > A > パターン」である場合、ディレクトリ構成はfeatures/機能名/A/パターン名とすることでより開発しやすいディレクトリ構成に発展するかもしれません。

パスが適切に分散するのでファイルが探しやすい

featuresディレクトリが登場する以前のディレクトリ構成の問題として、例えばcomponentsディレクトリ以下が完全にフラットだと、ファイルの命名ルールを追加しない限りは目的のファイルを探すことが非常に困難となります。

featuresディレクトリでは、機能名、パターン名というディレクトリが切られることでパスが分散します。その粒度がちょうどよいと感じます。私の関わっているプロジェクトである機能名、あるパターン名のディレクトリを開いたときに10を超えるファイルが格納されている、というケースはほとんどありません。それだけファイルを把握し易くなりました。

再び機能とパターン以外のコードの属性としてAという属性に着目してディレクトリ構成を検討するとして、開発作業で考慮する優先順位が「機能 > A = パターン」である場合は、パターンとAでどちらがより分散するか、という視点でディレクトリ構成を決めても良いかもしれません。

実際の運用について

私はfeaturesディレクトリを採用していますが、その他の細かな部分についても書いておきます。

私は機能名のディレクトリに4〜5ファイルぐらいまでなら、componentsなどのコードのパターンをまとめたディレクトリを作らない運用をしています。理由は機能の関連するファイル構成の全体像を把握しやすいと感じるためです。

また以前は 1ファイル1コンポーネントというeslintのルールを採用していましたが、やめました。例えば親子関係のある2つのコンポーネントが1つのファイルに書かれている方が分かりやすいケースがあります。そのため現在では柔軟に判断しています。この判断は、以下の記事の言葉を拝借させていただくと「切り出しのオーバーヘッドを気にする」ためです。

https://zenn.dev/kohii/articles/2c1126389d914a#切り出しのオーバーヘッドを気にする

まとめ

同時に関心を向けるファイルをより近い場所に配置することが作業効率化につながりますが、開発チームにとって重要な関心ごとが「機能」であることに気がついたことから、featuresディレクトリが広まったのだと思います。

featuresディレクトリに不満を感じることがあるなら、何に関心を向けているのか、向けたいのか考えましょう。

不満の先にある概念に気がつくことができれば、それがディレクトリ構成のさらなるブラッシュアップのチャンスかもしれません。

Discussion