SVO型のパッケージングで機能的凝集を目指すオニオンアーキテクチャ
#凝集度
from
パッケージング
SPAでのレイヤードアーキテクチャの考察と不確実性へのマインドセット
2023/05/26時点のNext.jsでパッケージングするならこうかな〜、というイメージ
ベースはオニオンアーキテクチャ (≒ 機能単位パッケージング)
前提
フロントエンドのコンポーネント設計
システムによって味づけ具合は異なる
Webサイト的か、Webアプリ的か、ツール的か
2023年以降のフロントエンド需要マッピング
コードスニペットはインターネットに溢れているのに対しコードベースはすべてユニーク
単純GUI,複雑GUIなどread, writeの比率
モードレスUI,モーダルUIなどのデザイン思想
どうでもいいことは流行に従い、重大なことは標準に従い、ドメインのことは自ら設計する
ドメインのことは考えながら作る(Write code thinking)ことを念頭においておく
原則
クールなURIは変わらない
スコープは小さいに越したことはない
状態設計から「なんとなく」を無くそう
主語->動詞->目的語(SVO)の流れを遵守する
App Routerの例
バックエンドもユースケースごとにコロケーションする
命名規則はプロジェクトごとによしなに
Layoutコンポーネントが、Rootがついてるserver componentコンポジションして配置の関心を閉じ込める
page, layoutと(たまにcontainer)で交通整理しておくと、ユースケースごとに関心を独立させられる
リソース直下のベース系
クライアントサイドでのキャッシュ管理でTanStack Queryを使う時は_apiを配置する
code:ts
/app
/Customers // 主語(リソース), URLに使われる
Customers.page.tsx // エントリポイント
Customers.layout.tsx // レイアウトコンポーネント (各領域ごとのコンテナの配置の関心を逃す
/_components // ユースケース横断で再利用するベースコンポーネント
/_form // ユースケース横断で再利用するベースフォーム
/show // 動詞(railsの7actionsに従うことが多い)
ShowCustomerRoot.tsx // server component, ユースケースのエントリポイント
/_components // client component, ユースケース内専用のコンポーネント
/api
/form
/new
NewCustomerRoot.tsx  
/_components
/api
/form
/edit
...
/Products
Products.page.tsx
Products.layout.tsx
/_components
/_form
/show
/list
/new
/edit
/destory
思想メモ
bulletproof-reactっぽさはあるけど個人的にfeatures的な切り方はしっくりこない
featureとユーザーのエントリポイント(集約(Aggregate))の単位は違うことが多くて、関心の千切りが起こりやすい
レイヤードアーキテクチャとオニオンアーキテクチャのディレクトリ構成の違い
レイヤ横断実装をなるべく減らしたい思いがある
10人いてもスケールする設計を目指したい
プロジェクト全体の構造としては、主語->動詞->目的語(SVO)の流れを遵守しつつ、機能固有の構造はBCD Designのように使い分けてるするのが大事
全体を俯瞰して捉えるときは主語が先にあるとわかりやすく、文脈が含まれる場合は目的が先にあると理解しやすい
RDBの構造と似てる。まず独立したエンティティを定義し、特定の文脈での関係性については後から別の領域で定義する
主語はWeb APIやモデル単位になることが多いかも(論理的にも物理的にも一致してる方がメンテしやすいよね)
この原則さえ守っていれば、それ以外の内側は実装詳細(private)になるので、厳しくルール化しない
_componentsはVercelの人がよくやってる慣習
@d151005: components のディレクトリ構成のベストは?Next.js の中の人的には今のところ
・全体で共有するものは /app の _components におく
・ページ固有のものはページディレクトリ内の _components におく
というのが良いらしい。_ 接頭辞によりルーティングから除外できる。
https://pbs.twimg.com/media/Fwc2-EraEAED5zR.jpg
DDD Trilemma
>Usecaseやdomainにどのような責務を持たせるかの議論は、まさにDDDのトリレンマの話ですべては両立できないので、チームで意志を持って決定する大切なポイントだと思います
CQSっぽくmutations, queriesで分けることもある
modelという抽象ではなく参照か更新かで分けたい
データ構造と振る舞いを切り離す
この辺の思想はDomain Modeling Made Functionalに多大な影響を受けている
システムの振る舞いを設計する際はコトに着眼する
綺麗にやろうとするとフレームワークのサポート必須なので難しいところはある
バッチングとかトランザクションとかコンカレンシーとか
単方向データフローにサーバーを含める
Cloudflare、App Routerならそろそろ大丈夫そう??
関連
永続化をエッジに押しやると、Repositoryパターンが不要になる
プレゼンテーション向けのストアをエッジに乗せつつクラサバの差分更新や同期を自動化したい妄想
ほか、参考
MVCから戦術的DDDまでの実装パターンの進化
FlutterでBLoCだChangeNotifierと振り回されて消耗するまえに
--
ReactなどのGUI開発に対応したスケーラブルなファイル構造
/fsubal/React プロジェクトのディレクトリ構成
/tosuke/フロントエンド(React)のディレクトリ構成
無理に共通化はせずにむしろfeaturesごとに別のプロダクトを作るような気持ちでそれぞれを最適化していくという思想
フロントエンドのディレクトリ設計思想 - Speaker Deck