モジュールは見通しをよくする

Scalaでプログラムを組むようになって3年経つが最近Scalaの功績の中では「object」キーワードの働きが大きいのではないかと考えるようになった。

objectキーワードはSingltonやjavaのstaticの代用などいくつかの側面があるが、私が多用しているのはモジュールとしての「object」の使用である。
つまりシステムのアーキテクチャとしてのモジュール構造をobjectを使って実現している。ただ、それだけのことであるが、これが実に見通しをよくする。

話は変わるが昔からビジネスアプリのクラス設計においてFat EntityかThin Entityかの議論やドメイン重視かイベント重視(リクエスト)かなどのいろいろな議論がある。昔はOOで開発する場合に、スタンドアローンかクラサバで組まれているアプリケーションであれば、ドメイン重視は当たり前(と言ってもOOでシステムを組むと言ったらSmalltalkくらいしかなかった当時のことであるが)だった。そこにWebが出てきてサーバーサイドのプログラムが脚光を浴びるのと同時にOO言語(Java)での開発が多用されてきて、ドメイン重視(OO的なメリット)が失われていった。

サーバーサイドのアプリケーションスタイルはIBMのIMSやCICSなどで何十年の実績があり、その中ではステートレスが当たり前であった。
その中にあっていくらJavaがOO言語であっても、スタンドアローンやクラサバで養われたOO技術をサーバーサイドに持ち込むことは無理があった。
OO技術が主にメカニズムとして活かされビジネス的な構造としてOOが活かされなくなった。
このようにWebプログラミング(サーバーサイドのプログラミング)が主流になって以来OOのクラス設計は揺れているように思われる。

そのような中で私もクラス設計で随分悩んだが、15年ほど前にAppleがDylanというオブジェクト指向と関数型を融合した言語を開発した。
関数型と言っていいのかどうかは今となっては難しいが、Dylanを作ったのはバリバリのLisperたちなので、Lispの香りがする言語仕様であった。
この言語は当時としては相当に先進的であったが、Appleの財政難でプロジェクトが中止になり、その後も紆余曲折があり今はWeb上にサイトがある程度である。

モジュールという言葉は最近あまり聞かないが、昔はよく使われていた。モジュール構造やモジュール強度など当たり前のように使っていた。
丁度現在のコンポ-ネントのような感じである。
私がモジュールに再度意識が向かうようになったのは、Dylanの言語仕様を知ってからである。あまり正確ではないがDylanのクラスでは属性をスロットと呼び、メソッドはGetterとSetterだけにする。 という思想だった。つまりオブジェクトの組み合わせとしてクラスに役割を持たすが、操作はクラスではなくモジュールにもたせる。というものだった。

これは言語としての割り切りとしてはかなり大胆な発想だと感じた。しかし、今は私もその考え方に賛同している。
そして、それが私のScalaの「object」キーワードの評価につながっている。

10年以上前にJavaでクラサバ用のフレームワークを作成した。

 http://www.vsa.co.jp/R&D/JBF/JBFIndex.html

簡単なORラッパーとAWTベースのGUI生成をもつフレームワークである。
(このフレームワークのミソはEntityの属性にメタオブジェクトを対応させて、RDBのカラムとGUIコンポーネントを柔軟に結びつけた構成になっている。偶然にもScalaベースのWebフレームワークLiftも同じようなメタオブジェクトを持つ)

このフレームワークを使って販売管理、仕入れ管理、会計の基本的な機能を実現するサンプルを作成した。

 http://www.vsa.co.jp/R&D/SOHOPartner/SOHOFrameSet.html

これはバリバリのドメイン重視でEntityと少しのアプリ部分でできており、画面はほぼ動的生成でできている。
ドメインモデルがそのままシステムになっているような構成である。
Entityを指定してそこから自分自身を表現(編集)できるビューを出すことができる。

このサンプルを作成して感じたことはやはり、Entityに処理を持ち込みすぎると分かりにくくなることである。
この分かり難さとはEntity個々のクラスと言うよりも、もう少し大きなコンポーネントとして構成しようとする時に何処にロジックをおくかという判断の難しさである。
つまり何かビジネス的な処理を行うために必要なオブジェクトは通常Entity単独ではなく、Entity群として扱われることが多い。そうなるとEntity個々にロジックをおくのは難しく、違うオブジェクトが必要になる。
そこにモジュールを持ってくるとしっくり落ち着くのである。
ドメインモデルやその他のパッケージング、レイヤリングした構造をモジュールに当てはめる。

モジュールにはそのモジュールが提供するサービスがあって、そこで使用するオブジェクト構造はモジュール内のクラスとして構成する。
オブジェクト構造に基づく処理はパターンマッチングで処理をすることで、各Entityにロジックを分散させるのではなく、モジュールで一括管理できる。

パターンマッチングは複雑なオブジェクト構造には正に最適である。これをオブジェクト自身にロジックを持たせると分かりにくくなる。

Visitorパターンなどはパターンマッチングと比べるとすごくまどろっこしく感じる。
やりたいことのコード編をクラスに分散してしまったように感じるからである。

もっともOO的にはその分散(ポリモフィズム)が柔軟な構造に対応できる鍵なので、そのようなことが出来なかったところから見ると分散することも美しいのであるが、関数抽象で同じことができることを知ってしまうとまどろっこしく感じる。

これはパターンマッチングを知って感じたことである。

モジュール内のメソッドでは関数抽象(クロージャなどで処理を抽象化し組み合わせる)で柔軟性をもたせ、モジュール内のクラスではOOのメリットを活かしオブジェクトの組み合わせで柔軟性を確保する。

実際にはまだそんなに綺麗に切り分けられていないがその構造を意識して設計している。
この関数抽象とオブジェクト抽象を自在に使い分けられる点が私がScalaを好きな理由である。
慣れると他の言語が面倒で使えなくなる。

今はScalaActionScriptを同時に使っているが、ActionScriptだと思考が中断されることが多く。同じくScalaからJavaのクラスを使う(特にJavaのコレクション)時も思考が中断されることが多い。

Scalaだと非常にスムーズにやりたいことが書ける。

特にクロージャの柔軟性は秀逸である。
ActionScriptでもクロージャーを使えるが、比べものにならない使い易さである。
それはクロージャーからのスコープの違いに起因する。
Scalaクロージャーは制約が非常に少なく、通常のスコープの概念でもコードが書けてしまう。
JavaActionScriptだと直感的ではない制約(後でこれは出来ないんだ と気づくようなもの)が多い。

というわけでちょっと脱線してしまったが、「object」キーワードはなかなかすごい発明だと思う。