++C++; // 未確認飛行 C ブログ

http://ufcpp.net/

ViewModel とかいちいち書いてられないよね

leave a comment »

こんな DSL 書ければいいのに(願望)。

書きたいDSL

http://ufcpp.net/study/csharp/draft/Characteristics.txt

module TypeDefinition.Models
{
    // 特性データ
    type Characteristics
        requres Norm >= 1
    {
        // 特性 X
        X : double
        requires 0 <= X && X <= 1;

        // 特性 Y
        Y : double
        requires 0 <= Y && Y <= 1;

        // 特性 Z
        Z : double
        requires 0 <= Z && Z <= 1;

        // 一次ノルム
        Norm = X + Y + Z;

        // 変更の適用操作
        command Submit excuted on this.Valid;
    }
}

 

ちょっと恣意的な型なのでわかりにくいですが、以下のようなもの:

  • 元データとして X, Y, Z の3つの double を持ってる
  • そこから導出される値として Norm を計算できる
  • X, Y, Z はいずれも 0~1 という制約付き
  • さらに、Norm が1以上という制約も付いてる
  • (ViewModel 上で使う用に)Submit というコマンドを持っていて、こいつはデータがきちんと制約を満たしていないと実行できない

生成したいコード

こいつからこんなソース吐き出したいなぁ(願望)

注意: 適当なので、いまいちな部分も結構あります(Contracts の使い方わかってなかったり、Submit コマンドの扱い方に迷いがあったり)

  • http://ufcpp.net/study/csharp/draft/Characteristics.cs
    • immutable で、かつ、コンストラクター内でデータ検証
    • なので、コンストラクターさえ通ればデータの有効性保証
    • (追記)色々突っ込みを受けて微修正
      • partial 付けた代わりに、プロパティの private set やめて、private readonly なバックフィールドを追加
      • Contract.Assert じゃなくてこの場合 Contract.Ensures だった
  • http://ufcpp.net/study/csharp/draft/CharacteristicsViewModel.cs
    • ViewModel 用(この例は Silverlight)
    • INotifyPropertyChanged.PropertyChanged 地獄
      • Norm = X + Y + Z みたいな記述から、プロパティの依存関係を見て、PropertyChanged の呼び出しを自動的に追加
    • ICommand.CanExecuteChanged 地獄
    • INotifyDataErrorInfo 地獄
    • http://ufcpp.net/study/csharp/draft/DelegateCommand.cs

あとは OR マッパー向けのエンティティクラス作ったりかな。階層的なデータとかコレクションも扱えると完璧だけども、結構めんどくさそう。

この DSL のポイント

  • GUI 用の ViewModel でも、データアクセス用の Entity でも、大体共通して書くのは:
    • プロパティ名、型、データ検証属性
    • あと、DSL 中の注釈もそのまま DisplayName 属性とか ///<summary> コメントに反映されて欲しい
  • 生成したいのは
    • ViewModel 用
      • ユーザーからの入力をいったんなんでも受けた上で、データ検証通らないと Submit コマンド実行できないように
    • その他用
      • GUI が絡む部分以外はいっそ immutalbe にしておく方が人的ミスも減るし、最適化もかけやすいはず
      • one-phase 構築して(コンストラクターで一気に初期化して、以後、個別のプロパティ変更を認めない)、データ検証通らない状態を認めない
  • 元データ以外に、導出される値があるはず
    • ViewModel にする場合には、X の変更を Norm の変更としても PropertyChanged イベント起こさないとダメ
    • 変更の通知はプロパティ間の依存だけじゃなくて、コマンドの実行可否にも影響するので、ICommand.CanExecuteChanged イベントも必要
  • 複数のデータにまたがるデータ検証もある
    • 例えば今回の場合、ViewModel 用なら Submit の CanExcute で検証するし、その他用ならコンストラクターで

DSL 作成支援、もっと欲しい

まあ、パーサー書いてコード生成すりゃできるんでしょうけども、数日前に書いたように、単に頑張ってパース&ソースコード生成できてもいまいちだなぁと思っておりまして:

  • 構文ハイライト欲しい
  • IntelliSense 欲しい
  • 式を書ける部分にはまんま C# の文法使いたい
    • 自分で C# のパーサー書かなくても、自作部分から
      syntax View = Identifier ‘=’ CSharp.Expression;
      みたいに書けば標準で用意されてる構文定義使ってパースできるような。
  • コード生成の方も、文字ベースのテンプレートじゃなくて、構文木ベースでできないものか
    • それも、関数型言語に見られるような Quote 的に、普通に C# っぽい記述書けば構文木になるような(今の式木 ラムダの拡張)

そういうのができる仕組みとか整わないかなぁ・・・

Written by ufcpp

2010年8月12日 @ 15:12

カテゴリー: C#

コメントを残す