Zerobase Dev Blog

コードネームYentry

Smalltalkウェブ・アプリケーション・フレームワークSeasideとZincを比較してZincを採用する方向で

UIコンポーネント単位のエンド・ツー・エンドの開発パイプライン』に書いた通り、 Seaside の「コンポーネント指向」のアーキテクチャは素晴らしいと思う。

しかし、 Seaside にはいくつかの問題がある:

  • もう一つの大きな特徴である「継続」は不要。いまなら Ajax でやる。
  • HTML5 対応が不安。 WAComponent のサブクラスで

      updateRoot: anHtmlRoot
          super updateRoot: anHtmlRoot.
          anHtmlRoot beHtml5.
    

    と書いても、 DTD<!DOCTYPE html> になるだけ。 <html xlsns=~~~ という XHTML の記述が残ってるくらいなので、あまり HTML5 対応は進んでいないと思った。

  • 2002 年に構想されたアーキテクチャは、さすがに HTML5 時代のウェブのエコシステムに適応できてない印象。

  • フレームワークが巨大すぎて、ちょっとしたことをやるときに調べ回らないといけない。 Seaside 自体の把握・改修・拡張が難しい。
  • その他、 Wikipedia にも「継続はメモリを食い過ぎる」「 REST 原則に反している」といった批判がある。

こういう問題があって、ぼくがやりたい「UIコンポーネント単位のエンド・ツー・エンドの開発パイプライン」で使うのには無理がありそうだ。

そこで注目しているのが Zinc という HTTP コンポーネント。第一印象は Ruby で言えば WEBrick のような簡易 HTTP サーバー。しかし、 Ruby でいう Sinatra 的な軽量フレームワークにもなっている。

more on this topic: Zinc HTTP Components (Pharo Conference Paper)

Zinc は HTTP のクライアントにもなる。 Zinc + Soup(HTML パーサー)でHTTP I/F のテストを書きたい。 Selenium WebDriver で網羅的にテストすると、テスト実行のコストが大きい。それは要点だけに止めて、網羅性は Zinc + Soup のテストで担保したい。

more on this topic: Smallthoughts Seaside - Automated testing 2

Seaside は一通り(さわりだけでも)理解したので、その設計思想に学びつつ、軽量なZincの上に色々なものを重ねていきたい。

とはいえ、 Seaside との出会いには感謝。おかげで開眼した。

今度は Zinc + GemStone/S というアーキテクチャを検討していく。 Zinc の上に独自のフレームワーク層をかぶせていく構想で。

P.S. 今日は第3回Smalltalkハッカソンに参加させて頂きました。主催の @umejava さんに感謝。

これまでの経緯 ver. 1 (2013-03-06)

Smalltalk やろうと決めたときに書いた『GLASS (GemStone, Linux, Apache, Seaside, and Smalltalk) によるテスト駆動プロトタイピングへ』から24日も経ってました。ふつうの仕事だとありえないスピード感ですが、「社内システム開発プロジェクト」兼「開発手法開発プロジェクト」なので、納得いくまで考えながら進めてます。

こんなふうに愉快な開発手法の研究や実践に取り組んでるゼロベースに興味がある方は、ぜひ気軽に遊びにきてください。毎週火曜日19時がオススメです。Wantedlyで受け付けてます。

UIコンポーネント単位のエンド・ツー・エンドの開発パイプライン

アーキテクトがリードするUIプロトタイピング(OOSass と JavaScript MVC と DDD)』の続き。ウェブ・アプリケーション・フレームワークの話です。

UIコンポーネント指向

UIコンポーネント」という単位で、UIからビジネス・ロジックまでエンド・ツー・エンドに実装する。「UIコンポーネント」の単位で、ひたすら並列開発できる(パイプライン化)。こんな開発手法を模索しています。

それにより、 OOSass を使った HTML & CSS ベースのプロトタイピングを、ビジネス・ロジックの実装にまで拡張できるはずです。それが「UIコンポーネント単位のエンド・ツー・エンドの開発パイプライン」という意味です。作業仮説ですが。

Seaside

ここで参考になるのが、SeasideというSmalltalkのウェブ・アプリケーション・フレームワークです。非常にユニークというか、個人的にはかなり違和感もある独特なフレームワークですが、学ぶべきところも多々あります。 About ページで挙げられている特徴のなかに「コンポーネント指向」の考え方があります:

  • Embedded components. Stop thinking a whole page at a time; Seaside lets you build your UI as a tree of individual, stateful component objects, each encapsulating a small part of a page.

「ウェブページをまるごと一度に考えるのを止めよう」と言っています。「ステートフルなコンポーネントを作り、その組み合わせによってウェブ・ページを構成しよう」という考え方です。コンポーネントは色々な画面で再利用できるので DRY (Don't Repeat Yourself) です。

しかも「継続」 (continuation) まで使えます。「ステートレスな HTTP というプロトコル」という常識に正面から挑んでいます。かなり独特なので(とくに URL が…)、だまされたと思って、いちど触ってみて頂きたいです。「だまされた!」と思うかもしれませんが…

ともあれ「コンポーネント指向」を分かりやすくイメージするならば、こういう喩えがよいでしょう。「ヘッダ」「フッタ」を共通化してインクルードして使い回すことがあると思います。そういう「埋め込み部品」 (embedded components) の組み合わせによってウェブ・ページを構成する手法を、ヘッダやフッタのみならずウェブ・ページを構成するあらゆる情報要素にも適用するということですね。静的なヘッダやフッタとは異なり、機能を持った部品 (functional components) もあるのがポイントです。

コンポーネント指向とオブジェクト指向の密接な関係

具体的に、どういうものが「UIコンポーネント」になるのでしょうか。設計次第ですが、現時点の私は、次のような粒度をイメージしています:

  • 問い合わせフォーム (an inquiry form)
  • 検索結果リストのなかの商品 (a product information embedded into a search result list)
  • 商品詳細の「カートに入れる」ボタン (an add-to-cart button embedded into a product detail)
  • 検索結果リストのなかの商品の「カートに入れる」ボタン (an add-to-cart button embedded into a product information, which is embedded into a search result list)

ここで、「カートに入れる」ボタンは、まったく同じ部品でよいとしましょう。ならば再利用できます。この再利用は、単なるコンポーネントの再利用とは少し意味が違います。コンポーネントの「入れ子」で再利用することになります。小さなコンポーネントを使って、大きなコンポーネントを作ることができるのです。

ここで「コンポーネント」を「オブジェクト」と呼び直せば、まさに「オブジェクト指向」 (OO: object-orientation) の考え方だと分かります。小さなオブジェクトの組み合わせで大きな部品を作り、大きな部品の組み合わせでウェブ・ページを作り、ウェブ・ページの組み合わせでウェブ・サイトを作る、というミクロからマクロへの構造が現れてくるわけです。

ちなみに、アラン・ケイオブジェクト指向を構想する際に「細胞」の概念を援用したという話があります。まさにそういう話になっています。

Seaside のコンポーネント指向に関する詳しい説明が『SeasideへGO!!(第2回)』にあります:

Web はマルチユーザの環境なので、「アプリケーション」のインスタンスは複数立ち上がらなければなりません。 つまり正確にはアプリケーションそのものではなく、ルートとなる「コンポーネント (WAComponent)」が、セッションごとに立ち上がります。 GUI にあてはめると、アプリケーションを選択した後に、ウィンドウが一つ開いたと考えると良いでしょう。

ルートコンポーネントはメモリ上で待機し、それぞれがループを行います。 イベントを受けつけ、必要に応じて自身の表示更新を行い、インタラクティブにユーザとやり取りをします。 リクエストごとに都度立ち上がるコントローラ、コントローラの指示を待つ受け身のビューというものは存在しません。

コンポーネントは内部にコンポーネントを入れ子として含むことが可能です。 ルートのコンポーネントがウィンドウ、入れ子になったコンポーネントが、ボタンやリストなどのウィジェットと考えることができます。

コンポーネントは、状態をそれぞれ別個で保持します。 典型的な Web アプリフレームワークでありがちな、ページ間にまたがるデータを一つのセッション辞書に詰め込むようなアプローチとは一線を画しています。

(※余談ですが、これは CSRF への本質的な対策になっていると思います→『高木浩光@自宅の日記 - CSRF対策に「ワンタイムトークン」方式を推奨しない理由, hiddenパラメタは漏れやすいのか?』)

さて、この文章は、いったんここで終わります。引き続き模索していきます。

メモ

コンポーネント指向のウェブ・アプリケーション・フレームワーク」は、まだまだ少ないようですね。とはいえ、探してみると、見つかりますね。

あと、Drupal も加えていいかも。第一義的には CMS ですが、生産性の高いウェブ・アプリケーション・フレームワークでもあります。

リンク

次:Smalltalkウェブ・アプリケーション・フレームワークSeasideとZincを比較してZincを採用する方向で

アーキテクトがリードするUIプロトタイピング(OOSass と JavaScript MVC と DDD)

一連の模索中:

ここで、いったん、まとめておく。

思想

開発とは、すなわちプロトタイピングである。

手法

プロトタイピングをスケール(大規模化)するには、使いやすい部品を作って、それらを組み合わせることである。

アーキテクチャ

コンポーネント定義はIAが行うのが理想。かつ、それをデザイナーやフロントエンドエンジニアに伝達し、実装後にそれが維持されているかを確認するところまでが仕事。(『CSS PreprocessorとIAの親和性【その仕事、蠍は留守です】』)

自分なりに再定義しておく:

  • アーキテクトがプロトタイピングをリードする。
  • プロトタイピングのなかで HTML と CSSJavaScript の基本的なモジュールを作る。
  • アーキテクトがハイレベルのアーキテクチャをコントロールしつつ、フロントエンド・エンジニア(やマークアップ・エンジニア)に詳細な実装作業を委譲する。

もちろん、フロントエンド・エンジニアからのフィードバックを受けてアーキテクチャを改善する必要があるのは言うまでもない。

以上はユーザー・インターフェイス層だけの話。それに加えて、アプリケーション層、ドメイン層、インフラストラクチャ層がある。合計4層。このすべての層をアーキテクトがコントロールする。

もちろん一人ですべてを作ることはできないので、各層の専門家とコラボレーションしながら。ペア・プログラミングなどの、密接で創造的なコラボレーションが大事。プロジェクト初期はワークショップ主体。

実装技術

OOCSS のアイデアに Sass を組み合わせた OOSass が有力。『Takazudolog - OOCSSとSass』によくまとまっている。

OOCSS で問題になっている「セマンティックでない class 指定」、言い換えると「スタイル指定そのものになってしまっている class 指定」については、オブジェクト指向の知見を導入して解決する方向で模索したい。

具体的には、宣言的な仕様として class に記述できるように CSS をモジュール化できないだろうか。『エリック・エヴァンスのドメイン駆動設計』でいうと「第10章しなやかな設計 設計の宣言的スタイル」など。

なんとなく、「コマンドと副作用のない関数の区別」のアナロジーで対処できる気がしている。作業仮説。

JavaScript については MVC フレームワークを導入する。システム全体としては「ユーザー・インターフェイス層」(UI層)だが、その UI 層のなかにも4層ある、と考える。つまり「UI サブシステム」の「ドメイン層」がある。 jQuery を使っていいのは「UI サブシステム」の「UI 層」だけ。

まあ4層は大げさかもしれない。『Backbone.jsにおけるModel-View-Presenterアーキテクチャパターン | クラスメソッド開発ブログ』のように MVP の3層で十分にも思える。このへんは、やりながら考えたい。

現時点では Backbone.js よりも AngularJS のほうに興味がある。 AngularJS は MVC アーキテクチャで、『AngularJSを使ってみよう « NAVER Engineers' Blog』が分かりやすい。

続き:UIコンポーネント単位のエンド・ツー・エンドの開発パイプライン

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

OOCSS + Sass (OOSass) について調べた

IA DSLとしての抽象化CSSとドメイン駆動設計』からOOSassへと至る。

OOSass は OOCSS (Object-Oriented Cascading Style Sheets) と Sass のいいとこ取り。

続き:アーキテクトがリードするUIプロトタイピング(OOSassとDDD)

IA DSLとしての抽象化CSSとドメイン駆動設計

CSS PreprocessorとIAの親和性【その仕事、蠍は留守です】

コンポーネント定義はIAが行うのが理想。かつ、それをデザイナーやフロントエンドエンジニアに伝達し、実装後にそれが維持されているかを確認するところまでが仕事。

CSS Preprocessor の利点を活かせばコンポーネントの構造を定義しやすいし、それ自体が共通言語となるために伝達が容易になります。

CSS Preprocessor そのものを共通ドキュメントにしてしまうとか

CSS Preprocessor を導入してモックアップを作ってみるとか (...) モックを作る時には紙やツールの上で行う時よりもきちんとしたコンポーネント設計・管理ができていないと破綻しますから、早い時点で綻びに気付くことができます(すくなくとも、フロントエンドエンジニアに「これ無理でしょ」と指摘される前に)。

プリプロセッサーの利用により抽象化されたCSSおよびHTMLは、情報要素の論理構造と視覚構造を定義する宣言的なDSLである。いわば情報アーキテクチャのドメインモデリングを駆動するIA DSLとしてCSSプリプロセッサーを活用できるかもしれない。

今後学習していきたい。というかこれちょっとすごい気付きかも。下記のような問題意識につながってる:

ドメイン駆動設計(DDD)とモードレスUI

オブジェクト指向でモードレスな UI の HTML アプリを作るなら、 JavaScript のなかでも「宣言的な UI ドメインモデル」と、「手続き的なイベントハンドラ」の峻別が有効だろうか。後者のコードは必ず3行以下にする規則とか。

AngularJS はオブジェクトを直接触っているような感じを実現するのに役立ちそう。オブジェクトの状態と UI プレゼンテーション層のあいだのマッピングを自動化して、宣言的に書けそうな感じが面白い。研究したい。

TDDでUIデザインするタイミング

UI設計と要件定義は一体のものであって、どちらかが先ということはない、という思想でプロトタイピングするとき、テスト駆動開発はどのように実践できるか。

システムをUIサブシステムとアプリケーションサブシステムに分離して同時に開発することで共進化させる?

BDUF(Big Design Up Front)は避けたいが、ある程度のインタラクションデザイン/UIデザインが進捗してからシステム設計したほうがよい。というのは、フィーチャーやユースケースが定義できなければ、受け入れテストは書けないからだ。モードレスUIにしたいので、フィーチャーやユースケースはインタラクションデザインから決めたい(逆にするとタスク指向のモーダルUIになりやすいはずだから)。メンタルモデルに照らして素性のいいシステムモデルを設計しないといけない。次はDCIを学ぼう。

ここで「ある程度のインタラクションデザイン/UIデザインが進捗してからシステム設計したほうがよい」というのは、疑わしくなってきた。

「インタラクション」あるいは「ユースケース」も、ドメインの知識に深く関わるという考え方で提唱されているのがDCIアーキテクチャだ。その批判を通じて「ユースケースDSL」というものが必要なのではないか、という考えに至ったところ:

DCIアーキテクチャへの違和感から見えてくるユースケースDSL

IA DSLとしての抽象化されたCSSを使いこなせれば、UI設計とドメインモデリングは同時に進められるのではないだろうか。これが現時点の仮説。未知の世界を探求していきたい。

続き:OOCSS + Sass (OOSaSS) について調べた

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

エリック・エヴァンスのドメイン駆動設計 (IT Architects’Archive ソフトウェア開発の実践)

Smalltalkとソースコード静的解析

Smalltalkは静的型付け言語じゃないから大規模開発においてIDEの恩恵を受けづらいだろうと思ってたんだけど、想像の上をいく独自のパラダイムで、ソースコードの静的解析機能が標準開発環境に備わってたりして、遅延束縛なのに、不思議であります。

Pharoでプログラミングしてると自動補完がすごい。IDEでJavaScalaを書くのと同じくらい生産的だと思う。TDDのためのSUnitも最初から備わってるJavaScalaならコンパイラが保証することもカバーできる。どうせテストは書くわけだし。