表現のコンポーネントとエレメント指向

Google I/Oに行ってきたのでそれ関連の話題を。

Paper Elementsのエフェクト要素

Material Designというデザイン言語が出て、そのWebへの適用手段としてPolymerPaper elementsが発表された。

CodeLabsでもPolymerとPaper ElementsでTodoリストアプリをPolymerとPaper Elementsで作るというコースがあった。この中に、エフェクトを指定するステップがある。ここでほーと思ったのが、影をキャストする際にはpaper-shadowを、波紋の効果を出すpaper-rippleを使うこと。エフェクトが要素になっているのだ。

表現が必ず要素化されているわけでもない。固定化されたツールバーがあって、スクロールし始めた際に下のコンテンツから浮き出るような表現をMaterial Designではwaterfallと呼んでるのだけど、ツールバーにその表現を与えるにはmode="waterfall"という属性をつけてやるらしい。

エフェクトのコンポーネント

影や波紋がひとつの要素として定義されているのはどのUIでも汎用的に使われる視覚効果で、それをコンポーネントとして使いたいからなのだろう。ドキュメンテーションからは、自分たちが定義するコンポーネントにエフェクトを与えたい時にこれらの要素を使えと書かれている。waterfallが要素化されていないのは、いち資格効果というよりも、スクローラブルなUIのいち表現という面が強いからだろう。

なので、エフェクトも必ず要素にせよというわけではない。そう言われたとしても、それはPolymerのお作法という側面が強いはず。たぶん…

とはいえ、Polymerであれなんであれ、再利用可能なコンポーネントはインポートしちゃえばいろいろできるので、コンポーネント時代が来たらコスメティックな表現だけの「ユーティリティ」要素が増える可能性だってある。そうなるとページ内の各要素にpaper-shadowを与えて〜と、非効率なマークアップが増えるかもしれない。

エレメンタル、クラシカル

古い人間なので、表現まわりはCSSをはじめとする、表現の定義を要素に適用するアプローチのほうがいいんじゃないかと思ってしまう。大体の場合において、そちらのほうが高効率な気がするからだ。ところがWeb Componentsでは、コンポーネント内で使われる視覚表現であったり挙動であったりを分離して管理・適用する仕組みが弱い気がする。Decoratorsがひとつの解なのだろうけど、いまのところ用意されてない。

Decoratorsのプライオリティが低い理由として、コンポーネントを読み込む際にはself-containedなもののほうがパフォーマンスや依存関係の面で都合が良いということがあるのかなと思う。

もうひとつは、ワークアラウンドでなんとかできるというのもあるんだろう。現在のPolymerもそうしている。たとえばさっきのpaper-shadowも、タグを子として書くだけという方法のみを提供してるわけではない。

The paper-shadow element is a helper to add shadows to elements. Paper shadows are composed of two shadows on top of each other. We mimic this effect by using two elements on top of each other, each with a different drop shadow. You can apply the shadow to an element by assigning it as the target. If you do not specify a target, the shadow is applied to the paper-shadow element's parent element or shadow host element if its parent is a shadow root. Alternatively, you can use the CSS classes included by this element directly.

併記してDOMで関連づけることもできれば、各ステートをclass属性値としてexposeしている。なので今のUIコンポーネントがやってるやり方も使える。HTMLもしくはスクリプトで適用することになるから、CSSでどうこうという話ではないんだけれど、直接書くよりはいくぶんか効率よいのではないか。

でもpaper-rippleにはドキュメンテーションを見る限りはそういうのがないんだよね。なんでだろ。

DeclarativeとImperative

Web Componentsを語るときにたまに出る単語として“Declarative”, “Imperative”というものがある。HTMLのタグはdeclarativeで、JavaScriptでDOM操作をするのはimperativeだ。SVGはdeclarativeでCanvasはimperative、AppCacheはdeclarativeでService Workersはimperativeだ。そんな対立というよりは対比がある。

PolymerはDeclarativeな性質をかなり推している。というよりもエレメンタル指向なのかもしれない。だからといってImperativeなものが否定されるわけではない。ただ、declarativeはそのわかりやすさから“magic”を生みだし、時たま不都合や混乱を生み出す。古いもので<select>、まあまあ新しいものでAppCacheとか。

わかりやすさの責任がとれないと、僕らが不幸になる。Magicではなく、どう振る舞うのかが説明されて、はじめて強力なものになる。Extensive Web Manifestoが目剤しているのはそこだ。Polymerが要素でなんでもしようとしてるけど、それはWeb Componentsが下にあって、モデルを提供しているからになる。こうすると、エレメンタルだけではなくクラシカルなアプローチも提供できる。影を要素として日の下に出すことも、今までのようにクラスに潜ませることもできる。


DeclarativeとImperative、エレメンタルとクラシカル、相互に補完することで、コンポーネントのデザインはより柔軟になるんだろう。ただ設計をするひとは、どこでimperative(スクリプトをごりごり書くか)それともdeclarative(タグ書きまくるか)にするのかということをそれないり意識しないといけないのかも。

コンポーネントならいいけれど、文書のマークアップとして要素を作るときはさらによく分からんくなるのかも。要素なのかそれともクラスなのか。

実際にコンポーネント書く前に、そんなことばっかり気になってしまっている。