2011年11月19日土曜日

横浜モデリング勉強会 (第2回)

今日(11/19)のモデリング勉強会の情報です。

http://atnd.org/events/21756

今回モデリングするのは以下のWeb記事です。

テーマ:  崖っぷちの欧州、ローマの炎上を許すな

モデリングは記事の問題領域であるドメインモデルを作成を目標にします。
  • 問題領域の構造を、エンジニアでない人が理解できるで構築している。
  • プログラムに落し込むことができる。
モデリングは各自のお好きなモデリング手法で行います。
一時間に一度程度、作成途中のモデルを見ながら議論します。
初学者の方は、MindmapModelingをお勧めします。

2011年10月31日月曜日

「TPP議論の本質はこれだ!」のマインドマップとクラス図

10月29日(土)に横浜モデリング勉強会を行いました。
札幌サテライトから2名参加があり合計6名の参加でした。
参加された皆さん、どうもありがとうございました。

この勉強会で、浅海が作成したモデルを紹介します。
モデルはMindmapModelingの手法で作成しました。(勉強会で使用したチュートリアル)

モデリングの対象は、田原総一朗氏のブログ記事「TPP議論の本質はこれだ!」です。時事ネタなのと、いろいろな情報が交錯していて、掴みどころがないのが、モデリングの練習によい感じです。
この記事における現実世界の構造をオブジェクトモデルとして抽出するという趣旨です。

まず、最初の作業で記事中から単語を抜き出します。
単語を抜き出しながら、登場人物、道具、出来事を中心にMindmapModelingの定めた分類に従って仕分けしていきます。
この結果、できた最初のマインドマップが以下のものです。(図をクリックすると拡大します。)


次の段階では、抽出した、登場人物、道具、出来事の洗練を行います。
用語の名寄せ、用語の種類(generalization)や部品構成(aggregation)を整理していきます。
また、この段階で区分(powertype)の抽出を開始します。
以上の作業を行った結果のマインドマップは以下のものです。


次の段階では、対象となる世界の動的な側面を捉える出来事や物語を整理していきます。
出来事や物語を洗練していくことによって、出来事や物語における登場人物や道具の役割が明確化され、より登場人物や道具の構造をさらに洗練させることができます。
出来事や物語で抽出した役割は、役割(role)としてモデル化して「役割」構造枝に配置し、役割の持つ構造を洗練していきます。

以上の作業の結果、作成したマインドマップが以下のものです。


モデリング勉強会での作業はここまででした。
その後、このマインドマップをSimpleModelerでクラス図に変換したものが以下のクラス図です。(クリックすると拡大します。)
クラス図にしてみると、まだまだ抜けているところがあることがよく分かります。
モデルとして欠陥があるわけではなさそうですが、名寄せが甘いところや、時間切れでモデルに記述しきれなかったところが明確になりました。


そこで、SimpleModelerでのクラス図生成を繰り返しながら洗練したマインドマップが以下のものです。


このマインドマップをSimpleModelerを使ってクラス図に変換したものが以下のクラス図です。(クリックすると拡大します。)
記事における現実世界の構造がそれなりに上手くとらえられていると思います。
短い記事ですが、丹念にモデル化していると存外大きな構造が背景にあることが分かります。



物語は記事中で一番重要視していると思われる「アメリカのアジア戦略」を抽出しましたが、時間があれば「アメリカの輸出増加戦略」や「日本のTPP外交戦略」というような物語を加えるとより内容が充実してくると思います。

2011年10月29日土曜日

モデリング勉強会

今日(10/29)のモデリング勉強会の情報です。

http://atnd.org/events/20884

今回モデリングするのは以下のブログ記事です。

テーマ:  TPP議論の本質はこれだ!

モデリングは各自のお好きなモデリング手法で行います。
一時間に一度程度、作成途中のモデルを見ながら議論します。

初学者の方は、MindmapModelingをお勧めします。

クラウド時代のデータアーキテクチャとモデリング

クラウド時代のデータアーキテクチャとモデリングについてちょっと思いついたことがあるのでメモ。



クラウドアプリケーションが従来のアプリケーションと異なる点の一つは、クラウド上に遍在する様々なデータをマッシュアップして使用することになるという点です。
自前で管理するデータだけでなく外部データを編みこんだドメインモデルに対して、アプリケーションが操作を行うことになります。
また、スケーラビリティを確保するため、CQRSのように参照系と更新系をアーキテクチャレベルで分割していく形が基本になるでしょう。
これは、自前データのサイズが巨大になる場合への対応にも有効ですが、外部データとの連携では必須のアーキテクチャです。自前データが巨大にならない普通のアプリケーションでも、外部データとの連携を行うのであれば、このアーキテクチャを採るのが得策です。

ドメインモデル

このアーキテクチャの上でドメインモデルは、以下の3つの種類に分類するのがよいのではないかというのがアイデア。

  • Application Domain
  • Actor Domain
  • Fact Domain
Application Domainは、アプリケーションが操作するドメイン。自前データと外部データをマッシュアップして見せます。
従来のドメインモデルとの違いは、外部データをマッシュアップすること。マッシュアップを行う場合、更新系を含めると実現方法が大変になってくるので、参照系を中心にするとよいでしょう。都合のよいことに参照系と更新系を分離するアーキテクチャにもマッチしています。
従来技術でもRDBMSのViewなどでこういった事が可能ですが、これをもっとアーキテクチャレベルで大掛かりにやるイメージです。(そういう意味ではデータベースの3層スキーマが近しいかも。)

外部データは、Actor Domainとしてモデル化します。Actor Objectは、アプリケーション外にあるオブジェクト(の代理オブジェクト)という意味ですが、このドメインモデル版という意図でActor Domainという名前にしてみました。
Actor Objectの場合、自前のオブジェクトでないので、決められた範囲でお願いはできるけど自由に操作できないという処理上の制約が出てきます。
Actor Domainもそういった制約を持ったドメインモデルをイメージしています。

そして、Actor Domainの外側にFact Domainを持ってきました。
Fact Domainは、クラウド上で発生する無数のイベントの生データをイメージしています。たとえばアプリケーションのログや、データベースのジャーナルなどです。

Actor Domainはアプリケーションの外部で、Fact Domainのデータを集約し、意味を付加したモデルとしてモデルインスタンスが公開されています。

Application Domainは、このAcotr Domainのインスタンスを、自前データとマッシュアップして、アプリケーションに取って意味のあるモデルのインスタンスとして、アプリケーションに提供します。

更新系

更新系には、Application Commandというモジュールを用意しました。(Commandというのは仮です。他によい名前があったら取り替えると思います。)
Application Commandは自前のデータの更新を中心に、Application Domainへの更新依頼、Fact Domainの情報提供を行います。
Application Domainへの更新依頼はあまり多くないという仮定で点線にしてみました。

モデリング技術

こういったデータアーキテクチャを採る場合のモデリング技術として、どうも文書モデリング(SGML, XML系)が有効でないかというのが、データアーキテクチャと同時に思いついたアイデア。
従来アプリケーションでは、データモデル/オブジェクトモデルがモデリングの中心でしたが、ここまで説明してきたようなマッシュアップが基本となるデータアーキテクチャでは、異なったセマンティクスのモデルをマッシュアップする基盤として文書モデリングが重要になってくるのではないかということです。
2000年頃にも、こういう話題がよく出たと思いますが、クラウド時代になって改めて、この技術を適用する形が見えてきた感触です。
ただし、今回はXMLという文脈でなく、関数型という文脈ではないかというのが、今回のアイデアの軸。関数型プログラミングと文書モデリングの相性は相当よさそうです。
XMLはデータ表現形式としてはよいのですが、データ操作体系としてはまだまだ不十分でした。ここを関数型言語ですっきりと記述することが可能になってきたのは一つミッシングリンクが埋まってきた感じです。

オブジェクトモデル、データモデル、文書モデル、関数モデル。
Application Domainのメタモデルとして、4つのモデルをどのように配合していくとよいのか。まだまだノーアイデアですが、未開拓の領域だけに色々と面白そうです。
クラウドも現時点では、プラットフォーム技術やフレームワーク、プログラミング言語といった実装よりの技術に焦点があっていますが、次の段階ではこういったモデリング技術の所に焦点が移ってくるのではないかと考えています。

2011年9月19日月曜日

RESTのFeedを一覧表示するActivityの生成

8月27,28日に開催されたクラウド温泉@小樽のセッション、「クラウドアプリケーション(App Engine&Android)自動生成 - SimpleModeler/g3/g4デモ」でのSimpleModelerからAndroidアプリの自動生成のデモの話の続きです。

SimpleModelerでは、アプリケーション開発のベースとなるドメインモデルの実装を「自動コーディング」します。この部分はドメインモデルが決まれば、プラットフォーム上での実装はほぼ決まるので自動生成の格好のターゲットです。逆に、この部分を手組みでコーディングしていると相当の工数が必要となります。プログラム開発の生産性を上げるためには、この部分の生産性向上が重要になってきます。

ただし、エンティティに対するCRUD処理については自動生成である程度のモノを生成可能です。アプリケーション部分のサンプルという意味もこめて、データに対するCRUD処理を行なうActivityを生成する予定で、一部実現しています。

現在SimpleModelerが自動生成しているのは、サーバー上に格納されているエンティティCustomerをREST経由でアクセスして一覧表示を行うプログラムが以下のCustomerRestViewActivityです。

package com.demo;

import android.content.Context;
import android.os.Bundle;
import java.math.*;
import java.util.*;
import org.goldenport.android.*;
import org.goldenport.android.traits.ListViewTrait;

public class CustomerRestViewActivity extends GActivity<DemoController> {
    
    // @LayoutView(R.id.header)
    // TextView mHeader;
    // @ResourceString(R.string.header)
    // String mHeaderLabel;
    // @ResourceColor(R.color.header)
    // Color mHeaderColor;
    // @IntentExtra("message")
    // String mMessage;
    
    public CustomerRestViewActivity() {
        addTrait(new ListViewTrait());
    }
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    
    @Override
    protected int get_Layout_id() {
        return R.layout.customer_rest_view;
    }
    
    @Override
    protected void onStart() {
        super.onStart();
    //    if (mMessage != null) {
    //        mHeader.setText(mMessage);
    //    } else {
    //        mHeader.setText(mHeaderLabel);
    //    }
        set_list_adapter(gcontroller.getCustomerRestFeedAdapter());
    }
}

GActivity


CustomerRestViewActivityは、サーバー上に格納されているエンティティCustomerをRESTでアクセスしてListViewの一覧として表示するActivityです。基底クラスはGActivityで、型パラメータとしてDemoアプリケーションのコントローラであるDemoControllerを指定しています。

org.goldenport.android.GActivityが、g4におけるActivityの基底クラスです。主に以下の機能を提供しています。

  • DI
  • コントローラクラスの自動バインド
  • トレイトによる機能拡張
  • 非同期更新処理

DI(Dependency Injection)

g4では、Google Guice (without AOP)を用いたDIコンテナ機能を提供しています。XMLで定義された各種ViewやリソースをActivityのインスタンス変数に自動インジェクトすることができます。
自動生成されたCustomerRestViewActivityを、自前で拡張するためのヒントとして以下のコメントが入っています。
この機能は次回の記事で説明することにします。
// @LayoutView(R.id.header)
    // TextView mHeader;
    // @ResourceString(R.string.header)
    // String mHeaderLabel;
    // @ResourceColor(R.color.header)
    // Color mHeaderColor;
    // @IntentExtra("message")
    // String mMessage;

コントローラクラスの自動バインド

g4では、画面表示を行うクラスであるGActivity(Activityのサブクラス)から、アプリケーション・ロジックを分離してコントローラとして実装します。コントローラはGControllerのサブクラスになります。
Activityからアプリケーションロジックを分離して、コントローラ側で実現することにより、以下の効果を期待しています。
  • アプリケーション全体のロジックをコントローラに集中させることで、アプリケーションの見通しを良くし、拡張性、保守性を高める。
  • GUIを経由しないで、アプリケーションロジックのユニットを可能にする。
  • アプリケーションロジックを複数のActivityから共用できる。
GActivityでは、コントローラクラスを自動的にインジェクトするので、GActivityの実装では、特に初期化処理なしでコントローラを参照して使うことができます。 
生成されたonStartメソッドにはヒントのコメントがあります。この不要なコメントを削除したonStartメソッドは以下のものになります。
@Override
    protected void onStart() {
        super.onStart();
        set_list_adapter(gcontroller.getCustomerRestFeedAdapter());
    }
「super.onStart()」はお約束。
set_list_adapterメソッドで、コントローラから返されるListAdapterを設定しています。
GActivityで定義しているインスタンス変数gcontrollerから参照しているコントローラ(DemoController)から、ドメインエンティティCustomerをRESTのフィードとしてアクセスするListAdapterを取得しています。
このListAdapterは、バックエンドにページング付きのREST通信と通信結果のキャッシュ機能を持っています。この機能を実現するために、SimpldeModelerが生成するAndroidコードで説明したとおり、ActivityからRESTドライバにいたるまで相当数のコードが自動生成されています。また、g4ベースでサーバサイドのコードも自動生成していることは、SimpleModeler (クラウド温泉@小樽)で触れました。このあたりのメカニズムはいずれ紹介したいと思います。

トレイトによる機能拡張

ActivityにListViewやGralleryなどを操作するロジックをハードコーディングしてしまうと、ロジックを他の目的に再利用させることができません。
これらの機能を持つ基底クラスを作るのが次善策ですが、拡張性や保守性に問題があります。
この問題を解決するために、g4ではScalaのトレイトライクなメカニズムを導入しました。
ListViewTraitは、ListViewを操作する機能を持つトレイトです。GActivityのaddTraitメソッドによりListViewTraitを追加することによりGActivityにListViewを操作する機能が追加されます。
以下のようにコンストラクタでトレイトListViweTraitを追加しています。
public CustomerRestViewActivity() {
        addTrait(new ListViewTrait());
    }

非同期更新処理

ListViewTraitが内部で自動的にハンドリングしているので、CustomerRestViewActivityには直接みえていません。
ListViewTraitが、一覧データのローディング時にプログレスバーを画面上に表示し、ローディングが完了した時点で表示を終了する処理を行っています。

2011年9月1日木曜日

SimpldeModelerが生成するAndroidコード

8月27,28日に開催されたクラウド温泉@小樽では、「クラウドアプリケーション(App Engine&Android)自動生成?SimpleModeler/g3/g4デモ」のセッションで、SimpleModelerからAndroidアプリの自動生成のデモを行いました。

クラウド温泉@小樽に向けてブログに書いてきたものを実演しました。

デモに使ったモデルは以下のCSV、demo.csvをコンバートして生成したDEACustomer.java、DEEBuy.java、DERGoods.javaの3つのScala DSLで記述したものです。

demo.csv
#actor,parts,attrs
customer,,phone
#resource
goods,,note
#event
buy,customer;goods
そのうちの一つ、DEACustomer.javaのソースコードは以下のものです。DEEBuy.javaとDERGoods.javaもだいたい同じコードになります。

DEACustomer.java
package com.demo

import org.simplemodeling.dsl._
import org.simplemodeling.dsl.datatype._
import org.simplemodeling.dsl.domain._
import org.simplemodeling.dsl.domain.values._

case class DEACustomer extends DomainActor {
  term = "customer"
  caption = "customer"
  brief = <t></t>
  description = <text></text>

  id("customerId", DVICustomerId())
  attribute("name", DVNCustomerName())
  attribute("summary", XString)
  attribute("phone", XString)
}

case class DVICustomerId extends DomainValueId {
  term = "customerId"
  caption = "customerId"
  brief = <t></t>
  description = <text></text>

  attribute("value", XString)
}

case class DVNCustomerName extends DomainValueName {
  term = "customerName"
  caption = "customerName"
  brief = <t></t>
  description = <text></text>

  attribute("value", XString)
}
デモでは、このモデルからg4上で動作するJavaソースコードを生成し、Androidアプリケーションとして動作させました。Javaソースコードの生成は、一部デモに間に合わなかったものもあったので、その後、少し改良しました。その改良版では、以下のソースコード(33ファイル、4.7Kステップ)を生成します。
  • BuyRestFeedAdapter.java
  • BuyRestFeedRepository.java
  • BuyRestViewActivity.java
  • CustomerRestFeedAdapter.java
  • CustomerRestFeedRepository.java
  • CustomerRestViewActivity.java
  • DDBuy.java
  • DDCustomer.java
  • DDGoods.java
  • DEACustomer.java
  • DEEBuy.java
  • DERGoods.java
  • DVIBuyId.java
  • DVICustomerId.java
  • DVIGoodsId.java
  • DVNCustomerName.java
  • DVNGoodsName.java
  • DemoAgent.java
  • DemoApplication.java
  • DemoContext.java
  • DemoContract.java
  • DemoController.java
  • DemoErrorModel.java
  • DemoFactory.java
  • DemoG3Driver.java
  • DemoModel.java
  • DemoModule.java
  • DemoProvider.java
  • DemoRepository.java
  • GoodsRestFeedAdapter.java
  • GoodsRestFeedRepository.java
  • GoodsRestViewActivity.java
  • IDemoRestDriver.java
このJavaプログラムをクラス図にすると以下のようになります。
BuyRestViewActivity, CustomerRestViewActivity, GoodsRestViewActivityがAndroidの画面クラスであるActivity(Androidの画面クラス)です。これらのActivityがサーバー上に格納されているデータを画面に表示します。
これらのActivityからDemoControllerを経由して、ドメインモデルを管理するクラスDemoModelにアクセスします。データの管理は、サーバーから取得したフィードデータをメモリ上に保持するクラスBuyRestFeedRepository, CustomerRestFeedRepository, GoodsRestFeedRepositoryで行い、これらのクラスをAndroidのウィジェットであるListView用のアダプタBuyRestFeedAdapter, CustomerRestFeedAdapter, GoodsRestFeedAdapterが使用します。
また、サーバーとの通信はDemoG3Driverが行います。今回のデモではサーバー側はg3なので、g3と通信するためのドライバを使用していますが、ドライバはインタフェースIDemoRestDriverを実装していれば取り替え可能な構造になっています。
クラス図の下に、Documentオブジェクト(DTO)であるDDCustomer, DDBuy, DDGoodsがありますが、これらのオブジェクトでデータのやりとりを行います。
クラス図のざっくりとした説明は以上の通りです。追々詳細な情報を書いていく予定です。
ここで強調したいのは、(トイプログラムではなくて)ある程度本格的なアプリケーションを作成する場合、ごく小さなドメインモデルからでも、これらのクラス群を作成しなければならないということです。一般的なJavaプログラムでも必要なものもありますし、Android特有のクラスもありますが、いずれにしても相当量のコーディングが必要になります。しかも、これらのクラス群はドメインモデルが決まれば、Android上でどう実装するのかというのも、ほとんど決まってしまうので、人力でコーディングするのは、かなりもったいない作業です。こういった定型部分を自動コーディングしてしまうことがSimpleModelerの目的です。

2011年8月31日水曜日

F#考 - クラウド温泉2.0@小樽

8月27,28日にクラウド温泉@小樽が開催されました。今回のクラウド温泉も盛りだくさんの内容で、ボクとしてはF#について詳しいお話を聞けたのが収穫でした。発表者の@bleisさん、MSの荒井さん、参加者の皆様、どうもありがとうございました。

F#はScalaと同じオブジェクト指向と関数型のハイブリッド言語で、ざっくりとはだいたい同じことができると捉えてみてよさそうです。ただし、言語の狙いは異なるので、利用シーンは違ってきます。

以下、F#の知識は当日の聞きかじりを元にしているので、不正確なところが多いと思いますが、ボクの現時点での認識のメモということでご了承ください。

F#の言語のセマンティクスは関数型が主でオブジェクト指向は従のようです。

関数型の世界で扱うデータはレコード/タプルで、構造体的な言語要素となっています。そして、このレコードとは別にクラス/オブジェクトが用意されています。(変数に関数をバインドしてメソッド的に使えるかもしれませんが、この点は未確認。)
つまりデータを記述する言語要素が二系統あって、そのうちの一系統を使うと関数型言語らしいプログラミングが堪能できるということですね。

一方、クラス/オブジェクトは、当日確認しなかったのですが、恐らく.NETのクラス/オブジェクトだろうと思います。クラス/オブジェクトを通じて.NETのクラス/オブジェクトをC#やVBと相互に連携できるのではないかと推測します。

データを記述する言語要素が二系統あるのは、関数型言語としての純粋性を保ちたかったということもあるでしょうし、.NETのクラス/オブジェクトを関数型言語向けに拡張するのが難しかった、という制約に起因するところもありそうです。

また、データは基本的にイミュータブルで、mutableというキーワードを付けるとミュータブルにもできるというアプローチになっています。この点からも関数型の方に軸足があることが分かります。このため、状態の存在を前提としたプログラミングには、あまり向いておらず、つまるところオブジェクト指向プログラミング言語としてはあまり快適ではなさそうです。

F#では、型パラメータの省略ができて簡潔な記述が可能になっていますが、関数をオブジェクトのメソッドとしてポリモーフィックに動かすことをやめることにより(クラス/オブジェクトではなくレコード/タプルを使う効果)、共変/反変まわりの指定を考えなくてもよいので、そのあたりが寄与しているのかなと感じました。これも、関数型側に軸足を持っている効果です。

以上のようにF#は関数型側に大きく機能を倒して、オブジェクト指向的にはほどほどにして、関数型言語の美点を伸ばしていくアプローチのようです。

このアプローチの延長線上で、コンピューテーション式、seq/yieldといったところが、関数型言語の高度な応用で、マニア的に面白いところですね。どちらもDSLの記述力を高めることに大きく寄与する機能です。

F#は関数型言語として素晴らしい言語であるのは確かですが、関数型側に機能を倒しているため、オブジェクト指向言語としては快適というわけではなく、実務へ適用する汎用言語としては考えにくいのかなという印象を持ちました。F#一本ですべての応用を記述する、ということにはならないかなと。

そこで、F#を取り囲む文脈を考えてみましょう。F#は.NET上で動作することを前提とした言語であり、C#やC++といった.NETの他の言語と共存することが前提です。

C#の場合は、VBなどを置き換えていって、.NETの中心言語にしていくという意図もあったかと思いますが、F#の場合は、C#を置き換えるといったことは意図しておらず、C#を補完する立場になるでしょう。そうすると、C#ができることを全部カバーした上で、新たに関数型の機能を追加するといったことをする必要はなく、オブジェクト指向的な文法は.NETのクラス/オブジェクトと連携できるものがあれば十分と割り切ることができます。その上で、C#ではできない関数型のプログラミングモデルを使いやすいものにする方向に力をそそいでいるわけですね。

そういう意味で、F#は.NETワールドを構成するパーツの一つとして、並列プログラミングやDSLといった関数型に適した分野をカバーする専用言語という戦略上の意図を持った言語であると推測されます。
今後の技術の発展の方向は並列プログラミングとDSLが二大潮流になることは確実なので、この2つの分野に強い関数型言語を並行プログラミングとDSL向けを意識してチューニングし、.NETワールド内でのポジションを明確にした上で提供してきているのにはMicrosoftの底力を感じました。

F#は、monoと組合わせてMacやLinuxでも普通に動くみたいなので、DSLにフォーカスした応用ではプラットフォームを問わず実用的に使用できそうです。そういう意味でも面白い存在です。