AtomicDesignに辟易したキミへ
こんにちは、ゆとです。
ぼく自身、Nuxt2系時代にAtomicDesignをめちゃくちゃ厳格にやっていた時期があるんですよね。最初は「おお、すごく美しい!」とテンション上がったんですが、やっていくうちに分割が細かくなりすぎて「あれ? どこに置いてたっけ?」なんて、ちょっと煩わしくなることもあったんです…。
しかも新しいメンバーがジョインするたびに「Atomsってなんだっけ? Moleculesは?」って説明するのも正直ちょっと大変でした。
そんなこんなで、「もう少しスピード上げたいし、新人にも優しい構成にしたい!」って思ったこと、ありませんか?
今回は「ぼくが次に取り入れるとしたらこうするかも」というコンポーネント設計のアイデアをまとめてみました。ちょうどNext.jsへ移行する前提でのお話です。もしよかったら、新しい設計のヒントにしてみませんか?
1. Feature-driven (機能別) ディレクトリ構成
ざっくりイメージ
src
┣── features
│ ┣── auth
│ │ ┣── components
│ │ ┣── hooks
│ │ ┗── pages
│ ┣── user
│ │ ┣── components
│ │ ┗── hooks
│ ... ...
┗── shared
┣── components
┣── utils
┗── hooks
ぼくも最近、新サービスの試作でやってみたんですが、機能ごとにまとまってるので開発効率が思ったより上がったんですよね。
-
メリット
-
新メンバーも機能単位で把握しやすい
- 「まずAuthまわりを修正したいなら
auth
ディレクトリ見ればいいんだ!」と迷いにくいんです。
- 「まずAuthまわりを修正したいなら
-
独立性が高い
- ある機能を追加しても他機能への影響が最小限で済むので、並行開発もしやすいですよね。
-
新メンバーも機能単位で把握しやすい
-
デメリット
-
共通化の微妙な境界に悩む
- 「あれ、これ共通化する? でもちょっとだけ違う…」という判断はそこそこ必要。
-
ディレクトリ構造が大きくなりがち
- 大規模になると、機能フォルダがどんどん増えて視認性が落ちないよう注意が必要です。
-
共通化の微妙な境界に悩む
ぼくは個人的に機能別構成がいちばんおすすめなんですが、ちょっと気になる方は下記の設計手法も見ていきましょう。
2. Presentational / Container 分割(Smart / Dumbパターン)
ざっくり言うと
- Presentationalコンポーネント: UIと見た目に特化
- Containerコンポーネント: データ取得やビジネスロジックに特化
この考え方、実はReact界隈では結構スタンダードなんですよね。たとえば、Next.jsのpage
はContainer的に扱って、その中でUIコンポーネントを呼び出すイメージです。
-
メリット
-
責務がクリア
- 「このコンポーネントはUI担当、こっちはロジック担当だね」と判断しやすいんです。
-
再利用しやすい
- Presentationalはデザインだけ担当してるから、他のページでも流用しやすいんですよね。
-
責務がクリア
-
デメリット
-
粒度の設定が難しい
- 「どこまでPresentationalにする? どこまでContainerに持たせる?」の判断が慣れるまでちょっと大変。
-
状態管理をどこに置くか
- React QueryやReduxなどを絡めるなら、その接続はContainer側? Presentational側? と迷いがちです。
-
粒度の設定が難しい
アトミックほど細かくないけれど、一定の保守性がほしい場合はこの「責務分離」をゆるやかに採用してみるといいかなと思うんです。
3. UIライブラリ / Design Systemを使ってサクサク開発
たとえばChakra UIやTailwind CSS、あるいはMaterial UIなんかを使ってみると、UIデザインを一から作り込むより時短になります。ぼくもTailwindを導入してみた時は、パッと見た目を整えられるし、新メンバーも「このクラスつければ色が変わる!」とすぐ理解できて、なかなか好評でした。
-
メリット
-
デザイン統一がしやすい
- 同じライブラリの同じスタイルを使い回すだけなので、全体的な見た目が揃います。
-
開発効率UP
- 一からコンポーネントを作るよりも、パズルみたいに既存パーツを組み合わせるだけでそれっぽく仕上がります。
-
デザイン統一がしやすい
-
デメリット
-
カスタマイズの難しさ
- 細かいデザインを変えたいとき、ライブラリのルールとケンカするとちょっと面倒かも。
-
バージョンアップの追従
- ライブラリのメジャーアップデートが来ると、プロジェクト改修が必要になる場合もあるんです。
-
カスタマイズの難しさ
このアプローチはAtomicDesignほどは厳格にしないかわりに、ライブラリがもともと提供しているスタイルガイドに乗っかるイメージです。「スピード重視でとにかくUIを素早く作りたい!」というときには最強の選択肢かなと思っています。
4. DDD(Domain-driven Design)的な発想で整理
これはぼくが以前、バックエンド寄りの複雑な業務ロジックを持ったフロントアプリを作るときに少しだけ取り入れた考え方なんですよ。フロントにも「ドメイン」「ユースケース」みたいな概念を導入して、ビジネスロジックをしっかり整理したんです。保守はかなり楽になりました。
-
メリット
-
大規模化しても破綻しにくい
- ロジックが整理されていれば「この機能を直すならここを見る」という流れがとてもわかりやすいんです。
-
チーム内の共通言語ができる
- 「これ、どのエンティティ? どのユースケース?」みたいな話ができるので、混乱しにくいですよね。
-
大規模化しても破綻しにくい
-
デメリット
-
学習コストが高い
- DDDの知識がないメンバーだと、概念に慣れるまで時間がかかります。
-
小規模ならオーバーエンジニアリング
- 小さいアプリでは「そこまで厳密にしなくてもいいのに…」と若干面倒に感じるかもしれません。
-
学習コストが高い
もし業務ロジックが複雑なアプリをNext.jsで作るなら、DDD風のディレクトリ構成にしてみるのはアリかもしれません。ただ、いきなり全部は大変なので、ポイントをおさえつつ柔軟に使うのがおすすめですね。
5. 結論:自分たちに合ったバランスが大事
① 「機能別(Feature-driven)構成」+「UIライブラリ」が、スピード重視かつそこそこ保守性も欲しいケースではわりとベストバランスかなと感じました。
② さらに「Presentational / Container」の分離で責務をもう少し明確にしてみるのもアリです。
③ 「複雑なドメインロジックを扱う」ならDDD風を取り入れるのもよさそうです。
要は、アトミックデザインみたいに分割を厳密にしすぎなくても、機能単位&UIライブラリでじゅうぶん管理しやすいよってことです。新メンバーも「このフォルダだけ見れば機能がわかる」という状態を作れれば、オンボーディングがぐっと楽になりますよね。
6. まとめ & ぼくからの提案
- AtomicDesignにちょっと疲れた… という方は、とりあえずFeature-drivenにしてみてはいかがでしょう?
- そこにUIライブラリ(Chakra UI/Tailwind/Material UIなど)を組み合わせると、開発スピードはかなり上がると思います。
- 「いや、うちのロジックめちゃくちゃ複雑なんだよね」という場合は、DDD的アプローチを選択肢に入れてみましょう。
ぼく自身も、ここ最近はFeature-drivenに落ち着いてまして、全体感がつかみやすいのが魅力だと改めて感じています。もしまだ迷いがあれば、一度小規模な部分だけ切り出して実験してみませんか? 「あ、この構成ラクかも」と思えたら、一気に全体へ適用する流れがおすすめです。
どうですか? 少しでも参考になったら幸いです。ぜひあなたのチームでもAtomicDesign以外の設計を試してみて、次のプロジェクトをもっとスムーズに仕上げてみましょう!
Discussion