Smalltalk Web開発編（Seaside超入門）

# Smalltalk Web開発編（Seaside超入門）
「Smalltalkを学んで何か作りたい。何か使えるものがいい」と言われる方はWebアプリケーションを作ってみてはいかがでしょうか。SmalltalkでもWebアプリができることは、[Smalltalk Web開発編 その0（Teapot）](http://qiita.com/kaminami/items/26ed2a12886107d13657)で知っていただいたと思いますが、Teapotはマイクロフレームワークのため、色々と実装しなければなりません。そこで、今日はSmalltalkの中で有名なWeb frameworkのSeasideについて紹介します。

![seaside-m.png](https://qiita-image-store.s3.amazonaws.com/0/18287/d3375bb2-e44a-6946-1c49-d3f17b00f09f.png)
http://www.seaside.st/about/logos

# Seasideとは
SeasideはAvi BryantさんとJulian Fitzellさんが2002年にWebアプリケーションを作成するためのSmalltalkで実装されたフレームワークです。HTMLなどほとんどのものをSmalltalkで記述でき、アプリケーションの処理は、GUIアプリケーションのように記述することができます。

本当の特徴とは違っているかもしれませんがSeasideの特徴を説明してみます。

1. HTMLなどのマークアップはSeaside、Smalltalkで記述する
2. Webアプリケーション特有のURLによる画面遷移、アプリケーションの処理を行わない（統一的なURLを利用する）
3. GUIアプリケーションのようにフォーム画面やナビゲーションなどの部品化が可能（１つの画面で、独立したコンポーネント埋め込目込むことが可能）
3. 状態を管理が楽（セッション管理をあまり意識しなくてもいい）

3の特徴は「継続」とよばれる技術が使われいます。継続を使うとWebアプリ開発でありがちなSessionでの状態を管理をアプリのローカルな変数（Session変数のような特別な変数を用意する必要がない）として扱うことができ、そのため画面遷移がGUIアプリのように自然なコーディングができます。

**異色すぎて意味不明ですか？そんな人こそ一度触ってみることをおすすめします。**
*PHPのSmartyやRuby on Railsを学んだ僕が最初に知ったときは衝撃でした*

Smalltalkは様々な処理系があるため、パッケージが気に入った処理系に対応していなかったりすることが多いですが、珍しくSeasideは様々なSmalltalkに実装されてます。万が一Smalltalkの処理系を変える必要があった場合にも少ないコストで移行ができると思われます（あまりないことを祈ります）。

Seaside 公式ページ
http://seaside.st/

## Seasideのライセンス
MITライセンスです。

http://www.seaside.st/about/license

## Seasideの活用事例
私の所属している会社でのPharo Smalltalkを使ったSeasideは活用しておりますが、その他、海外、国内でビジネスの現場で利用されております。詳しくは[Smalltalk勉強会（東京）](http://www.smalltalk-users.jp/)で聞いてみるといいでしょう。

# Seasideのインストール

## Seasideインストール済みイメージをダウンロード

Seasideの公式ページにはインストール済みのSmalltalkイメージが配布されております。お手軽にSeasideを始められる方にはおすすめです。
http://www.seaside.st/download

## 自分のSmalltalkにインストール
Workspaceに以下のプログラムを記述してDo itしましょう。インストールは多少時間がかかります。

```smalltalk
Gofer new
url:'http://www.smalltalkhub.com/mc/Seaside/MetacelloConfigurations/main';
package: 'ConfigurationOfSeaside3';
load.
((Smalltalk at: #ConfigurationOfSeaside3) project version: #stable) load.
```

# サーバーの起動と停止

```smalltalk:Pharo3.0+Seaside3.1+Zinc
"サーバを起動"
ZnZincServerAdaptor startOn: 8080. "do it"
"サーバを停止"
ZnZincServerAdaptor stop.
```

*2014/12/15時点ではPharo SmalltalkでのSeaside, Zincの組み合わせでの起動方法としては最新です。ネットでSeasideの記事を読んでいる方はお使いの環境に合わせて実行してください。*

古いSeasideを使う必要がある方もいるかもしれませんので、ComancheをベースとしたSeasideのサーバーの起動方法を以下に紹介します。

```smalltalk:Squeak3.10.2+Seaside2.9+Comanche
"サーバを起動"
WAKom startOn:8080. "do it"
"サーバを停止"
WAKom stop.
```
なおこの記事では以降はSeaside 3.1の説明します。
サーバーを起動したら http://localhost:8080 をウェブブラウザで開きましょう。
以下ようなWelcome画面が表示されたら成功です。

<img src="https://qiita-image-store.s3.amazonaws.com/0/18287/27128038-c1ed-5771-d535-b0bed28c8f05.png" width="600">

*開かない方は既に8080ポートが他のアプリケーションが利用していないかチェックしてみてください*

# デモアプリを試してみる
サーバーを起動すると既に登録済みのサンプルプログラムを利用することが可能になります。Seasideでどんなことができるか現在登録されているアプリケーションの一覧を確認してみます。右の[Diving In]のBrowseをクリックしてください。
<img src="https://qiita-image-store.s3.amazonaws.com/0/18287/773bbcea-2902-4db5-8dd1-ad1406e2d8ab.png" width="600">

クリックすると、サーバーを立ち上げた場合の初期アプリケーションをWelcome画面から登録アプリケーション一覧とするか質問をされますが、ここでは[No]をクリックします。
<img src="https://qiita-image-store.s3.amazonaws.com/0/18287/5f9e860b-374f-9b10-a3d4-32c737b7deb1.png" width="500">

既に登録済みのアプリケーションの一覧が表示されます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/18287/e466f09d-77e3-87d1-dbca-28eddc8c4e07.png" width="500">

[examples]-[counter]の順にリンクをたどってみましょう。以下のような画面が表示されます。
カウンターアプリです。[++]をクリックすれば、現在の数にプラス1、[--]をクリックすれば現在の数からマイナス1をするというものです。
<img src="https://qiita-image-store.s3.amazonaws.com/0/18287/adde5f7d-5bb3-b92b-0ff6-7d1d3a0ce1a1.png" width="500">

このサンプルを少し触ってSeasideの特徴を実感してみましょう。

1. まずは[++]をクリックをして表示画面を6にする
2. ブラウザの「戻る」ボタンを押下して表示画面を3にする
3. １回だけ[++]をクリックします。

**表示画面はいくつになりましたか？**
以下のように4となったのではないでしょうか。
<img href="https://qiita-image-store.s3.amazonaws.com/0/18287/f6ab37d1-9e9a-4a1e-589d-212c3f0caa10.png" width="500">

他のフレームワークでWebアプリケーションで作成された経験がある方は、表示画面は７になると思われたのでしょうか。ブラウザの戻るボタンをクリックしているため、サーバーは何回戻ったか不明なのにも関わらず、表示画面に加算をしております。Seasideでは、状態管理が備わっているためこういった挙動も可能になります。

# Seasideでカウンターアプリを作ってみる
Seasideで早速アプリケーションを作ってみます。作成するアプリケーションはサンプルのカウンターアプリです。

## コンポーネントの作成
最初にコンポーネントとよばれるWebの画面と処理を行う部品を作成します。コンポーネントはSystemBrowserを開いて作成していきます。

まずは、カウンターアプリのパッケージ（package、処理系によってはカテゴリとも言われます）を作成します。パッケージ「Seaside-First-App」をしましょう。

![スクリーンショット 2014-12-15 13.36.11.png](https://qiita-image-store.s3.amazonaws.com/0/18287/37e06cca-987a-b060-32cd-1ddce39394e9.png)

![スクリーンショット 2014-12-15 13.36.38.png](https://qiita-image-store.s3.amazonaws.com/0/18287/a528277f-f0cd-7474-4807-a24ca7840c0c.png)

コンポーネントのクラスを定義します。
クラスの定義

```smalltalk:MyCounter
WAComponent subclass: #MyCounter
	instanceVariableNames: 'count'
	classVariableNames: ''
	category: 'Seaside-First-App'
```

コンポーネントはWAComponentのサブクラスを継承して作成します。また、カウンターの値を保管するためのcountというインスタンス変数も用意します。次に具体的な処理と画面を作成していきます。

次にメソッドカテゴリとしてinitializationを追加し、initialize メソッドを作成します。

```smalltalk:MyCounter>>initialize
initialize
	"オブジェクト生成時の処理"
	super initialize.
	count := 0.
```
![MyCounter>>initialize](https://qiita-image-store.s3.amazonaws.com/0/18287/493fe50e-c8e0-ae10-a17d-79a0de5e4b3c.png)


次に、カウントアップ処理のincreaseメソッドとカウントダウン処理のdecreaseメソッド実装します。

```smalltalk:MyCounter>>increase
increase
	count := count + 1
```

```smalltalk:MyCounter>>decrease
decrease
	count := count - 1
```

カウンタの処理は実装できたので、画面の表示部分（HTMLの生成）を作成していきます。画面表示はrenderContentOn:オーバーライドします。
今回は、ブラウザでアプリケーション画面を見るとカウンターの値がh1の見出しで表示するようにします。プログラムは以下です。

```smalltalk:MyCounter>>renderContentOn:
renderContentOn: html
    html heading: count
```

SeasideではHTMLなどのマークアップもオブジェクトにメッセージを送るというSmalltalkらしい方法で生成されるようになっております。これによりテンプレート型のWeb Frameworkで作成したときに発生するマークアップの記述にミスによるバグは少なくなりますし、デバッグも可能になります。

ここまでのプログラムをブラウザで動作確認してみます。実行するにはSeasideにコンポーネントの登録をします。Workspaceで以下のコードを実行します。

```smalltalk
"MyCounterをmycounterで登録"
WAAdmin register: MyCounter asApplicationAt:'mycounter'.
```

http://localhost:8080/mycounter を開いてみます。以下のような画面が表示されます。

![スクリーンショット 2014-12-15 22.00.00.png](https://qiita-image-store.s3.amazonaws.com/0/18287/457cf2c1-3c84-5941-3181-8cb1aa47bda8.png)

0という初期値が表示されております。画面の下部に表示されているのは、開発を支援するためのSeasideの機能です。開発時のみ利用して、運用する際には非表示します。

続いてはカウントアップとカウントダウンをできるようにしていきます。

```smalltalk:MyCounter>>renderContentOn:
renderContentOn: html
	html heading: count.
	"以下のコードを追加"
	html anchor callback:[ self increase ]; with: '[++]'.
	html anchor callback:[ self decrease  ]; with: '[--]'.
```

ブラウザをリロードしてみます。

![スクリーンショット 2014-12-15 22.09.32.png](https://qiita-image-store.s3.amazonaws.com/0/18287/ccaeb8f5-7e28-cee3-a50e-58ba9e3b393e.png)

サンプルと同じような画面になっています。[++]や[--]をクリックして動作を確認しましょう。カウントアップ、ダウンはできるようになったと思います。ただし、ブラウザの戻るボタン後のカウントアップ等の挙動がサンプルとは異なっていると思います。Seasideの状態管理機能が働いていないためで、状態管理をするものを指定する必要があります。指定の方法はstatesメソッドに状態管理をするオブジェクトを記述するだけです。今回の場合は、selfを状態管理します。
*countを指定したい方がいるかもしれませんが、管理したいのはMyCounter自身なのでselfします。*
statesメソッドを追加します。メソッドカテゴリはaccesingとするとよいでしょう。状態管理の指定は配列の形式で行います。

```smalltalk:MyCounter>>states
states
	"状態管理の指定は配列の形式で行います"
	^ Array with: self.
```

プログラムを追加したら、画面下部のツールバーにある[New Session]をクリックしましょう。するとサンプルを同じ動作になります。ちなみにサンプルはWACounterというクラスで実装しておりますので、実際のコードも眺めてみるといいと思います。

# Seasideのツールを学ぶ
次へ進む前に画面したのツールバーについて簡単に説明をします。

## New Session
新しいセッションとして接続したい場合に使います。

## Configure
アプリケーションの詳細な設定を行うことができます。アプリケーションにエラーが発生した場合に処理するクラスやセッションクラスの指定などが行えます。

![スクリーンショット 2014-12-15 22.49.53.png](https://qiita-image-store.s3.amazonaws.com/0/18287/f20f3eac-32ab-01e0-ecf4-089045477c0f.png)

## Halos
HalosはPharoやSqueakでおなじみのHalo（ハロー）を模したツールです。現在表示されているコンポーネントをブラウザ上で操作するを可能にします。Halosをクリックする以下のような画面になります。
![スクリーンショット 2014-12-15 22.53.51.png](https://qiita-image-store.s3.amazonaws.com/0/18287/c8ae1a84-9cd0-2a0b-d69d-c8a504ed173c.png)
枠の左上はコンポーネントのクラス名（今回の場合は、MyCounter）が表示されます。
右上の「Source」をクリックするとコンポーネントが描画しているHTMLを確認することができます。

![スクリーンショット 2014-12-15 22.53.55.png](https://qiita-image-store.s3.amazonaws.com/0/18287/87a8b656-dedb-4690-856e-1bc46330f88f.png)

左上の３つのアイコンは、クラスブラウザ、インスペクタ、CSSのエディターを開くためのボタンです。
クラスブラウザは、ブラウザからコーディングを可能にします。個人的にはSmalltalkのブラウザとは違い支援機能が著しく損なわれるので使いませんが、非常に強力なツールだということは言えます。
![スクリーンショット 2014-12-15 22.54.04.png](https://qiita-image-store.s3.amazonaws.com/0/18287/b84f71d3-bcd9-af95-0016-4ac240252130.png)

インスペクタもブラウザでSmalltalkのインスペクタと同様なことができます。
![スクリーンショット 2014-12-15 22.54.08.png](https://qiita-image-store.s3.amazonaws.com/0/18287/dab15e96-76e0-2131-3411-31fae8d8420e.png)

# Viewを充実させる（Smalltalkでマークアップを記述する）
Seasideでは、マークアップすらSmalltalkで書けるようになっております。つまりSeasideではSmalltalkでマークアップを生成する方法を知る必要があります。これを理解するにはrenderContentOn:の引数で渡されるWAHtmlCanvasについて調べる必要がありますが、時間がかかるので一部だけをざっと記載することにします。

## 見出し
```html:HTML
<h1>見出し1</h1>
<h2>見出し2</h2>
<h3>見出し3</h3>
<h4>見出し4</h4>
```

```smalltalk:Seaside
html heading with:'見出し1'.
html heading level:2; with:'見出し2'.
html heading level:3; with:'見出し3'.
html heading level:4; with:'見出し4'.
```

## 順序なしの箇条書き

```html:HTML
<ul>
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ul>
```

```smalltalk:Seaside
	html unorderedList 
		with:[	
			#($a $b $c) 
				do:[ :v |  html listItem: v ]. 
		].
```

## 順序ありの箇条書き

```html:HTML
<ol>
  <li>a</li>
  <li>b</li>
  <li>c</li>
</ol>
```

```smalltalk:Seaside
	html orderedList 
		with:[	
			#($a $b $c) 
				do:[ :v |  html listItem: v ]. 
		].
```

## テーブル

```html:HTML
<table>
  <thead>
    <tr> 
      <th>言語</th><th>パラダイム</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Smalltalk</td><td>オブジェクト指向</td>
    </tr>
    <tr>
      <td>Lisp</td><td>関数型</td>
    </tr>
  </tbody>
</table>
```

```smalltalk:Seaside
	html table 
		with:[
			html tableHead 
				with:[
					html tableRow:[
						#('言語' 'パラダイム') do:[:v |  html tableHeading: v ]. ].].
			html tableBody 
				with:[
					{ ('Smalltalk'->'オブジェクト指向').  ('Lisp'->'関数型') }
						do: [ :v | 
							html tableRow:[
								html tableData: v key. html tableData: v value  ].
					]]. 
		].
```

## 改行
```html:HTML
<br/>
```

```smalltalk:Seaside
html break.
```

## アンカー

```html:HTML
<a href="http://seaside.st" targer="_blank">Seaside</a>
```

```smalltalk:Seaside
html anchor url:'http://seaside.st'; target:'_blank'; with:'Seaside'.

```

いかがでしょうか。SmalltalkのWeb Framework Seasideについて興味をもっていただけでしょうか。次回はもう少し本格的なアプリの作り方を説明します。

# 参考
**Seaside 公式ページ**
内容が更新されていないページもありますが、Seasideの基本的な考え方などが記載されております。
http://seaside.st/

**Seaside へ GO!!**
日本で一番Seasideについて書かれているページです。基本的なところを学ぶには最適です。
http://www.ogis-ri.co.jp/otc/hiroba/technical/seaside/

**Dynamic Web Development with Seaside**
Seasideでの開発方法についてまとまった情報があります。他のSmalltalk処理系についても記載されているので、参考にするとよいでしょう。
http://book.seaside.st/book

**Seaside Tutorial - Software Architecture Group**
Dynamic Web Development with Seasideが登場する以前は、もっとも充実したSeasideページでした。オブジェクト指向データーベースMagmaとの接続なども含めて記載されているので、OODBに興味をお持ちの方にはおすすめです。
http://www.swa.hpi.uni-potsdam.de/seaside/tutorial

**日本初のSeaside紹介ページ**
Smalltalkを始めたばかりだった学生の頃　このページを見て愛知から東京へ目指したものです。
http://swikis.ddo.jp/umejava/38

**「Seaside 3.0でWeb 3.0」 – 梅澤 真史**
Seaside 3.0の紹介PDF
http://docs.google.com/viewer?a=v&pid=sites&srcid=c21hbGx0YWxrLXVzZXJzLmpwfGhvbWV8Z3g6NzUwMjU2YWE5YzI3NjY0Mw