![見出し画像](https://assets.st-note.com/production/uploads/images/70744070/rectangle_large_type_2_62060a8eaa0c544b9d69888b01d69c40.png?width=1200)
atomic designへの理解
こんにちは。Showcase Gigプラットフォームチーム所属のryoです。
O:der Platformを開発して一年が経ちました。この一年間はatomic designを使って試行錯誤しながらプロダクトを作りまして、いろいろ勉強できたことがあります。 今日は、atomic designのatom、moleculeとorganismについて学んできたことをシェアーさせていただきます。
概要
atomic design)の定義は言うまでもなくて、小さい部品(component)を作って、それらを使って合成(composition)で複雑な部品とページを作成するデザイン方針です。
我々はサードパーティUIライブラリを使わず9割りぐらいの部品は自作で実装してプロダクトを作ったので、atom、moleculeとorganismの違いは一部理解できました。
例えば:
![](https://assets.st-note.com/img/1642995200184-AesKqObhMM.png)
atom
この部品は本当にatomであるかの判断基準は部品名を見たら頭の中にイメージが浮かんでくること、具体的に何をやっているかは単語1つ説明できること、もっと小さい部品を切り出せないことです。なぜなら。
イメージはすぐ思い出せるなら、その部品は主にUIの役割を果たしているのです。
単語1つで説明できるなら、その部品は一般的あるいは汎用的なもので、かつ多くの人々に分かりやすいものです。(9割り以上のケースでは単語1つで説明できます。単語が2ついる場合はそれがmoleculeであるかを考え直した方が良いです)
もっと細分化できないなら、その部品は最小粒度なのです。
例で説明すると:
簡単なselect
<!-- 案1 -->
<Select value={1}>
<Option value={1}>tokyo</Option>
<Option value={2}>osaka</Option>
</Select>
<!-- 案2 -->
<Select options={{1: "tokyo", 2: "osaka"}} value={1} />
select内に検索欄を追加
<!-- 案1 -->
<Select>
<SearchInput value={} onChange={} />
<Option value={1}>tokyo</Option>
<Option value={2}>osaka</Option>
</Select>
<!-- 案2 -->
<Select options={{1: "tokyo", 2: "osaka"}} searchValue={} onSearch={} />
option group追加
<!-- 案1 -->
<Select>
<SearchInput value={} onChange={} />
<OptionGroup>
<Option value={1}>tokyo<Image src="src1"></Option>
<Option value={2}>osaka<Image src="src2"></Option>
</OptionGroup>
</Select>
<!-- 案2 -->
<Select options={{
group1: {1: <>tokyo<Image src="src1"/></>,
2: <>tokyo<Image src="src2"></>
}}} searchValue={} onSearch={} />
案1はルールに従って実現はしてます。要するには、OCP(open closed principle)と似て、機能追加ならコードの修正(案2, selectの修正)より追加(案1, 粒度細かいatomの追加)の方がatomic designとの相性が良いです。 atomはUIの表現を豊にするため粒度を細かくしないといけないです。 ほかの例:Button, Tableなど。代表的なライブラリはもちろんreact-bootstrapです。(我々はほかのライブラリを参照してatomの名付けをしています)
molecule
moleculeはatomと比べると、粒度は荒くなってもっと専用な部品となります。 例で言うと:
<!-- 更新Form -->
<!-- 案1 -->
<UpdateForm>
<QuerySelect options={enterprises} onChange={enterpriseOnChange} searchValue={} onSearch={} />
<Input type="text" value={} onChange={} />
<SubmitButton onClick={} />
</UpdateForm>
<!-- 案2 -->
<UpdateForm>
<Select>
<SearchInput value={searchValue} onChange={} />
{
enterprises.map((option) => (
<Option value={option.value}>{option.label}</Option>
))
}
</Select>
<Input type="text" value={} onChange={} />
<SubmitButton onClick={} />
</UpdateForm>
複雑な機能を実現するのに簡単なatomを使ってもできるのですが、細かいタグはいっぱいで分かりづらくてメンテナンスもしにくくなります。 ですので、粒度を荒くする必要があります。 粒度は荒くなったため、部品内atomの動作とかstyleとかはすべてカスタマイズできなくなります。よって専用的な部品になります。 atomと似て、molecule名は単語2つで役割を説明できます。 例えば:DatePicker, TimePickerなど。(我々は汎用単語 + UI部品でmoleculeを名付けてます) 個人的には合成(composition)ではなく、主にプロパティで部品をカスタマイズするならそれはmoleculeです。 moleculeのライブラリ:react-select
organism
organismは主にビジネス上の役割を果たすので、APIの呼び出しを入れても問題ないです。 moleculeよりもっと専用的な部品ですので、分かりやすくするため我々はドメインエンティティ + α + UI部品の形で名付けをしてます。 例えば:企業を選ぶ部品をCompanyPickerと名付けてました。Company(ドメインエンティティ) + Picker(UI部品) 都道府県と市町村を選択する部品をPrefectureCascadingSelectと名付けました。Prefecture + Cascading(α) + Select 操作可能な部品は一個しかないなら、αがいらないです。複数があるとαはあった方が分かりやすいです。
例えば:cascadingだから複数selectがあることを連想できます。
organismなら必ずドメインエンティティが名前に入ってます。ないならそれはatomあるいはmoleculeの可能性が高いです。 それぞれのプロダクトにはドメインが違うので、代表的なライブラリはありません。
まとめ
UI向けなのでatomは粒度細かくする必要があります。APIはhtml寄りにしたらもっと馴染みやすいです。 moleculeとorganismは使いやすいという理由で粒度を荒くしてます。 atom、moleculeとorganismは分かりやすいためネーミングを使って名付けをしてます。 templateとpageについては整理がついたら別途でシェアーさせていただきます。 atomic designを採用しようとしているあるいはすでに使っている方々に役立つとうれしいです。
宣伝
Showcase Gigで急成長するプロダクトを一緒に作る仲間を募集しています!