今更Atomic Designを考えてみる

こんにちは。
システム開発部の芦刈です。

今回は Atomic Design について、Vue.js での実装を例にお話ししたいと思います。

Atomic Design

Atomic Design はコンポーネント指向の一種で、2013年にBrad Frost さんが考案したフロントエンドのデザイン手法です。

まず、コンポーネント指向とは、ひとことで言うとプログラムを「各々が独立した小さな部品の組合せ」で作りましょうという考え方です。フロントエンドの文脈だと多くの場合、HTML(構造)/ CSS(見た目)/ JavaScript(振る舞い)のセットを1つのコンポーネントとして扱います。

Atomic Design では、そんなコンポーネントの最小単位を Atoms(原子)と定義し、Atoms を組合せることでコンポーネントの塊を少しずつ大きくします。そして、下記の段階を経て最終的なコンテンツとします。
各コンポーネントは下記の単位で可換かつ共通化され、コンポーネント単位での修正・変更が容易に行える構成となります。

f:id:tashi_monex:20201005233411p:plain
Atomic Design - Chapter 2 Methodology より

ざっくりと説明すると、

単位 説明
Atoms
(原子)
コンポーネントの最小単位。
検索フォームを例に挙げると、入力フォームや検索ボタンがそれぞれAtomsになる。
Molecules
(分子)
Atoms の組合せで作る。
検索フォーム単体等が該当する。
Organisms
(生体)
Molecules の組合せ、または Atoms と Molecules の組合せで作る。
ヘッダーやフッター、サイドメニュー等、各Webページの共通部分が該当する。
Templates
(テンプレート)
Organisms を配置先を決めた、ワイヤーフレームのようなもの。
大体省略されていて、使われているケースをあまり見たことがない。
Pages
(ページ)
Organisms を組合わせて作る。最終的なWebページ。


Atomic Design については、Brad さんが書籍を丸々Web公開しているので、厳密な情報が欲しい場合は下記を参照すると良いと思います。

Vue.js

今回は単一ファイルコンポーネントの概念により、1ファイルを1コンポーネントとして扱える Vue.js を使います。

Vue.js は最近流行っているJavaScriptライブラリです。
少し前までフロントエンドのフレームワークといえばシェア率最強の React か Angular の2択でしたが、2014年のリリース後、Laravel で採用されてから知名度が上がり、(ほぼ別物とはいえ前身のAngular JSのせいですが)エンジニアからの評価が分かれた Angular に代わり話題に上がるようになってきました。 HTML/CSS/JavaScript を理解していればとりあえずは始められる敷居の低さも人気の一因のようです。

f:id:tashi_monex:20201005215421p:plain
The State of JavaScript 2019 - Front End Frameworks より

後は日本語の記事が多いこともあって、日本でも結構人気です(2020年 10月時点)。

実装してみよう

そろそろ「こまけぇこたぁいいんだよ!!」と言われそうなので簡単に実装してみます。

下記では上部入力フォームで整数値かそれ以外かの判定を、下部でひらがな・カタカナ・漢字かそれ以外かの判定を行い、アラートダイアログを表示します。
なにか適当に入力してチェックボタンを押してみてください。

Validation 関数を書いた jsファイルを動的にimportしたところは正直やりすぎというかこんな構成にはしないだろうなと思いますが、概ね簡潔にポイントを抑えられたと思います。

実装してみて

Vue.js という非常に強力なツールがあったこともさることながら、Atomic Designはフロントエンドの開発においてとても有用な概念であると感じました。

まず、実装をかなりシンプルにできますね。
特にデザインについて、各コンポーネント単位でのみ考えればいいのが楽でした。
CSSは、新規開発のたびにファイルが増えていって何がどこにあるかわからなかったり、important がいたるところで使われていてスタイルが適用されなくなっていたり、同じコードが重複していたり、セレクタ名が被っていてどれを使っているかわからなくなったりと、開発・運用をしていく上で簡単に破綻しがちなので嬉しいです。

次にデザインとロジックの実装を分離できるのが楽でした。
Atoms ~ Organisms までのコンポーネント単位が Pages に対してプラガブルなので、最低限ワイヤーフレームでのレイアウト構想があれば、サーバ側への問合せ等の先行実装ができます。またデザイナー側も各コンポーネントの詳細を後から詰められるため、実装スケジュールを並行化しやすいのではないのでしょうか。
コンポーネントの再利用が容易そうなのもいいですね。

反面、開発チームやデザイナー間での実装方針に対する認識の一致を図るのがめちゃくちゃ難しいだろうなというのも感じました。特に各単位の実装粒度なんかそうだと思います。
上記の実装だと、「Subject ってわざわざAtomsとして分ける必要ある?」という話になる場合もあると思います。また、各コンポーネントが発火したイベントをどこまで伝播するのかや、親子コンポーネント間でやり取りするデータも決めておかないと、容易に複雑化したり密結合化しそうな雰囲気があります。

後はデザインの共通化についてですね。どこまで共通化するのか。
上記の実装の例だと、Subject は Pages で設定することで、2種類のチェックフォームをOrganisms単位で共通化していますが、別々のOrganismsを作成してもいいと思います。
デザインのスタイルやトレンドに応じて、共通化できるコンポーネントの範囲が決まってくるなんてこともあると思うので、デザイナーだけでなくプログラマ側もデザインについての知見が必要に思いました。
ちょっと文章がくどかったですが、デザイナー目線でフラットデザインに触れた本として、下記が面白かったです。

上記問題については、いくら調べても実装や管理、運用での対処法やフレームワーク等のエコシステム内のキラーライブラリによる対処法などは特に見当たらず、プロジェクトに応じて柔軟に決めるとよいという感じでした。提唱されてから結構時間が経っているにも関わらずこのような状態なので、やはり解決の難しい問題のようです。

プログラマとデザイナー間での認識のバックグラウンドを共有化したり、最初のプロトタイピングに時間をかけてプログラム構成を厳密に決めてあげたりするしかないのかな。