entry-header-eye-catch.html
entry-title-container.html

entry-header-author-info.html
Article by

Atomic Designの概念に基づいたJavaScriptフレームワークのコンポーネント設計とは?

はじめに

こんにちは。はてなブログとエモい話が何よりもすきな17新卒のエンジニアPotato4dです。 ひょんなことからこのpixiv insideに技術的な記事を書く機会に恵まれたので、JavaScript周りの話を書きたいと思います。

概要

モダンなJavaScript環境に慣れ親しんだ方には、「コンポーネント」という単位をベースとしたUIやロジックの開発を行う事は珍しくないかと思います。 しかしながら、その「コンポーネント」という単位の大きさと分割指標については、中々まとまった資料が存在せず、それぞれの開発者や、フレームワークによりけりとなっている印象を受けます。

昨今のフロントエンド開発、特に全てJavaScriptで完結するSPA開発で頭の悩ませる部分としては、状態の管理に次ぐ、大きな課題となっているのではないでしょうか。

今回の記事では、そんなJavaScriptにおける「コンポーネント設計」について、1つの叩き台となるような形を提案してみたいと思います。

コンポーネントの種別

実際のコンポーネントについて話をするにあたっては、事前の認識のすり合わせはかかせません。 特に、「コンポーネント」というワードは、事前のコンテキストにより意味が変わりがちです。

そこでまずは、その「コンポーネント」について、「SPA開発」という文脈において、広く使われている要素に分割してみたいと思います。

ページを表現するためのコンポーネント

SPA開発を行う場合、各ルーティングに対応するページのコンポーネントというものは必須となります。

1ページを巨大な1つのコンポーネントとして管理し、その中にUIパーツを配置していく。という記法がメジャーです。 このコンポーネントは、基本的に1つのルーティングに対して1つのコンポーネントがあてがわれ、それらは複数のルーティングにまたがって利用されない、つまりは、再利用されないことが前提となっている場合がほとんどです。

UI要素のひとかたまりを表現するためのコンポーネント

そして、その次に大きなコンポーネントとして、UI上の要素のひとかたまりを表現するコンポーネントがあります。 これは、ナビゲーションといったグローバルで利用されるものから、パンくずリストといったものまで、複数のページのコンポーネント間で共有することが多発するものを指すこととします。

小さなUI部品を表現するためのコンポーネント

最後に、これまでに紹介したものより、非常に小さな粒度の部品をさすコンポーネントです。

例としてあげると単一のボタンや、入力フォーム、見た目をカスタムしたcheckboxなどで、単機能をもち、1つの画面内で繰り返し利用されるものについても、コンポーネントとして定義することが非常に多くあります。

これは、いわゆるCSSフレームワークの要素ひとつひとつをそのままコンポーネントに落とし込んだようなもので、その用法なども似通っています。

場合によっては「エレメント」と呼ばれることもありますが、今回は統一してコンポーネントの一種として扱います。

3者の関係性

さて、このそれぞれのコンポーネントですが、開発中に多少の例外こそ出てくるものの、一般的にはどれも上から下への依存関係が存在します。 例えば、1つのページを表現するためにはナビゲーションやパンくずリストといった、ある程度のかたまりとなるUIの要素が必須ですし、そうでなくても、より小さなボタンなどの部品は必要です。

また、一つ下層にあるナビゲーションやパンくずリストなども、また子に小さな粒度の部品を持っており、それなしでは成り立たない場合は多く存在します。

このように、各コンポーネントは、ページ>大コンポーネント>小コンポーネントの順で依存しており、下層であればあるほど、より依存される量は増え、再利用される数は多くなります。

Atomic Designの概念に当てはめる

これまでのコンポーネント種別を見て、気づいたかたもいらっしゃるかもしれませんが、実はこれらのコンポーネントは、Atomic Designにおけるデザインの要素と酷似しています。

(Atomic Designの基礎知識についてはPOSTDの記事が、実践情報についてはDeNA社のブログが参考になるかと思います。)

フロントエンドエンジニアが再利用性と粒度を重視し、無意識に行っている設計は、実は現在話題になりつつある、新たなデザイン設計と同じ理論の基に成り立っているのです。

原子から分子、そして1つのページへ

Atomic Designは、UI上の全ての要素を、現実的な範囲での限界まで細かく分解し、その組み合わせにより全てのデザインを表現する手法です。

Atomic Designの基本となる「Atoms(原子)」という概念は、Atomic Designの名が表すとおり、それ以上の全てのデザインの元となる、基本原則的要素です。

ここにはボタンや入力フォームのフォーム単体、ラベルなどの「単一の要素」を表し、常に孤立しており、疎結合な要素のことを指し、それ自体には意味をもたないものとなっております。

そして、それらAtomsが複数集まることで、「Molecules(分子)」と呼ばれる単位となり、Moleculesはラベル+入力フォーム+ボタンといった、小さなひとかたまりの要素を形成します。

そうして、幾つかのMoleculesを組み合わせることで、例えば一つのフォームやナビゲーションなどの、「ユーザーの関心ごととして意味のある」ものとして一つの単位が形成されます。そして、これを「Organisms(有機体)」と呼び、生きている一つの単位と定義しています。

この定義がJavaScriptでのプログラミングにおけるコンポーネント設計と比較して興味深い点としては、本質的な要素を変えること無く、より詳細に落とし込んだところでしょう。

JavaScriptでは「UI要素のひとかたまりを表現するためのコンポーネント」と比較的広義で扱われている中規模のコンポーネントの概念が、Atomic Designに落とし込む場合は、単一の機能を提供する場合はMolecules、実際のページ上での、まとまった機能を提供するものをOrganismsと明確に定義されることとなります。

そして、そのOrganismsを複数組み合わせることによって、最終的な「Pages(ページ)」という一つの成果物を生み出します。

いわば、Atomic Designとは、究極のボトムアップ型デザイン手法なのです。

コンポーネントと一対となる概念

そして、これらは全て、JavaScriptフレームワークでのコンポーネントにて表現することが可能です。 ページを表すコンポーネントは、そのままページと、ひとかたまりを表現するためのコンポーネントは、Organismsに言い換えることができます。

また、そのOrganismsを形成するために、UI部品としての、CSSフレームワークライクなコンポーネントが存在し、この中に、Atomic Designが採用されていないプロジェクトではAtomsおよびMoleculesによく似たするものが混在している状態です。

とはいえ、UI部品がそれより大きな要素の全てを構成していることに、違いはありませんので、適切な整理により、ただしくAtomic Designの分類に仕分けていくことが可能です。

つまりは、従来の「コンポーネント」という単位は、「Atomic Design」というフレームワークに乗ることによって、より強固で、確かな共通認識を持つ概念へと昇華することが可能となるのです。

Atomic Design x コンポーネント指向

さて、それではなぜこれらをかけあわせるのでしょうか。

私が考えつくだけでも、これによるメリットは非常に多くあります。試しに幾つか挙げてみます。

全員の持つ「コンポーネント」の意識が明確になる

これまでのSPA開発では、コンポーネントの粒度は人によりけりで、プロジェクトのコードを見た上で、「なんとなく」の雰囲気を掴んでいく必要がありました。

対策として、ドキュメントなどで明文化される場合もありますが、そもそもとなる「大きさ」「粒度」の感覚の違いをすり合わせるのは困難でした。

しかしながら、Atomic Designという共通原則に乗ることによって、デザインのレイヤーを一つまたぐ場合は一つのコンポーネントをバイパスするように定義することで、より確実なコンポーネントの設計が可能となります。

プロジェクトの走り出しを支援しながら、なおかつ長期利用に耐えやすい

Atomic Designの特徴として、下から上へと流れるようなデザインフローがあります。

先に細かい要素を作ってから、それによって全体を構成するため、フロントエンドエンジニアとデザイナーが並行作業しやすいというメリットもあります。

例えばですが、Atoms要素とMolecules要素のみができあがっていれば、それらのデザインだけでなく、イベントの伝播のコントロールまでを含めて先に記述しておくことができるため、インブラウザデザインを行うほど必死になる必要はないにもかかわらず、それに近い効率での作業が可能となり、「はやく作り、はやく出す」を実現しやすい組み合わせとなっております。

それだけでなく、予めこのルールに基づいた設計を行っておけば、基本的にはページを構成する全ては小さなものの組み合わせであるため、ABテスト内容を変えたい場合や、細かなUIの改修にも強く、作って終わらない流れを形成しやすいメリットもあります。

他にもメリットは多数

また、今あげただけでなく、プロジェクトの形によって、様々なメリットがあります。

例えば、Atomic Designを遵守したプロジェクトで、かつ何らかのFlux実装を適用していない場合、イベントの集約所の定義を、必ず1ページに一つだけ存在することが保証されている「ページ」のコンポーネントに持たせるような設計もしやすいというメリットがあります。

また、どういったデータフローの設計を行っていた場合でも、後からイベントの動作を変えたいというニーズにも、Moleculesコンポーネントのコードの変更だけで良くて済むというのは開発効率に貢献することは間違いありません。

後から差し込むには中々難しい概念ではありますが、定義することで得られるメリットは大きいので、新規立ち上げ時などに実際にベースとしてみるのは良手かもしれません。

Atomic Designの運用において気をつけるべきポイント

とはいえ、Atomic Designに通りに従うと何も問題なく、すべての場合に対応できるかというと、そんなことはありません。 全てのソフトウェア開発者がこれまで幾度となく耳にしてきた通り、狼人間を撃つ銀の弾丸はこの世にはありません。

ですので、少しだけ、実運用における注意点を記しておきます。

Atomic Designに振り切ることが非効率である場合もある

実際の運用を考えると、基本的にはAtomic Designの原理を完全に遵守して開発を行うことは不可能に近いです。 そっくりそのまま開発を行うことは、かえって非効率であることの方が間違いなく多いことは明白です。

比較的大きな規模であり、変更も多く、かつきちんと子から親へと要素を組むだけでできあがる構成であれば良いですが、そもそも「ここでしか使わない」といったものが多い場合、Atomic Designを採用することは手間を増やすだけなのでオススメできないでしょう。

設計にプロダクトが縛られないように

また、当然の話ではありますが、どんなアプリケーションであっても、開発を進めていく中で必ず例外的なコンポーネントやデザインというものは出てきます。 Atomic Designの概念だけでは、技術的に難しかったり、また、著しくUXを損なう場合もないとは言い切れません。

Atomic Designは、比較的厳格な設計手法であり、それを遵守することによってある程度の秩序が保たれますが、それにこだわることは、設計パターンによってプロダクトが制限されているということになります。

そういった場合にある程度妥協点を見つけることは必要です。

最後に

いくつか注意点こそあるものの、Atomic Designは概念としては非常に良くできていますし、曖昧な言葉の問題を超越して、一つの定義として、コンポーネント設計への明確なアンサーを提示しています。

プロダクション環境で使っていくことを考えるのであれば、原理主義になりすぎないように「Fluxの概念をベースとしたオレオレFlux実装」のように、「Atomic Designの概念をベースにしたオレオレコンポーネント設計」を行っていくのが正しい道でしょう。

たとえそれを遵守しきれない場合においても、開発に携わる全員が、Atomic Designという共通の概念を持って開発を行うことは、情報の齟齬を最低限に抑えることにもつながるほか、効率的な開発のモデルを常に意識し続けることが可能であるため、非常に有意義です。

すぐには導入できなくとも、皆がこの意識を持つことによって、協業しやすい設計の意識は更に加速するでしょう。

エンジニア募集中

ピクシブ株式会社では、屈強なエンジニアを募集しています! 新卒・中途採用どちらも行っておりますので、新しいことに挑戦したいかたは是非ご応募ください!

hrmos.co hrmos.co

20191219021233
Potato4d
想いの力だけを大切に生きています。 高卒でJavaScriptエンジニアやっていて、気合とJavaScript筋で生活する日々、過去にはFRONTEND CONFERENCE 2017の実行委員長やったりしていました。