Featureディレクトリを深掘りする
featureディレクトリは機能単位でまとめていく。っていうすごい曖昧な記憶になっているので、もう少し深掘りして実際に使うパターンをイメージしながらまとめていこう。
Reactでコンポーネント設計するときにどんな機能やページ、コンポーネントごとのコラボレーションのパターンがあるか考える。
パターンの粒度は適当で思いつく限り出す。
- 複数のfeatureを1ページに表示(featureごとに干渉し合わない)
- 例)zennの本文とサイドバーのユーザー情報
- 複数のfeatureを1ページに表示(featureごとに干渉しあう)
- 例)zennの本文とサイドバーの目次
- 1つの機能だが複数ドメインの処理が含まれる
- 例1)Qiitaマイページのタブ
- 記事と質問は異なるドメインだと認識できそう
- 例2)zennのユーザーアイコンのドロップダウンリスト
- ログインもできるし、各種リンクへ遷移できる
- 1つの機能でたくさんのコンポーネントが組み合わさっている
- 例)VSCodeのサイドバーとエディタ部分
どんな感じの意見があるかな。
Google検索で引っかかった上位いくつか見てみる
- 機能単位でfeatureを切っている
- API周りのhooksはfeatureにおいている
- feature Aとfeature Bで同じAPIを叩くこともあるので、feature/hooksは他のfeatureから呼び出せる
- => ということはfeature同士の依存関係は基本なさそう
- ユーザー名の編集
- アバターの変更
- メールアドレスの編集
- お知らせの受け取り
これらを「設定」という機能として捉えるのか、各項目を一つの機能として捉えるのかに悩んでいます。
ディレクトリ構造にするとsettingsの中にnestさせるかどうかだけなのですが、下記のようになります。
確かに。この視点が結構難しい。
この方は、settings/のようなディレクトリ構造にせず、フラットに配置している。
理由はurl pathの構造にfeautreも引っ張られるから
- The Feature-Based Pattern: The Cornerstone of Scalable Folder Structure
- Fractal-Based Pattern: The Winner Among Folder Structure Patterns?
- Page-Based Pattern: Scalable Next JS Folder Structure
- Library-Based Pattern: Scalable NX mono repo Folder Structure
- Atomic Design Folder Structure: For Scalable React Applications
- Ducks Design Folder Structure: For organizing Redux-related code
↓ - 機能ベースのパターン: スケーラブルなフォルダ構造の礎石
- フラクタルベースのパターン: フォルダ構造パターンの勝者?
- ページベースのパターン スケーラブルな次のJSフォルダ構造
- ライブラリベースのパターン スケーラブルなNX mono repoフォルダ構造
- アトミックデザインのフォルダ構造 スケーラブルなReactアプリケーションのために
- Ducks Designのフォルダ構造: Redux関連コードの整理に
features/group/feature-nameのように機能のグループでまとめている。
例えば
- features/account/account-details
- features/account/account-list
_sharedのディレクトリ切るとわかりやすいな
- feature/feature-nameで切っている
- uiというディレクトリがあって、共通で使うuiをまとめている
- adapterディレクトリでapi周り管理している
- fetureを使うことで得られる恩恵
- 機能ごとに疎結合
- プロダクトにどんな機能があるかなんとなくわかる
- コンポーネントの命名に迷うことが減る
- これはfeature/componentは他から参照されないから命名をあまり限定的な名前にしなくていいから?
- ドメインを意識した開発を行える?
- featureは規模が小さいと逆に悩む時間が増えて大変
featuresディレクトリに関する記事のリンクたくさん
再現性
コード規約は、React の経験が最小限で最近入社したインターンを含む、チームのメンバーであれば誰でも簡単に再現できる、理解しやすいものである必要があります。
推論可能性
ほとんどの人は、たとえ暗記したとしても、そのすべての単語を暗記するつもりはありません。この規約が実際に機能するためには、チーム内の人々がコードを読むだけでリバース エンジニアリングできるように、規約が非常に明白で直感的であることが理想的です。完璧な世界では、コードのコメントと同様に、それをどこにも書き留める必要さえありません。コードと構造自体がドキュメントになります。
独立
複数人、特に複数チーム向けのコーディング構造ガイドラインの最も重要な要件の 1 つは、開発者が独立して作業できる方法を確立することです。複数の開発者が同じファイルで作業したり、チームが常に互いの責任領域に侵入したりすることは最も避けたいことです。
リファクタリング用に最適化
現代のフロントエンドの世界では、これが最も重要です。今日のフロントエンドは信じられないほど流動的です。パターン、フレームワーク、ベスト プラクティスは常に変化しています。それに加えて、今日では機能を迅速に提供することが求められています。いいえ、早いです。そして1か月後に完全に書き直します。そしてまた書き直すかもしれません。
したがって、コードを移動する方法がない恒久的な場所にコードを「貼り付ける」ことを強制しないことが、コーディング規約にとって非常に重要になります。リファクタリングが日常的に何気なく実行されるものであるように物事を整理する必要があります。規約が行うことのできる最悪のことは、リファクタリングが非常に困難で時間がかかり、誰もがリファクタリングを恐れるようになってしまうことです。代わりに、それは呼吸するのと同じくらい簡単であるべきです。
- featureのようだが、ディレクトリではなくnpm packageで切り出している
- importがわかりやすい
- commonのようなものが複数ディレクトリにできた場合でも、packageならどこからか明確にわかる
- リファクタリングの影響範囲を抑えられる。例えば、ディレクトリを変えたときにfromが変わらない
- packageに切る基準
- ボタンやツールチップなどの「デザインシステム」タイプのもの
- 「共有可能な」機能 - 複数の場所で使用できる機能
- 明確な境界を持ち、論理的で理想的には UI に表示される、独立した「機能」として説明できるもの
- 単一プロジェクト内のネストされたフォルダーの数を最大 3 つまたは 4 つに制限することを検討してください
Next.jsのApp routerで以下のルールだとpage.tsxがRSCなのでstateをもてないんだよな
- features以下はClient Component
- features同士は依存しない
- page.tsxはServer Compoenent
- page.tsxでfeatureの機能を組み合わせる
そうすると、検索バーで検索結果リストを表示する画面があるとする
fetureを以下で切ったとする
- 検索バー
- 検索結果リスト
この2つを使う場合、親コンポーネントがstateを持ち、検索バーへonChange関数を渡す。検索結果リストへはstateの値を渡す。
ただ、page.tsxはServer Componentなのでstateをもてない。
これはfeaturesを複数まとめる層を作らないといけない?
ディレクトリ名はケバブケースを推してるの多いな
案を考える
パターン1
featureを切るときの思考。
- 機能グループを切るか考える
- すでにあるグループに所属できそうかどうか
- 所属できないのであれば、機能グループを作成する
- 機能を切る
- 単体で動作できる最大の単位できる
機能グループとは何単位できるのか。
- d
機能を切るときの思考
-
単体で動作できる最大の単位できる
- これだと、全て1機能にできちゃう
-
features
- Auth
- LoginButton
- components
- hooks
- states
- types
- LoginButton.tsx
- index.ts
- LoginButton
- Service
- ServiceDetail
- components
- hooks
- states
- types
- ServiceDetail.tsx
- index.ts
- ServiceEdit
- components
- hooks
- states
- types
- ServiceEdit.tsx
- index.ts
- ServiceDetail
- Auth
featureを切る単位はプロジェクトごとに違うし、人ごとの感覚値で違う。
統一するために明確な切り方の指針を出すのは難しいので、このプロジェクトのこの機能は、このようにfeatureを切りました。っていう感じで指標となるものがあればそれと比較してfeatureを切る判断ができるのか?