2012年9月20日木曜日

Scalaとオブジェクト・モデリング

最近Scalaのトレイトを使っていて 新しい切り口を思いついたのでメモしておきます。

ScalaによるObject-Functional Programmingがモデリングに対して与える影響としてOFAD(Object-Functional Analysis and Design)という切り口で幾つか考察を続けてきました。

ここまで主に関数型プログラミング(FP)という切り口で、オブジェクト・モデリングの拡張を考えてきています。

さて、ScalaではFPの導入と同時にトレイトというオブジェクト指向プログラミング(OOP)での新しい言語機能を提供しています。OOPの世界でも着実に技術革新が進んでいるわけですね。

トレイトはかなり強力な機能でOOPのやり方を大きく変えてしまうインパクトを持っているというのが使ってみての感想です。そして、そのインパクトはモデリングにまで及びそうということに気づいたのが本記事の動機になっています。

分析、設計、実装

理想論では分析段階のモデルは実装技術に対してニュートラルで、影響を受けないはずです。分析段階では、ビジネスに対してより本質的なモデルを作成し、設計段階で実装とのギャップを埋めることになります。

とはいえ、分析モデルと実装技術に大きな乖離があると、分析モデルは単なる参考情報になってしまって、設計段階で事実上、一からモデリングを作ることになってしまいます。(更にひどくなると設計モデルと実装も乖離してしまって、一度実装に入ると設計モデルも参考情報になってしまい、プログラムとデータベーススキーマにしか正しい情報が残っていないといううこともありがちです。)

また、ユビキタス言語がオブジェクト・モデリングからOOPによって構成されるオブジェクト指向開発のキモで、上流のモデルと実装言語でインピーダンス・ミスマッチをなくすことが本質的に重要となります。

そういう意味で良くも悪くも上流工程におけるオブジェクト・モデリングも実装技術からはニュートラルというわけにはいかず、実装技術の文脈の中でモデリングのバランスが決まってきます。実装にスムーズに繋がるモデル要素とその組み合わせによって構築されたメタモデル(プロファイル)を定義して現場に適用していくことがオブジェクト・モデリングの活用技術ということになります。

SimpleModeling

本ブログで提唱しているモデリング手法はSimpleModelingで、MindmapModelingもその一環になっています。

SimpleModelingでは、もちろん分析モデルは実装ニュートラルを前提としていますが、実装技術としてはJava的なクラスベースのオブジェクト指向プログラミングとRDBMSを念頭に置いており、この実装技術から乖離しない範囲でいかに実装ニュートラルな分析モデルを作成するのかという点が主眼の一つとなっていました。

Java&RDBMSで困るのはインヘリタンスの扱いです。

Javaのインヘリタンスは単一継承なので、ドメイン・モデルに多重継承が使われていると実装時に困難が生じます。

また、RDBMSはインヘリタンスは直接扱えないので、アプリケーション側で何らかのエンコーディングを行う必要があります。

どちらも本質的な問題なので、分析と実装の間を埋める設計で吸収することはできなくはありませんがかなり大変です。

この点からSimpleModelingでは:

  • インヘリタンス(汎化)はできるだけ使用しない

というアプローチを取っています。

もちろん必要な所ではインヘリタンスを使いますが、可能な場合にはインヘリタンスのかわりに:

  • パワータイプ(powertype)
  • ロール(role)

を使うようにします。

トレイトによるCakeパターン

トレイトは、ちょっと制約を強くした多重継承のメカニズムと考えると分かりやすいと思います。制約を強くすることで多重継承を可能にした、ということですね。本当の多重継承とはちょっと異なるので、その点を理解した上でミックスイン的な使い方をすることになります。

トレイトを用いることで、ミックスインによるクラス合成ができるようになります。

このメカニズムをふくらませてイディオム化したものがCakeパターンです。

コンパイル時に静的型付けの枠組みで安全にDIができる、ということでCBD(Component-Based Development)的な用途にも広げていけそうです。

Cakeパターンは本当に便利で、OOP的にもプログラミングのやり方を大きく変えてしまうのインパクトがあります。

単一継承問題

オブジェクト・モデリングにおいてJavaを実装言語とする際に発生する最大の制約は単一継承です。

Scalaでは、トレイトの導入によってこの制約を大きく緩和することができます。また、ミックスインによるクラス合成、静的型付けの枠組みでの安全なDIといった新たな技法が利用可能になっています。

SimpleModelingでは、区分(powertype)やロール(role)を用いてインヘリタンス(汎化)をできるだけ回避するという方針を取ってきていましたが、Scalaを主力の実装言語とすることで、この方針を採る必要がなくなる可能性が出てきました。

さらに、ミックスインを積極的に活用したドメイン・モデルという可能性も見えてきました。

ロールの編み込み

単一継承問題の有り無しにかかわらず、ロール(role)はドメイン・モデルの重要な構成要素です。ロールを用いないと、物語(business use case)や出来事(event entity)から道具(resource entity)へのつなぎがうまく機能しないのでMindmapModelingでも役割(role)として基本構成要素にしています。

トレイトはロールの実装方式としても有力です。ロールをエンティティにトレイトを使って編み込むというような使い方です。

実装言語でロールが簡単に取り回しできるようになると、ドメイン・モデルでも採用しやすくなりますし、モデル駆動でのプログラム生成でも活用できます。またトレイトでの実装を意識したロールのモデリングの最適化も重要なモデリング技術になってきます。

トレイトでロールを編み込むというアプローチを推し進めていくとDCI(Data, context and interaction)アーキテクチャといった方向性も見えてきます。

このあたりも含めて、トレイトがオブジェクト・モデリングに与える影響はかなり大きそう、というのが現時点での見積りです。

関数型データアクセス

RDBMSへのアクセス法について考える際に、関数型言語の導入で影響がありそうなのが、関数型プログラミングとSQLの相性のよさです。

SQLやその他のQLも一種の関数型言語と考えると、アプリケーション側で関数型プログラミングをしている以上、ORMでSQLを隠すよりSQLを生に使って関数型プログラミングし、アプリケーション側の関数型プログラミングとシームレスにつなげてしまえばよいのではないか、というアプローチが有力に思えます。

このアプローチを採ると、OOPのインヘリタンスとRDBMSのインピーダンスミスマッチ問題は大幅に緩和されます。OOPとRDBMSの接続点で、ORMという枠組みの制約を受けることがなくなりますし、RDBMS側のデータをSQLで臨機応変に、ドメイン・オブジェクトにマップすることができるからです。(この「臨機応変」というところで、オブジェクト・モデリング的に面白い話題があるのですが、これはまた別途。)

つまりRDBMSでの実装を前提としたオブジェクト・モデリングの大きな制約になっていた単一継承問題を解決することができます。

SQLで関係演算をしてドメイン・オブジェクトの情報にマップするというアプローチは、「トレイトによるミックスインによるクラス合成」ともセマンティクス的に近しいものがありそうな感触もありますし、合わせ技で一本取れるかもしれません。

トレイト&関数型データアクセス

以上の議論をまとめると、単一継承問題に関して、プログラミング言語側の制約はトレイトで、RDBMSへの接続は関数型データアクセスで解決できる可能性が見えてきました。

つまり、この2つのボトルネックの解消により、ドメイン・モデルの構築時に(多少の工夫は必要でしょうが)インヘリタンスを禁忌扱いしなくてもよくなります。加えてCakeパターン的なクラス合成を積極的に活用するアプローチも可能になりそうです。

まとめ

これまでFPの切り口でオブジェクト・モデリングの拡張について考えてきましたが、Scalaによって導入されるトレイトも非常にインパクトのある機能です。トレイトがオブジェクト・モデリングに与える影響の可能性について、単一継承問題、ロールの編み込みといったところを考えました。

また、関数型データアクセスと合わせると、ドメイン・モデル構築時にインヘリタンスを禁忌扱いする必要がなくなることに加えて、Cakeパターン的なクラス合成を活用するアプローチも見えてきました。

ScalaによるOOP&FP&トレイトの効果は絶大で、オブジェクト・モデリングにも重大な影響を与えることになりそうです。

0 件のコメント:

コメントを投稿