yojikのlog

yojikのブログです

アニメ ジョジョの奇妙な冒険

これ完全に初期荒木節だなー。
「生き抜こうとするJOJOの肉体が動かしたのだ! JOJOの生命の大車輪が、JOJOの直感をプッシュしたのだ!」

低予算だけど、とても原作愛に溢れた良い作品でした。公式ページのWebラジオを聴くと皆さん同じ方向で取り組む素晴らしいプロジェクトだったんだなーと感じます。多くの声優さん(屍生人役まで)がマイ文庫本を持ってきて台本とセリフを相互チェックするような現場だったそうです。

火山弾にぶっ飛ばされるカーズの気分が味わえる、イタリアシチリア州メッシーナ県 ヴルカーノ島 の地図。↓


大きな地図で見る

Java8でDuckTyping的なこと

Javaのラムダ式のついでに導入されたメソッド参照がなかなか便利な感じです。メソッド参照をつかってDuckTyping的なことができます。

HasName という関数型インタフェースを受け入れるGreeterクラスの定義*1
public class Greeter {
  /** 関数型インタフェースの定義 */
  @FunctionalInterface
  interface HasName { String getName();}
  
  /** 「名前を持っているオブジェクトに挨拶をしてもらう」メソッド */
  public void greet(HasName... targets) {
        for(HasName it : targets) {
            System.out.println(it.getName());
        };
  }
}
「HasNameの関数型インタフェースと同じシグネチャを持つメソッド」を持つクラスの定義

ただし引数と戻り値さえあっていれば、HasNameインタフェースを実装する必要もないし、名前をあわせる必要も無いです。

class Duck {
    public String name() {
        return "duck";
    }
}
class Dog {
    public String myname() {
        return "dog";
    }
}
Greeter::greetメソッドにメソッド参照を渡す

DuckやDogのインスタンスからメソッド参照を取りだしgreetメソッドに渡す。メソッドの引数戻り値さえあっていればどんなクラス/インスタンスのメソッドでも渡すことができます。

もちろんクロージャにおける「環境」のように、インスタンスの情報*2も一緒についていきます。*3

public class Sample {
    public static void main(String[] args) {
        Greeter  g = new Greeter();
        Duck duck= new Duck();
        Dog dog  = new Dog();
        g.greet(duck::name, dog::myname);
    }
}

*1:@FunctionalInterfaceアノテーションは無くても別にいいですが、書いておくと定義が関数型インタフェースに沿っているかチェックしてくれます

*2:この場合ならduckやdogのインスタンス変数の情報。定義してないけど

*3:メソッド参照に対応するインスタンスのクラスはSample$$Lambda$数字 という名前になるようです。なおコンパイル時ではなく動的に生成されている模様

DCIの疑問点をまとめる

以下勉強会(DCI hansei meetup)用のメモです。

自分の立場

問題意識は理解できる。しかしこの問題は以前から理解されていたものであり、それぞれの方法論等で常に問題になっているものである。DCIで解決策として示されているものが、それ以外の方法に比べて特にすぐれているとは思えない。

DCIに関する自分の理解

DCIとは

スピリチュアルなことを別とすればMVCと同様のアーキテクチャパターン

http://d.hatena.ne.jp/digitalsoul/20100131/1264925022

コンテキスト

ユーザーとの相互作用があるソフトウェアをつくる際には、ユーザの意図とソフトウェアの内部で起きていることを同期させる必要がある。具体的にはGUIアプリケーションの構築時など。

DCIが解決しようとしている問題

従来のMVVの道具(オブジェクト指向の道具)では、、いろいろな不具合がある!

ユーザのメンタルモデルをソフトウェアが表現できていない。

オブジェクト指向の道具(クラス、インスタンスインスタンス間で交換されるメッセージ)では、メンタルモデルの構造を表現すのには向いているが、「振る舞い」を正しくマッピングできない。

複数の小さなオブジェクトが分担してアルゴリズムを実行するというモデルはユーザのメンタルモデルから乖離し風雑さを増している。(余談ですがアルゴリズムという言い方は(ビジネスロジックという言い方より明確でいいですね))

どのオブジェクトが振る舞いのどの部分を分担するのかは常に明確じゃない。(新人研修のころ「サイコロ」をモデル化するために、「人間がサイコロを振る」「サイコロが転がる」のか一日論争になった記憶がよみがえります)

継承の問題点もろもろ

良くある話なので割愛

データモデルは安定し、アルゴリズムは安定しない。

したがってドメインクラスはデータの処理をおこなってはならない

ちなみに元の論文ではモデルの肥大化については特に語っていません。(間接的には関係あると思いますが)

フォース

  • マインドモデルの「構造」を捉えるのはオブジェクト指向の道具(ドメインモデルとか)が適している けど、
  • 振る舞いはむしろFortran時代のような手続き型、集中化された記述が適している

と、Trygve Reenskaug氏とJames O. Coplien氏 は考えている

この矛盾したフォースを調和させるために、、

解決策

システムの構成要素を以下のように分割する

  • 振る舞いを持たないデータ
  • 特定のユースケース(コンテキスト)に参加するオブジェクトの振舞いをまとめたロール
    • (技術的にはTraits等で実現する)
  • データをロールを紐つけるコンテキスト

特定のコンテキスト(ユースケース)実行時には、データに対して、そのデータがそのコンテキストで振舞うべきことを記述したロールを組み込み、アルゴリズムを実行させる。

ちなみにコンテキストはネストすることも可能

ここから俺の疑問です

実現手段としての「トレイト」の問題点

メンタルモデルとドメインモデルの乖離問題はよくわかる。しかし、そこで問題となるのは振る舞いとデータの乖離ではなく、粒度ではないのか。(トレイトでは解決しないのでは)

例えば論文のサンプルにあった預金口座オブジェクトに対応するデータ構造はふつうの銀行関連アプリケーションにはないだろう 。通常はトランザクションや監査ログなどの細かいデータの集合として実現される(論文でも触れていますが)

トレイトとしてロールを表現する場合、対象となるデータオブジェクトに対して振る舞いを組み込むのみ。メソッドが増えたり減ったりするのみ。 粒度の違いについては解決しない。

上記の例だと口座を構成する複数のデータのうちどれにロール被せればいいのかわからない。

問題を記述するには細かすぎるオブジェクトを集約して大きな粒度であつかう技法が必要なのでは

  • アダプタやサービス、ファサードを使った間接層をはさむとか
  • 集約ルートを使ってデータ(的)オブジェクトよりは大きな単位で処理を記述するとか
  • SQLアンチパターンではActiveRecordを持つドメインモデルを導入(永続データと処理を行なうオブジェクトの分離)
  • OOSEにおけるBCEも少し関係するかも

上記方式ではなく、トレイトを使うとオブジェクトの同一性が保たれるのがメリットとされるが、なぜメリットなのかよくわからない。

※振る舞いの再利用手段としてのトレイトは否定しません。たとえば、永続化機能がないドメインオブジェクトにActiveRecordトレイトを組み込むとか、そういう用途に便利そう。

データオブジェクトがコンテキスト共通であるという誤解

特定にコンテキストしか使わないデータオブジェクトというのは確実に存在する(つまりデータのレベルでもコンテキストに依存するものがある)

結局データの階層がシステムでもっともロバストだというのは幻想である。データの中にもシステム共通のもの、それぞれのコンテキスト依存のものがあり、保守のライフサイクルが異なるはず。ライフサイクルが異なるものはパッケージやレイヤなどで分離した方がいい。

またドメインモデル、データモデルの段階でロールっぽいものを抽出する方法論も存在する。データだからコンテキスト共通ということはない。。

例:

  • UML in Color (Peter Coad)におけるロール
    • ドメインモデルを分析する段階で、ロールオブジェクトを抽出し、共通のドメインオブジェクトに集約させる (DCIとは依存の)
    • 「ロール」は「パーティ/場所/物)」がイベント(瞬間時間間隔)にどのように参加するかを示す

その他: T字系のVirtualEntityとか(自信なし)

コンテキストが複数ある場合のパターンが示されていない

元論文ではコンテキストを別のコンテキストから利用するというケースが想定されている。しかしその実現手段については述べられていない。コンテキストはマクロな目でみればデータ(状態)と振る舞いを持つふつうのオブジェクトであり、これらが協調動作する、というのは結局一周し元のモデルに戻っているのでは。

WDYT?