BT

最新技術を追い求めるデベロッパのための情報コミュニティ

寄稿

Topics

地域を選ぶ

InfoQ ホームページ ニュース データ、コンテキスト、相互作用 : James O. Coplien氏とTrygve Reenskau氏による新しい設計方法

データ、コンテキスト、相互作用 : James O. Coplien氏とTrygve Reenskau氏による新しい設計方法

ブックマーク

原文(投稿日:2009/5/8)へのリンク

 James O. Coplien氏とTrygve Reenskaug氏は、オブジェクト指向プログラミングの新しい設計方法を紹介する 連載の最初の記事をこのほど公開した。その設計方法とはデータ(Data)、コンテキスト(Context)、相互作用(Interaction) パターン(DCI) に基づくものである。

この最初の記事で、オブジェクト指向プログラミングは構造を捉える手段としては役立つものの「エンドユーザの振る舞いに関する要求」を示すことができないため、ユーザが思い描くモデルを完全に表現できない、と著者は主張する。「振る舞い」が具体的に何を意味するのか、著者は口座オブジェクトを例に挙げた。例えば、口座オブジェクトは、残高を減らしたり、預金を引き出したりすることができる。Coplien氏とReenskaug氏によれば、「この2つの振る舞いは、根本的に違う。残高を減らす行為は、『どういう状態にあるか』というデータの特性にすぎない。しかし、預金を引き出すという行為は、『何をするのか』というデータの目的を反映する。」のである。 どのような状況であれ、残高を減らすことができるという事実はデータの特性を示し、変動しない。対して、預金を引き出すことは「ATMの画面や音声ガイドとのやりとり」を含み 、動的であり、『どうあるか』ではなく『どうするか』にかかわる問題である。

ユーザモデルでは「どうあるか」と「どうするか」を自然に同一視してしまうため、「『どうするか』を把握しコードでどのように表現したらよいのか、オブジェクト指向では少ししか、そしてMVCでは全く、開発者にはわからない。」 「オブジェクト指向は (この2つの作用を)一緒くたにしている。」そのため、設計から保守までのあらゆる局面で非常に重要であるにもかかわらず、「シンプルで変動しないデータモデルと動的な振る舞いモデル」を分けて考えることが難しいのである。さらに、純粋なオブジェクト指向では巨大なアルゴリズムはメソッドに分解し、最も密接に結びついたオブジェクトにばらばらに配置することを要求する。一部のアルゴリズムは分断されずにひとつのオブジェクトに配置されるかもしれない。しかし、「往々にしてビジネス上有用な機能がオブジェクト間をまたいで存在することになる。」

このような動的振る舞いモデルを表現するために、James氏とTrygve氏は以下の3つの概念に基づくDCIモデルを使用するべきであると言及した。

-       データ(data)、 ドメインオブジェクトにより表現され、変動のない部分を表す。

-       相互作用(interactions)、「オブジェクトが『どうするか』に関する、一連の振る舞い」ともいうべきロールとして表現される。

-       コンテキスト(context)、ひとつの表としてみることができる。この表は「ロールを表す関数(表の列)とオブジェクトのメソッド(表の行はオブジェクト)を関連付ける。表を埋めるのは、プログラマが提供するBIである。このBIにより、与えられたユースケース内でどのオブジェクトがどのロールを担うべきなのか、コンテキストオブジェクトが把握することが可能となる。」

このモデルを具体的に理解するために、著者は送金ユースケースを例に挙げた。送金は預金口座や投資口座などが関与するものの、この特定のユースケースにおいてユーザは『送金元口座』と 『送金先口座』という言葉を用いて表現することが多い。これらがロールであり、送金の相互作用はアルゴリズムによって説明することができる。これらのロールはコンテキストにより異なるオブジェクトに付与することも可能である。送金の例では、送金元口座というロールを預金口座オブジェクトと結びつけるのだ。

コード内でロールを表現するには、traitという設計概念を使用するのが一般的であるが、その実装はScalaのtraits、Squeak Smalltalkの Squeak Traits、C++のtemplates など、各プログラミング言語の構成によって異なる。この手法の最も優れている点は、プログラマによって提供されるコードがそのまま、「ほぼユースケースを自然言語で表したものになっている」点である。

この設計方法によれば、ロジックが複数のクラス間にまたがって存在する場合に比べ、より理解しやすい形になります。ロジックは自然に組み合わさっているため各ロジックの境界ははっきりしないですし、エンドユーザの思い描くモデルもたいてい分割困難なものです。

この記事は多くの反響と批判を呼び、またJames氏とTrygve氏にDCIの概念に関する詳細な説明を求める声が集まった。

Michael Feather氏とその他大勢のコメンテータは、送金に関する責任を送金元口座に割り当てることこそ不明瞭であり、ユーザが思い描く現実のモデルにそぐわないと主張する。 なぜなら、多くのユーザは、送金は口座ではなく銀行や「取引オブジェクトなどに対応する相互作用モデル」で行われると思うだろうから、というのである。 John Zabroski氏は、例えば振替伝票(TransferSlip)といった分析クラスを使用することを主張する。また、DCIが既知の事柄に関連することに対しても議論が起こっている。それはある言語でいうところの「traits」である。 「(関数プログラミング)における一般的な概念。アルゴリズムの問題であり、明確に示されなければならない。」 などという意見があがった。

James O. Coplien氏はこの議論に対して以下のように返事した。DCIは 「1980年代のオブジェクト指向以降ドメインモデルに関するたくさんの良好な観念とあいまって、(Fortranなどの)手続き的言語がもたらしたアルゴリズム的表現の便利さを再び提供しようとしている。」 。Scalaなどの言語におけるTraitsは「これらを解決するためのひとつの方法ではある」 が、他の言語でも異なる構成を用いればDCIの構造を取り入れることが可能である。 私はツールを紹介したり、例を示したいわけではない。1) どのような状況においてもドメインオブジェクトを特定するような振る舞い と 2) ビジネスロジックに属し、往々してオブジェクト間にまたがって存在するあるコンテキストに特有な振る舞い を分離する、という設計方法そのものを紹介したいのである。 Bill Venners氏も以下のように言及する。「口座の概念がアプリケーション内の10個のユースケースに関係するとしたら、 今までの方法であれば全てのユースケースの振る舞いを口座クラスに実装することになる」 が、このような設計にはさまざまな課題が潜んでいる。それならば、「オブジェクトに、それぞれのコンテキストを表す別のクラスをもたせたらどうか。」 DCIを適用することにより、「OOプログラムはよりわかりやすいものとなるだろう。」

[…] ひとつのオブジェクトにあまりに多く(の振る舞い)を盛り込みすぎる傾向にあること、そしてこれらの振る舞いの特定の組み合わせが別のコンテキストで必要になる場合があることを、この記事は指摘しています。 オブジェクトにとって余分なものをtraitsとしてモデリングすること、そしてtraitsはユーザの思い描くモデルの中のロールとマッピングする(ことを著者は主張しています)。さらに 特定のコンテキスト、あるいはユースケースにおいて、機能を持たないドメインオブジェクトに必要なtraitsを付加していくのです。

またDCIにより可読性があがることも主張している。Coplien氏はコードが読みやすくデバグが容易になる理由を4つ挙げている。

1.コンテキストがビジネスの機能間にまたがって存在するようなことがあまり見られなくなります。これによりコンテキストは、(ドメインに基づく)プログラマのモデルより(ロールに基づく)ユーザが思い描くモデルに近いものになります。
2. 包含ポリモーフィズムが完全になくなります。もしfoo関数を実行したら、ただひとつのfoo関数の結果が返されます。継承階層の上から下まで、あらゆるところに存在するfoo関数のうちどれが実行されたか判断する必要がなくなります。
3. ソフトウェアがビジネス上価値ある何かを生み出すか確かめるためにどこをテストすればよいか、見つけられるようになります。つまり、本当の意味でBDD(ビジネス駆動開発)をすることができます。これにより、デバグをサポートするテストケースを容易に開発できるようになります。
4. コンパイル時のコードがより読みやすくなるため、実行時のデバグを最小限に抑えることができます。

Trygve Reenskaug氏はDCIを理解するためには、以下のようにする必要があると強調します。 「クラスの抽象化という概念から視線を挙げ、このオブジェクト構造に適用する新たな抽象概念に心を傾けよう」 、そして「クラスを増補し、オブジェクトのアイデンティティを保持する抽象概念をオブジェクト」、つまりロール「を付加しよう。」 

この記事に星をつける

おすすめ度
スタイル

BT