Help us understand the problem. What is going on with this article?

Atomic Design(アトミックデザイン)をプロダクトに適用するとこうなった

ちゃお!関西系ギャル(30代男性)のたくおやで。
今日はワイが魂と交換して手にいれた「Atomic Design(以下アトミックデザイン)をプロダクトに適用するとこうなった」を語らせてもらうで。

ちなみにたくおはスタートアップでプロダクトオーナー兼プロジェクトマネージャー兼プログラマー兼デザイナー兼インフラエンジニア兼保守・運用を1人でしてるから同じような境遇の人にはきっとめっちゃ有益やでっ!!
なお、これは正しい意味でのアトミックデザインではないので、もし本当に正しい意味でのアトミックデザインの知識をお求めの場合はお近くのQiitaでちゃんとした記事を見てくださいなんやで。

汗と涙と血反吐を垂れながしながら体得したプロジェクトから得たとあるひとつの実践的なアトミックデザインの運用方法です。(妥協の産物とも言う)

アトミックデザインとは

まずは教科書に書いている内容のカンタンなおさらいね

  • atoms
    抽象化したコンポーネント。コンポーネントの最小単位でコレを組み合わせてさらに大きなコンポーネントを作っていく。

  • molecules
    上記のatomsおよびmoleculesを組み合わせてコンポーネントを作る。意味のある単位のコンポーネントだけどまだ抽象的。

  • organisms
    atoms,moleculesならびにorganisms自身を組みあわせて作る単一の具体的な意味のあるコンポーネント。

  • templates
    その名のとおりテンプレート。骨組み。

  • pages
    ユーザが実際に見るページ。コンテンツを適用する。密結合&再利用不可前提やで。

オーケーGoogle。日本語でおk。

おわかりいただけるだろうか?
ワイは最初読んだときサッパリでしたよ。

上記を学習して自分なりに解釈して実際にプロダクトへ反映していった結果、上記の原理原則を一部破っていってしまいましたので、
スゴいツヨツヨエンジニアとアトミックデザイン原理主義の方は怒らないでくださいお願いします納期の都合上しかたなかったんですボクは悪くないんです!!

さて、自己弁護もしっかりしたので、実際にプロジェクトに適用していくとどうなるか具体例とともに見ていきましょう。

atoms

最小単位のコンポーネントだが具体的に作ってOK。
ただし、テストしやすいようにするためとある操作をしたらかならずその状態になるように設計するんやで。

atoms/before.jsx
export const Button = (props) => {
  return (
    <button onClick={ props.clickFn }>
      { props.label }
    </button>
  )
}
atoms/after.jsx
export const TsukkomiButton = (props) => {
  return (
    <button onClick={ e => props.nandeyanen() }>
      なんでやねん
    </button>
  )
}

さっそく「なんでやねん。再利用でけへんやないかっ!!」っと問われそうだが、まさにそれを狙っている。
このatomの名前を見てそっこうで使いかたを推測できたのではないだろうか??
そして、実際のビジネス欲求(という名の無茶振り)ではリアルタイム(という名の納期延長不可)制が求められるのでパッと見でわかるというのは非常に重要なんやで。

さらに言うとわいは君らに逆に突っ込みたい。

「本当にプロジェクトを跨いでコンポーネントを再利用したことがあるのか?」

本当に再利用するならatomsとか言うかわいらしい世界に閉じこめておらず、
堂々とnpmパッケージにするなり、スニペットに登録するなり自分用githubにアップするなりするのがエンジニア道というもんや。
そんなイケてるナイスな抽象化したものが作れた日にはOSSにしたるのがホントのクリエイターっちゅうもんやろっ
つまりプロジェクトってのはプロダクトのためにあるんやっ!!
最適化するためatomsは具体的実装でかまへんのやっ!!(暴論)

っと少々熱くなってしまいましたが、なんとなくメリットを理解していただけましたでしょうか??
ついでなメリットですが、あまりにも具体化されているのでテストめっちゃ書きやすいです。

__test__/atoms/after_test.jsx
describe("TsukkomiButton", () => {
  it("ツッコんだら大爆笑", () => {
    /* 成功するパターン */
  }

  it("スベった", () => {
    /* 失敗するパターン */
  })
})

ここまで具体的なテストやったらプロジェクトのコード完全理解したマンになれるで。

molecules

意味のあるコンポーネントを作成する。
ただし、テストしやすいようにするためとある操作をしたらかならずその状態になるように設計するんやで。

molecules/before.jsx
import { Label } from "../atoms/label"
import { Input } from "../atoms/input"

export const Search = (props) => {
  return (
    <div>
      <Label>
        { props.label }
      </Label>
      <Input
        onChange={ props.inputFn }
        placeholder={ props.hint }
      />
      <Button onClick={ props.submit } label={ props.buttonName } />
    </diV>
  )
}
molecules/after.jsx
import { OkanLabel } from "../atoms/okan_label"
import { OkanInput } from "../atoms/okan_input"
import { OkanButton } from "../atoms/okan_button"

export const SayOkan = (props) => {
  return (
    <div>
      <OkanLabel />
      <OkanInput />
      <OkanButton />
    </div>
  )
}


// importしてるatomsたち
export const OkanLabel = () => <label>おかんのありがたい名言を入力してください</label>
export const OkanInput = (props) => <input onChange={ e => props.okanTheFn(e.target.value) } placeholder="例: たくお、あんたが秘密にしてた本、机に並べといたで"/>
export const OkanButton = () => <button>J( 'ー`)し</button>

ワイもよく指摘されるけど「あんたの話、主語ないからわかりづらいねんっ!!」って言われるじゃん?
まさにbeforeのほうはそれで、「検索するのはわかった。んで何をや??(威圧)」となれへん??

その点afterは「おかんが言う」というのを明確に表わしていますやん。
もうおかんが必要な箇所以外では絶対に使えへんやん??

後述するorganismsと何がちゃうん??ってよく言われますが、すごく簡単な指針があります。
moleculesはヘルパーである。あくまでヘルパーである。

「カーチャン…僕の秘密にしておいた本を並べておくなんて、ナイスヘルパーだよ……(涙)」

organisms

でっかい部品。とにかくどこに置くか迷ったらまずここにつくる。
作ったあとにatoms/moleculesに適切に振り分けたらいいだけの話なのでここからつくる。

最初から完璧にしようとしてはいけません。かの神様も世界を創造するのに1週間もかかったのだ。
我々人間ごときがたった数日で完璧にしようとするのもおこがましいのである。

というわけで、とにかく迷ったらここにつくればヨロシのです。
ただし、テストしやすいようにするためとある操作をしたらかならずその状態になるように設計するんやで。

organisms/before.jsx
import { Search } from "../molecules/search"
import { List } from "../molecules/list"
import { InputForm } from "../molecules/input_form"

export const Posts = (props) => {
  return (
    <div>
      <Search { ...props } />
      <List { ...props } />
      <InputForm { ...props } />
    </div>
  )
}
organisms/after.jsx
import { OkanSearch } from "../molecules/okan_search"
import { OkanSaid } from "../molecules/okan_said"
import { SayOkan } from "../molecules/say_okan"

export const OkanSerifs = (props) => {
  return (
    <div>
      <OkanSearch { ...props } />
      <OkanSaid { ...props } />
      <SayOkan { ...props } />
    </div>
  )
}

役割はmoleculesと被る部分がおおいですが粒度が全く違います。
moleculesのときはオカンが喋るだけでしたが、こんかいは喋る上にありがてぇお言葉と検索機能までついてますね。

ちなみにここまで具体的だと後続するtemplatesから先の工程が一気にラクになります。
というかここまで抽象的だと後続するtemplatesから先の工程が一気に具体化させないといけないため、カオスコードになります。

どちらがいいかは人それぞれですが、3歩歩くと忘れてしまう鳥頭なたくおは前者がいいです。3行以上のコードを頭に入れるとswap発生するので。

templates

ユーザが実際に見るページ。だけどデータはすべて外部から注入するんやでぇ!
ただし、テストしやすいようにするためとある操作をしたらかならずその状態になるように設計するんやで。

ここからはbeforeが書きにくいので、具体的なサンプルコードのみ用意してます。
(けっ決してメンドくさくなったからだとかじゃないんだからねっ…/// か、かんちがいしないでよねっ…!! ><)

templates/okan_template.jsx
const OkanTemplate = (props) => {
  <div>
    <Header { ...props } />
    <Navigation { ...props } />
    <OkanSerifs { ...props } />
    <Footer { ...props } />
  </div>
}

ステキですねぇ…ページができあがっちゃいましたねぇ…
しかも超なにしたいかわかりやすくないっすかっ!?
もう僕これ何のページかわかりますもん。おかんのページでしょ。おかん。

ちなみに、XDなんて軟派なツールを使わない猛者は、organismsではなくここから実際のコードを書いてプロトタイプ作っていってもいいと思います。
(XD使うよりコーディングしてプロトタイプ作ったほうがはやい派です。XDの学習をサボってるわけちゃうで。ほんとやで。うそじゃないよー(棒読み))

pages

ReduxのconnectとかReact hooksのcontextをここで使って実際にデータと繋げる。
ビュー関連のコンポーネントはtemplates以外importしない。

そしてここからは、「ただし、テストしやすいようにするためとある操作をしたらかならずその状態になるように設計するんやで。」をしませんっ!!
聡明なる読者の方々はすでにお気づきだろうが、ここからは実際にデータを繋ぐので副作用だらけの、いわゆるダークネスアンダーワールドアルティメットファンタスティックメニーメニーバグ発生源です。
ここをテストしようとすると、とてもじゃないが人間を辞めなければなりません。
ここ以外のテストで動作の担保をとりましょう。(Reduxとか使ってたらReduxでしっかりテストすればよいだけなのですやで)

pages/okan_page.jsx
import { OkanTemplate } from "../templates/okan_template"

const mapToState = state => state
const mapToProps = dispatch => dispatch

const OkanPage = (props) => {
  <OkanTemplate { ...props } />
}

export default connect(mapToState, mapToState)(OkanTemplate)

でも、こういう風に書くと他しっかりしてたらテスト書かなくてもいいんじゃね??ってなりませんか??
僕はなりましたし、実際今のところうまく動いてます。やったねっ!たくお!!

まとめ

ちょっと日本語長めの記事になりましたがいかがでしたでしょうか??
実際にいくつかのプロジェクト/プロダクトにアトミックデザインを取り入れていって一番しっくり&プロジェクトが成功率が高い方法を共有したいと思い今回初カキコさせていただきました。

賛否両論あると思いますし、ましてや僕みたいなロールで仕事をしている人は少ないかもしれませんので全く参考にならないかもしれません。
ですが、この記事を読んでひとりでもアトミックデザインっておもろそーやなっ!やってみよっ!って方が増えましたらこれ以上ない喜びですw

また、プロジェクトメンバーの人数やプロジェクトそのものの規模によってはただの足枷になる場合もあると思います。
なのでぜひコメント欄に「俺の考えた最強のアトミックデザイン」を書いていってやってください。

タクオ イロイロナ セッケイ マナビタイッ!

んじゃ、アデューッ!

次回予告

アトミックデザインを取りいれて無事プロジェクトを完遂させたたくお。
しかし次の瞬間待っていたのはプロダクションサーバーの突然の死であった。
すでに広告費を投入したリスティング広告は掲載されているっ!!
たくおに安らぎの時は来るのかっ??

次回 『docker-compose死す。なぞのk8sとは一体…』

みんな!!期待しててくれよなっ!

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away