はじめに
はじめまして、1年半ほど前からプログラミングを学習しているものです。
現在開発中のWebアプリでアトミックデザインを採用して進めていましたが、作り直しに近い形でリファクタリングを始めることにしました。
今回はなぜそう思い立ったのかと今後の方向性について書いていこうと思います。
これまでの経緯
Reactを最初に学んだときに知ったのが、アトミックデザインであり、これがディレクトリ構成の基本なんだと思い、あまり自分の頭で考えることなく、これに従って進めていきました。
厳密に言えば、atomsはchakraUIを用いていたため使ってはおらず、chakraUIで成り立つ複数コンポーネントを取りまとめたものをmoleculesとし、それをimportして使っていました。
templateとmoleculesを当初分けていましたがそれぞれの違いがよくわからなくなってしまったので、画面を構成する汎用的なコンポーネントの集まりをmoleculesとしてtemplateは使わずに進めていきました。
顧客の新規登録など1ページを構成するものをorganismsとして進めました。
以下がディレクトリ構成のイメージです。
src/
├─ components/
│ ├─ molecules/
│ │ ├─ Input/
│ │ │ ├─ InputArea/
│ │ │ ├─ Form/
│ │ │ │ ├─ InputText/
│ │ │ │ ├─ InputNumber/
│ ├─ organisms/
│ │ ├─ Input/
│ │ │ ├─ PartnerInput/
│ │ │ ├─ ItemInput/
├─ hooks/
├─ functions/
よかった点
organismsは機能が担うコンポーネント、moleculesは見た目だけを担うと分けて実装ができました。
そのためなにかロジック周りで不具合があった際には、organismsをまず見にいけばいいという整理ができていました。
反省点
1つのコンポーネントで共通化しようとしすぎた
当初すべてのコンポーネントがバラバラであり、フォームの実装において、大量のuseStateを用いており、パフォーマンスも悪い状態でした。
もう少し共通化したほうがいいよという指摘を先輩エンジニアから受け、react hook formを導入するタイミングで、フォームに関わるコンポーネントをその後、がっつり共通化を進めました。
その際、フォームに関するカード・タイトル・ボタンまでをも、1つのコンポーネントとしてすべて共通化してしまったため、
新規登録画面に出したい「新規登録ボタン」と「キャンセルボタン」と、
編集画面に出したい「保存ボタン」と「キャンセルボタン」と「削除ボタン」ををすべて三項演算子を用いて出し分けを行っていきました。
フォームの種類は依頼主・お届け先・商品・注文・送状・まとめて登録と6通りあり、これをなるべく共通化するようにしてしまったことで、条件分岐だらけになってしまい、とてもわかりづらいコードになってしまいました。
ロジックを外に出さずに直接書いてしまった
organismsにロジックを直接書いてしまったことで、前半100行くらいCRUD処理に関わるコードが埋め尽くすようになっていました。
これもコードが見づらくなってしまった要因となっており、リファクタリングしようにも、各organismsのコンポーネント内で各々が書いたロジックがコンポーネントにへばりついているため、この状態でコンポーネントから切り離すのは骨の折れる作業となり断念しました。
さらに、organismsに書くとまずそうだなと気づき、開発終盤に追加が必要になったものはfunctionやhooksディレクトリを作って外に切り出しました。
これにより、organismsにロジックと外に切り出したロジックは時間経過以外の違いを持たず、これもなんとも分かりづらい要因となりました。
解決したいこと
そのため、整理すると以下のようなことを解決していきたいと思いました。
- 画面それぞれで微妙に異なる表示の出しわけをなるべくわかりやすく書いていきたい。
- コンポーネントから関数やhooksを分離させ、見通しをよくしたい
- 単体テストを導入しやすい単位にコンポーネントのサイズを最適化したい。
本来どうあるべきなのかを調べてみる
上記の課題を解決するために、改めてアトミックデザインでディレクトリ構成を考えるのならば、どのような形がよかったのかを調べ始めました。
さっそくググって最新の記事を探しているとアトミックデザインを辞めた発信が多いのに気づきました。
コードの稚拙さはあるものの、
アトミックデザインで苦労しているのは自分だけではないことがわかり、少し安心しました。笑
ハードルの高そうなアトミックデザインは一旦置いておき、改めてどのようなディレクトリ構成がメンテナンスしやすいのか情報を集めてみることにしました。
記事を探しても、なかなかうまく理解できなかったため、
すでにエンジニアとして働いている仲間に相談をしてみると、コロケーションというなるべく近くに配置する考え方があることを教えてもらいました。
存在する機能やドメイン単位でディレクトリを分けていき、その機能に関わるhooksなどは近くに置くというものでした。
イメージとしては以下のようなものです。
src/
├─ features/
│ ├─ items/
│ │ ├─ components/
│ │ │ ├─ ItemCreate/
│ │ │ ├─ ItemEdit/
│ │ ├─ hooks/
│ │ ├─ functions/
│ ├─ partners/
├─ components/
│ ├─ button/
│ ├─ form/
├─ hooks/
├─ functions/
実際に書き始めましたが、対象範囲が限定されることで、types.tsから対象の型定義を見つける場合に、億劫になっていた気持ちや、対象のロジックを切り出すときに、名前や配置場所に悩むことが減りました。
これにより、少しだけコードが書きやすくなったような気がします。笑
まだまだ書き直し始めたばかりのため、やってみての振り返りはあまりできませんが、
いったんこれで進めてみて、しばらく進んだらまた振り返りをしてみようと思います。