2020年9月30日水曜日

クラウド・アプリケーションの特性

前回よりSimpleModel 2020(SM2020)の検討を進めています。

SM2020のターゲットはクラウド上に構築するクラウド・アプリケーションとなります。

そこで、まずクラウド・アプリケーションの以下の特性に対してアプリケーション・アーキテクチャとモデリングの観点から考えます。

  • 並列
  • 分散
  • スケーラビリティ
  • アベイラビリティ
  • リアルタイム
  • UI

アプリケーション・アーキテクチャ

並列

伝統的にプログラムを実行するマシンは1台、プロセッサは1CPU/1コアの時代が長く続いていたわけですが、クラウド・アプリケーションでは複数CPU/複数コアのマシンを複数台使用したシステム構成が普通となっています。

このため、この環境ではプログラムさえ書ければ容易に並列実行が可能です。

しかし、伝統的なプログラムの手法では逐次的に処理を進めるプログラミングが主で、並列処理は難易度の高いプログラミングが必要でした。

しかし、このままではクラウドによって潤沢に使用することが可能となったハードウェアの能力を活かすことができません。

積極的にクラウドの持つ並列処理能力を活かしたいところですが、アプリケーション開発で高度な並列プログラミング技法を使用することは避けたいところです。

つまりクラウド・アプリケーション開発における並列処理に求められるのは、通常のプログラミング・モデルの範囲内で無理をせず並列性能を得られる方式を整備することといえるでしょう。

アプリケーション・アーキテクチャの考慮点

アプリケーションで並列を扱う必要があるケースとして以下のものが挙げられます。

  • 並列に発生する物理事象に対する処理を高レスポンス実行
  • 大規模計算を並列で高スループット実行

CPUリソースをふんだんに使うことで高レスポンスや高スループットを実現します。

「並列に発生する物理事象に対する処理を高レスポンス実行」に対してはメッセージングベースのオブジェクト指向アーキテクチャであるアクターが有力です。

「大規模計算を並列で高スループット実行」に対しては関数のアプローチが有力です。HadoopやSparkのような大規模データ処理基盤では関数のアプローチによって並列処理のベースとしています。

また大規模データ処理基盤を使わない場合でも、関数型プログラミングによって関数を使った実装を行うことで並列処理と親和性の高いプログラムの構造になります。

アクターによる実装はやや難易度が高いので、可能であればプログラミングが容易な手法が望ましいところです。この目的に合致する技術がリアクティブストリームです。リアクティブストリームを使えば、関数型プログラミングよって関数を合成した作成したパイプラインを、バックグラウンドのアクター上で並列分散実行することが可能になります。つまり、このアプローチが使える状況の場合、通常の関数型プログラミングで安全に並列分散処理を記述することができるわけです。

このため、リアクティブストリームが使える応用ではリアクティブストリームを、そうでない場合は直接アクターを使った実装方式が有力です。

分散

本稿では「分散処理」は複数のマシン上で並行動作するエージェントが協調動作して1つの仕事を行うことを指すこととします。

概ね以下の2つのパターンがあります。

  • 複数の物理事象に対する対応をまとめあげて1つの仕事を行う
  • 1つの大きな仕事を複数のエージェントで分担して行う

いずれの場合も、エージェント間の分散合意の技術がキーポイントとなってきます。最重要な分散合意技術がデータベースに対する分散トランザクションです。

現時点では分散トランザクションは一応の標準プロトコルは存在するものの気軽に使える日用品の技術というわけではありません。

また、分散合意アルゴリズムのPaxosも実用化されていますが、こちらも気軽に使えるという感じではないと思います。

分散については、並列と同様にアプリケーション側では分散を直接意識したプログラミングは避け、プラットフォームやフレームワークが提供する機能を使用して、通常のプログラミング・モデルの範囲内で無理をせず分散の効用を得られる方式を整備することが求められます。

アプリケーション・アーキテクチャの考慮点

分散処理を行うためにはマシンをまたいだエージェント間の通信が必要です。この目的でプラットフォームが提供する以下の機能を使うことになります。

  • RPC
  • メッセージング

RPC(Remote Procedure Call)はプログラミング言語内の手続き呼び出しのセマンティクスでリモートサービスの手続きを呼び出す機能です。本稿ではWeb系で使用されるRESTもRPCの一種として扱います。基本的に、通常の手続き呼び出しと同様に使うことができますが、以下の点で注意が必要です。

  • 性能が遅い
  • 通信層、サービス側でのエラーが発生する可能性がある

特にネットワーク分断などのエラーが発生した場合は、分散処理に参加する各エージェントが独自に動作してシステム全体として誤動作するケースもあるので注意が必要です。

メッセージングは分散処理を構成するエージェント間で非同期メッセージを送受信して処理を進める方式です。RPCとは以下の点で異なります。

  • 非同期
  • キューイング
  • 同報(ブロードキャスト、マルチキャスト)が可能

基本が非同期の処理となるため、エラー時のリカバリ処理が複雑になります。

メッセージングの同報機能はサービスバスの土台となります。

サービスバスを使うことで、複数の疎結合のモジュールを組み合わえてアプリケーションを構築することが可能になります。

エージェント間の通信にメッセージングを使う場合、並列の項でも述べたとおりエージェントの実現方式としてアクターが有力です。「複数の物理事象に対する対応をまとめあげて1つの仕事を行う」場合、アクターを使うと???

また並列の後で述べたように「1つの大きな仕事を複数のエージェントで分担して行う」応用では関数がキーとなる技術です。

スケーラビリティ

クラウド・アプリケーションの重要な特性の一つはスケーラビリティ(scalability)です。

本稿ではサービスを同時に使用できるユーザー数が増えた時に、ハードウェアリソースを追加してシステムを拡張していく能力とします。また、スケーラビリティを達成する手段としては、CPUなどのハードウェア増強によるスケールアップとマシン数の追加によるスケールアウトの2種類がありますが、モデリングに影響があるスケールアウトを対象にします。

アプリケーション・アーキテクチャの考慮点

サービスの実行時に、サービスを実行するエージェント間で共有するリソースがなければサービス実行は完全に並列実行でき、マシン数の追加に対する特別な考慮も要りません。

しかし、通常のアプリケーションはデータベースに格納したデータを共用するので、データベースアクセスが最大のボトルネックになります。特に更新処理が発生するは排他制御が大きなボトルネックとなります。

スケーラビリティを高めるためには、サービスを実行するエージェント間でのデータベースの競合を以下に減らすかが論点の一つとなります。

一つのアプローチとしてはアプリケーションロジックを可能な限り関数化することで並列実行を阻害する要因を減らすことです。

また、更新処理に関してはデータベースの競合を避けることは難しいですが、冪等性を活用することでクライアントからの再実行が可能となり、楽観的手法など競合を緩和するアプローチが選択可能になります。

アベイラビリティ

アベイラビリティ(availablity)は、システムを止めずに処理を続行する能力です。マシンが1台の場合、そのマシンが落ちてしまえば処理を続行することができませんが、マシンを二重化しておけば1台のマシンが落ちても、もう一方のマシンで処理を続行することができます。

さらに、スケールアウトなどの目的で複数マシン構成になっている場合には、1台のマシンが落ちても残りのマシン群で処理を継続することができるはずです。

複数のマシンを並列動作するクラウド・アプリケーションの性質上、ハードウェア的には要件を満たしているのでできれば実現しておきたい特性の一つです。

アプリケーション・アーキテクチャの考慮点

アベイラビリティを達成するための有力な方式がクラッシュした場合の処理の再実行です。

クライアントはサービス実行を依頼するマシンが落ちた場合、別のマシンに同じサービス実行を依頼することでサービスを提供するマシンが落ちても処理を継続することができます。

このような仕組みでアベイラビリティを高めることを柔軟性(resillient)のキーワードで表すこともあります。

アプリケーション・アーキテクチャ上は以下のような考慮が必要になります。

  • 処理の再実行機能を組み込んだRPC(Remote Procedure Call)
  • メッセージング
  • 関数型
  • 冪等性

処理の再実行自体はプラットフォーム側で提供する機能を利用することになるでしょう。このため、必要なのは再実行可能なアプリケーションロジックです。この目的には関数と冪等性が有効です。

リアルタイム

リアルタイムというと、制御系システムで所定の時間内で処理が完了する性質を表すことが多いと思いますが、ここでは外部の事象に即時に反応して処理を行う機能を指すことにします。

たとえば、事前に登録した商品の在庫がある店舗近くに来た時に通知で知らせる、といった応用を想定しています。

アプリケーション・アーキテクチャの考慮点

リアルタイムを実現するためには、並列で述べた「並列に発生する物理事象に対する処理を高レスポンス実行」や分散で述べた「複数の物理事象に対する対応をまとめあげて1つの仕事を行う」を実現するメカニズムが必要です。

手続き呼び出しベースではなく、非同期性を内包したメッセージングをベースにしたアプリケーション・アーキテクチャにしていくことが重要です。

このメカニズムとして有力なのがアクターです。

UI

UIはシステムが提供するサービスを利用する接点となる機能です。

本稿でのUIはWebブラウザ上やスマートフォン上のネイティブアプリとして実装するフロント側のUIアプリケーションを指しています。ここでの検討では、UIそのものの機能はスコープ外としUI機能とサーバー側で実行されるサービスとのコミュニケーションを中心にみていきます。

アプリケーション・アーキテクチャの考慮点

UIそのものの実現方式はいろいろな議論があると思いますが、サーバー側のサービスとの通信方式は以下の2つに集約されます。

  • RPC
  • メッセージング

RPCはUIからのサービス呼び出しを同期型で行うもので、従来からあるものです。

一方メッセージングはUIからサービスまたはサービスからUIへの呼び出しを非同期で行うものです。

クラウド・アプリケーション的に考慮が必要なのはサービスからUIへの呼び出しです。この使い方では、分散処理を構成するエージェントの一つにUI機能が入るというような構成になります。

モデリングの検討

アプリケーション・アーキテクチャでの考察で以下の要因を抽出しました。これらの要因に対するモデリングの手法を確立することが重要です。

  • 関数
  • 冪等性
  • RPC
  • メッセージング
  • サービスバス
  • アクター
  • リアクティブストリーム

今後SM2020の開発を進めていくにあたって、現時点でのアイデアをまとめました。

関数

クラウド・アプリケーションは並列・分散ネイティブを指向することになるため、関数がキーテクノロジーとなります。つまりアプリケーションの分析・設計時には手続きと関数を明確に峻別し、関数化できるところを最大化するアプローチを取る必要があります。

SM2020では以下のようなアプローチが有力と考えています。

  • ルールを第一級モデル要素とする
  • データフロー図

SimpleModelではリソース、アクター、イベントなどのエンティティは特別な分類子としてステレオタイプで記述可能になっています。従前からルールもこの特別な分類子として用意していましたが、関数の集まりという観点で並列や分散に親和性の高いモデルとして積極的に活用していく予定です。

また、関数の計算過程をデータストアとの関係で記述したデータフロー図も有力です。

冪等性

スケーラビリティやアベイラビリティを最大化するためには、サービスが提供する手続きの冪等性が重要な要因になります。

サービス設計時に冪等性を意識的に取り扱っていく必要があります。

SM2020では以下のようなアプローチが有力と考えています。

  • サービスの手続きの特性として冪等性を記述可能にする
RPC

モデリング的にはRPCは通常の手続き呼び出しと同等に考えることができます。ただし、性能問題とエラーのリカバリの2つの問題は考慮に入れる必要があります。

SM2020では以下のようなアプローチが有力と考えています。

  • サービスの提供する関数や手続きの特性として
メッセージング

メッセージングは従来のUMLではシーケンス図を用いて記述する方法はありますが、コンポーネント図などでの記述方法などは今ひとつ明確化されていないと思います。

SM2020では以下のようなアプローチが有力と考えています。

  • サービスの分析・設計にメッセージング記述用の記法を追加
  • メッセージングの流れを記述するメッセージ図を整備

個人的にはUMLのシーケンス図やコラボレーション図でもメッセージングの記述に曖昧な点が残ると考えています。この問題に対応するためにメッセージ図を開発しました。

SM2020ではこのメッセージ図を整備していく予定です。

サービスバス

サービスバスを使うことで、非同期事象やイベント駆動をうまく扱えるようになります。

SM2020では以下のようなアプローチが有力と考えています。

  • イベントの整備
  • アクター

サービスバスの機能をアプリケーションで活用する場合には、イベントという抽象化を用いるのが有力です。

SM2020ではエンティティとしてイベント・エンティティを用意しているので、これとサービスバスの連携を行うような方向性を考えています。

またサービスバスからの受信するメッセージの処理にはアクターが有力だと思うので、アクターでの記述方式を検討予定です。

アクター

メッセージングやサービスバスで受信したメッセージの処理の実装にはアクターが有力です。

SM2020では以下のようなアプローチが有力と考えています。

  • アクター記述用の記法を追加
  • メッセージ図でアクターの振る舞いを記述可能にする
リアクティブストリーム

前述したように並列分散の処理を実装する場合、リアクティブストリームが使える応用ではリアクティブストリームを、そうでない場合は直接アクターを使った実装方式が有力です。

このためSM2020でもリアクティブストリーム向けのモデリングの枠組みを検討予定です。

SM2020では以下のようなアプローチが有力と考えています。

  • データフロー図
  • メッセージ図

データストアとの関係を重視したい場合はデータフロー図、パイプライン処理の側面を重視したい場合はメッセージ図という使い分けを想定しています。

まとめ

SM2020のモデル検討の前提情報としてクラウド・アプリケーションの性質から、必要と思われるモデル要素の抽出を行いました。

アイデアレベルですが、簡単な検討を行いました。

クラウド以前は並列分散処理は特殊な分野でしたが、クラウド時代に入ってコモディティ化しており、従来型のComand-Controlモデル向けのモデリング手法では対応しきれなくなっています。

とはいえ並列分散向けのモデリングの拡張を安易に入れてしまうと、モデリングの難易度が高くなってしまい実用性に問題が出てしまいます。

通常のアプリケーション開発で使用できる範囲内の難易度で、並列分散についても実用的に取り扱えるモデリング体系のバランスを取っていく必要がありそうです。

2020年8月31日月曜日

SimpleModel

簡単なWebサイトの開発などはDBスキーマ設計+プログラミングで十分なケースも多いと思いますが、複雑な業務や高度なユーザー経験を実現する場合は、何らかの分析設計を行い、その結果を元に実装に落とし込む必要があります。この分析設計手法の最右翼がOOAD(Object-Oriented Analysis and Design)です。

しかし、OOADは難しい技術で独学でマスターするのはなかなか大変です。

独学でマスターすることが大変な理由として、そもそもOOADがソフトウェア工学の集大成という位置付けのものなのでカバーする技術分野の範囲も広く難易度が高いということがあります。その上で独学に適したよい教科書がないということもあります。また、モデリングをアシストするためのツール類の不足も大きな問題です。

以前、大学でモデリングを教えていた時、授業やゼミで使えそうな教科書がないことが悩みのタネでした。

一つは具体的なモデリングの手順を解説した本。UMLの文法解説の本は多いのですが、最上流から実装までの流れを順を追って解説している本がなかなかありません。

また、UMLはすべての応用に適用できるように仕様が巨大でチューニング項目も沢山ありますが、ターゲットのシステム開発向けに必要最小限の大きさにカスタマイズして使用することが想定されています。この「ターゲットのシステム開発向けに必要最小限の大きさにカスタマイズ」してあるUMLのカスタマイズ仕様、いわゆるプロファイルが定義されている本はほぼないと思います。つまり、UMLの記法を学んだだけではUMLを活用することはできないわけです。

そこで中小規模の業務アプリケーションをターゲットに整備したメタモデルとしてSimpleModelを設計しました。

SimpleModelをベースにこれらの問題を解決するために授業やゼミで使える教科書の目的で以下の2つの本を書きました。

UMLを記述言語として書いたものが『上流工程UMLモデリング』、マインドマップを記述言語としたものが『マインドマップではじめるモデリング講座』です。

『上流工程UMLモデリング』が教科書、『マインドマップではじめるモデリング講座』がゼミでのワークショップ用という位置付けです。

ソフトウェア構築技術の進化

SM2008を作成したのが2008年前後ですが、すでに12年の月日が流れており、ソフトウェアの構築技術にも大幅な変化がありました。

特に以下の3つの分野での大きな進展があります。

  • クラウド
  • AI
  • DX(Digital Transformation)
クラウド

クラウドの登場によって大きく変わったのは、大規模アクセス・大規模データのアプリケーションを簡単に構築できるようになった点だと考えています。大規模アクセス・大規模データのアプリケーション構築するための部品が多数用意され、運用管理コストを含めたコストが安価に提供されるようになりました。

逆に言うと大規模アクセス・大規模データの業務アプリケーションを開発する必然性が生まれたわけで、スケールアウトや非同期処理・分散処理を達成するための技術力が求められるようになりました。

それに伴い、以下のようなアーキテクチャが登場してきました。

  • CQRS
  • Event Sourcing
  • Microservice

これらのアーキテクチャに対して、業務アプリケーションのモデリング上でどのように対峙していくのかが論点になるでしょう。

AI

業務アプリケーションの開発においてもAIは無視できない存在になってきました。

ただ、業務アプリケーションそのものがAIのエンジンを開発するということはなく、既存のAIエンジンを使用し、数理モデルを新規開発または既存モデルの改良という形で利用していくことになるケースがほとんどだと思います。

AIも大きく従来型の知識ベースや推論エンジンによるAIと、最近流行の機械学習型の2種類があります。

前者については、AIシステムをコンポーネントやサブシステムとしてモデル化し、利用方法を考えていく形になるでしょう。後者については利用方法を設計するのに加え、学習に必要な情報の収集方式についても検討する必要がでてきます。

DX

DXはもともと「ITの浸透が、人々の生活をあらゆる面でより良い方向に変化させる」という意味とのことですが、ソフトウェア開発の文脈では、企業活動のあらゆる側面をIT化して、企業の形態をIT中心に変換する、というようなニュアンスで語られることが多いと思います。

DXの文脈では、単なる業務アプリケーションの開発ではなく、企業活動全体を俯瞰した企業システムの構築の一環として業務アプリケーションを開発することになります。業務アプリケーションの設計ではなく、企業システム全体をモデル化した上で、その中に組み込まれる1コンポーネントという形での設計になってくるでしょう。

こうなってくると、プログラミング主導の開発では不十分で、全体像を俯瞰し、ターゲットの開発スコープを明確にするモデルの作成が必要なのは明らかです。

SimpleModel 2020

このように、SimpleModelを開発した2008年当時から見るとシステム開発を取り巻く要素技術は大幅に進化しています。この技術進化を取り込むためにSimpleModelの拡張を行うことにしました。その内容については本ブログでこれから検討していくことにします。

前述の書籍で使用しているSimpleModelをSimpleModel 2008年版と呼ぶことにします。そして、このブログでこれから検討していく新しい時代背景に対応したSimpleModelをSimpleModel 2020年版と呼ぶことにします。また簡易表記はSimpleModel 2008年版をSM2008、SimpleModel 2020年版をSM2020とします。

記述言語

前回説明したとおり、モデルコンパイラであるSimpleModelerの記述言語はSmartDoxのDSL基盤上に構築されています。すなわち、節による木構造、表による表構造を使用してのモデル定義と、自然言語による説明文を自然な形で混在させることができます。

文芸的プログラミング(Literature Programming)ならぬ文芸的モデリングということができます。

ツール

OOADによるモデリングを実務に適用するために重要なことは使いやすくて実効性のあるツールによるアシストです。

従来からUMLエディアなどのツールは存在しましたが、実務にモデリングを適用させたり、モデリング教育を効果的に行うといった目的には十分な機能を提供しきれていなかったともいます。

モデリングで作成するモデルは大きく以下の2つに分けることができます。

  • 実行可能モデル
  • 青写真モデル

実行可能モデルは、作成したモデルがプログラムとしてそのまま動いたり、プログラムを自動生成できる、といった形でプログラム開発に直接連携できるモデルです。

一方、青写真モデルはあくまで参考として使える情報であり、実際のプログラムには手作業で開発することになります。

従来モデリングが活用されてこなかった理由の一つは、せっかく苦労してモデルを作っても青写真モデル止まりだったことが大きいと思います。

モデリング活用の阻害要因であるこれらの問題に対応するため、2008年以降、Scalaを使って以下のプロダクトを整備してきました。

SmartDox
文書処理系
SimpleModeler
モデルコンパイラ
Kaleidox
アクション言語
Arcadia
Webフレームワーク
PreferCloudPlatform
クラウド・アプリケーション・プラットフォーム

これらのツールは現在SM2008向けになっていますが、SM2020のメタモデルをベースに拡張していく予定です。

まとめ

業務アプリケーション向けメタモデルであるSimpleModelの最新版SimpleModel 2020について紹介しました。

SM2020の具体的な内容については本ブログで順次検討していきたいと思います。

次回はSM2020を検討する上での論点を整理したいと思います。

2020年7月31日金曜日

SimpleModeler

前前回の記事ではModegrammingをキーワードにしたモデル駆動開発向けに開発している5つのプロダクトについて説明しました。

SmartDox
文書処理系
SimpleModeler
モデルコンパイラ
Kaleidox
アクション言語
Arcadia
Webフレームワーク
Prefer Cloud Platform
クラウド・アプリケーション・プラットフォーム

今回はSimpleModelerについて紹介します。

SimpleModeler

SimpleModelerはモデルからプログラムなどの成果物を生成するモデルコンパイラです。

SimpleModelerはSimpleModel形式で記述されたモデルを入力し、JavaやScalaのプログラムを始め各種生成物を生成します。

モデル

SimpleModelerはSmartDox形式の文書として記述したSimpleModelを入力とします。SmartDox形式はざっくりEmacs org形式とMarkdown形式を折衷した形式です。

SimpleModelは、現在、静的構造モデル(UMLではクラス図、パッケージ図など)とユースケースモデルを記述することができます。この中でユースケースモデルと静的構造モデルはモデル検証用に、静的構造モデルはプログラムの生成に使用します。

静的構造モデルでは以下のような種類のオブジェクトをステレオタイプとして定義しています。

Resource
リソース
Event
イベント
Actor
アクター
Role
ロール
Voucher
バウチャー
Powertype
パワータイプ

これらのオブジェクトを適材適所で使用してモデルを記述することで、モデルの精度や情報量も高まり、より適切なプログラムの生成につなげることができます。

今回はシンプルにResourceのみを定義したモデルを使います。

#+title: サンプル

* Resource

サンプルモデルのリソースです。
PersonとAddressを定義しています。

** Person

#+caption: 特性一覧
| 特性 | 名前    | 型      | 多重度 | ラベル | カラム | データ型 | 備考 |
|------+---------+---------+--------+--------+--------+----------+------|
| 属性 | name    | token   |      1 |        |        |          |      |
| 関連 | address | Address |      1 |        |        |          |      |

利用者です。

住所を記述するAddressへの関連を持っています。

** Address

#+caption: 特性一覧
| 特性 | 名前 | 型    | 多重度 | ラベル | カラム | データ型 | 備考 |
|------+------+-------+--------+--------+--------+----------+------|
| 属性 | zip  | token | ?      |        |        |          |      |

住所です。

ここではEmacsでの編集が楽なorg形式の文法を使用して記述しています。

このモデルではリソースPersonとAddressを定義しています。

まず「* Resource」で以下のクラス定義がリソースであることを示しています。

つぎに段落を一つ下げた「* Person」、「* Address」でそれぞれPersonとAddressを定義してます。Personは利用者、Addressは住所を記述するためのリソースです。

オブジェクトの属性や関連は「特性一覧」の表で定義しています。

段落と表以外はモデルとして認識しないので、モデルの説明などの文章を自由に書くことができます。

このモデルをsample.orgというファイルに格納します。

生成

前出のサンプルから各種成果物を生成することができます。

Java

SimpleModelを格納したsample.orgを引数にsmコマンドを起動します。

第1引数にjavaを指定するとJavaプログラムを生成します。

$ sm java sample.org

以下のようなJavaプログラムが生成されます。

import java.math.*;
import java.util.*;
import org.json.*;
import org.simplemodeling.SimpleModeler.runtime.USimpleModeler;

public class Person {
    public static final String PROPERTY_NAME = "name";
    protected String name;
    protected Adress address;

    public Person() {
    }

    public Person(Person o) {
        this.name = o.name;
        this.address = o.address;
    }

    public Person(String name, Adress address) {
        this.name = name;
        this.address = address;
    }

    public Person(PersonVoucher o) {
        this.name = o.name;
        this.address = o.address;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Adress getAddress() {
        return address;
    }

    public void setAddress(Adress address) {
        this.address = address;
    }

    public Person withName(String name) {
        this.name = name;
        return this;
    }

    public Person withAddress(Adress address) {
        this.address = address;
        return this;
    }
}
Scala

smコマンドの第1引数にscalaを指定するとScalaプログラムを生成します。

$ sm scala sample.org

以下のようなScalaプログラムが生成されます。

class Person(var name: String) {
    private String name;

    def public String getName() =  {
        return name;
    }

    def public void setName(String name) =  {
        this.name = name;
    }

    def public Person withName(String name) =  {
        this.name = name;
        return this;
    }
}
UML

smコマンドの第1引数にumlを指定するとUMLのクラス図を生成します。

$ sm uml sample.org

生成したクラス図は以下になります。


まとめ

今回はSimpleModelerについて説明しました。

次回は、SimpleModelerの扱うオブジェクトメタモデルSimpleModelについて説明します。

2020年6月30日火曜日

SmartDox

前回の記事ではModegrammingをキーワードにしたモデル駆動開発向けに開発している5つのプロダクトについて説明しました。

SmartDox
文書処理系
SimpleModeler
モデルコンパイラ
Kaleidox
アクション言語
Arcadia
Webフレームワーク
Prefer Cloud Platform
クラウド・アプリケーション・プラットフォーム

今回は、この中のSmartDoxについて紹介します。

SmartDoc

2000年ごろに文書処理系のOSSであるSmartDocを開発していました。

SmartDocはXML形式のSmartDoc文書で記述したソースから、HTML、PDF(Tex経由)、プレインテキストを生成します。

SmartDocは個人用文書作成ツールとして便利に使っていたのですが、モデル駆動開発のDSLの基盤としても活用できないか、検討を重ねてきました。というのは、文芸的プログラミング(literate programming)をモデル駆動に適用した文芸的モデリング(literate modeling)の実現しようと考えたからです。

文言的モデリングを実現するためには、モデルの内容を説明した文章とモデル定義を同一のプレインテキスト内に自然な形で同居させる必要があります。

モデル記述言語

Modegrammingにおけるモデル駆動開発を行うためのモデル記述言語を考えた場合、前述した文芸的モデリングが重要な要素になります。

一方オブジェクト指向モデリング言語のデファクトであるUMLは、以下のような理由でモデル駆動開発で本格活用するのは難しいのではないか、と個人的に考えています。

  • UMLはグラフィカル言語であるためモデルの入力が煩雑
  • グラフィカル言語は大規模モデルの編集が難しい

また、UMLの編集に専用ツールが必要、というのも運用上の問題点です。

格納形式も独自形式になるので、UMLモデルを作成したツールでしか編集することができません。商用製品の場合、製品にロックインされることになるため、経費がかかることに加えて、将来製品が販売停止になった時にはモデルの再利用や保守などにも問題がでてきそうです。

格納形式が独自形式になることで、テキストベースのバージョン管理システムで管理することが難しくなるという問題もあります。

このようにグラフィカル言語のUMLを、本格的な開発に適用することは色々と問題がありますが、その一方でUMLで定義しているオブジェクト・モデルのメタ・モデルは業界標準としてのコンセンサスがとれているものなので活用したいところです。

以上のことを考えると、モデル駆動開発向けのモデリング言語として以下の要件に行き着きました。

  • プレインテキストでモデル定義とモデルの説明文を文芸的モデリング的に同居できる
  • UMLのメタ・モデルをベースにしている

これを実現するためのメタメタモデルとしてSmartDocが活用できないかと考えたわけです。

SmartDox

SmartDoxはOSSで開発しているSmartDoc後継の文書処理系です。

モデル駆動開発のためのモデリング言語のDSLを構築するためのメタメタモデルを提供しています。

同時に、本来の機能である文書処理系にもSmartDocと同様の機能セットを提供することを目標にしています。本ブログもSmartDoxで書いたものをBlogger形式に変換しています。

SmartDoxはEmacs org形式をベースにMarkdownとHTML、XMLの文法をマージした文法を定義しました。

SmartDocはXMLベースでしたが、SmartDoxはプレインテキストベースの文書形式になっています。近年はMarkdownによるプレインテキストがソフトウェア開発での文章作成のデファクトになっているのでMarkdownを取り入れています。また、ボクが通常Emacs上でEmacs orgモードで文章作成しているのでEmacs org形式もサポートしています。ざっくりいうとEmacs org形式とMarkdown双方の緩い上位互換をとりつつ、拡張文法としてHTMLやXMLによる詳細指定を可能にした文法になっています。

このSmartDox文法によって、以下の3種類の文書を構築する構成要素が得られます。

  • セクションの入れ子による木構造
  • テーブルによる表構造
  • マークアップ付き自然言語

この中で「セクションの入れ子による木構造」と「テーブルによる表構造」をモデル駆動開発におけるモデル記述のメタメタモデルとして使用するのがSmartDoxによるモデル記述の基本アイデアになっています。

また「マークアップ付き自然言語」によってモデルに対する説明文をモデル記述内に自然に配置することができます。

SmartDoxベースのDSL

SmartDoxによるDSL基盤を使ってSimpleModelerとKaleidoxを実装しています。

SimpleModeler

SimpleModelerはモデル駆動開発に用いるモデルコンパイラです。

元々ScalaのDSL機能を用いてモデル定義をする方式を主にしていましたが、現在開発中の新バージョンよりSmartDoxベースのモデル記述方法に一本化しました。

SimpleModelerのモデル定義の例を以下に示します。

#+title: サンプル

SimpleModelerのサンプルです。
以下のようにコンパイルします。

```
$ sm java sample.org
```

* Resource

** Person

#+caption: 特性一覧
| 特性 | 名前    | 型      | 多重度 | ラベル | カラム | データ型 | 備考 |
|------+---------+---------+--------+--------+--------+----------+------|
| 属性 | name    | token   |      1 |        |        |          |      |
| 関連 | address | Address |      1 |        |        |          |      |

** Address

#+caption: 特性一覧
| 特性 | 名前 | 型    | 多重度 | ラベル | カラム | データ型 | 備考 |
|------+------+-------+--------+--------+--------+----------+------|
| 属性 | zip  | token | ?      |        |        |          |      |

リソース・エンティティの2つクラスPersonとAddressを定義しています。

SmartDoxのセクションの階層構造を利用してクラス種別のResourceとその配下にクラスPersonとAddressを定義しています。

Kaleidox

次の例はモデル駆動開発向けのアクション言語Kaleidoxです。

Kaleidoxでは、スクリプトを用途ごとに文法の違う複数のセクションで構成する構造になっています。

Kaleidoxのスクリプトの例を以下に示します。

* description

Kaleidoxでモデルを使用する例です。

* env

db.default.driver="org.h2.Driver"
db.default.url="jdbc:h2:mem:"

* voucher

** user

#+caption: 特性一覧
| 特性 | 名前 | 型     | 多重度 | ラベル  |
|------+------+--------+--------+---------|
| 属性 | id   | int    |      1 | User ID |
| 属性 | name | string |      1 | 名前    |
| 属性 | age  | int    |      ? | 年齢    |

* main
(store-query 'user nil)

スクリプト全体はSmartDoxの文法によって記述されており、プログラムを記述するmainセクションにKaleidoxのスクリプトが書かれています。

以下の例はdescription, env, voucher, mainの4つのセクションで構成されたKaleidoxスクリプトです。

descriptionセクションはスクリプトの説明を書くセクションです。SmartDox形式のプレインテキストを記述します。

envセクションはスクリプト実行時の環境変数をHOCON(typesafe config)形式で定義します。

voucherセクションはVoucherステレオタイプを持ったクラスを定義するセクションです。SimpleModeler形式の表形式でモデルを記述します。

mainセクションはスクリプト本体をKaleidoxスクリプト形式(S式)で記述します。

以上から分かる通り、各セクションの構造はSmartDoxのセクションを利用し、自然言語による記述を行うセクションではSmartDox形式を用いています。

まとめ

今回はオブジェクトモデル記述のためのDSL基盤の側面からSmartDoxについて紹介しました。

次回はSimpleModelerの紹介をする予定です。

2020年5月31日日曜日

モデル駆動によるクラウド・アプリケーション開発

「クラウド」というとすでにややレトロな響きも出てきたかもしれません。しかし、Kubernetes/Dockerといった足回りやAWS Lambdaのような要素技術は登場していますが、クラウド・アプリケーション全体を構築するための開発手法の整備にはまだ手がついていない状況だと思います。

当ブログではModegrammingをキーワードに、モデリングとプログラミングを融合したモデル駆動開発を提唱しており、このModegrammingのクラウド・アプリケーションへの適用を中心的なテーマとしています。

Modegrammingを成立させるためには、開発手法を下支えする開発ツールや実行プラットフォームの存在が不可欠です。この目的で現在、以下の5つのプロダクトを開発しています。

SmartDox
文書処理系
SimpleModeler
モデルコンパイラ
Kaleidox
アクション言語
Arcadia
Webフレームワーク
Prefer Cloud Platform
クラウド・アプリケーション・プラットフォーム

2008年からScalaを使って少しずつ開発を進めてきましたが、かなり整備が進んできたので現在の状況についてまとめてみました。

SmartDox

SmartDoxはSmartDocの後継となる文書処理系です。OSSとして開発しています。

SmartDocは文書形式としてXMLを採用していましたが、SmartDoxではMarkdownとEmacs orgを融合させた独自のプレインテキストを文書形式として使用します。

本ブログもSmartDox形式で記述したものを、SmartDoxでBlogger形式を生成したものをBloggerに貼り付けています。

文書処理系とモデル駆動開発との関係は一見なさそうにもみえますが、Modegrammingの中でSmartDoxを重視しているのは、Literate Programming、Literate Modeling、ひいてはLiterate Modegrammingの基盤となる文書処理基盤を提供するためです。具体的には、後述するSimpleModelerとKaleidoxがSmartDox基盤を使用してLiterate Modeling, Literate Programmingを実現しています。

SmartDoxは当面はSimpleModeler、Kaleidox、Arcadiaの中でLiterate Modegramming(Literate Modeling + Literate Programming)を実現するための要素技術として使用していく予定です。

将来的にはSmartDocと同様に、独立した文書処理系として公開するかもしれません。

SimpleModeler

SimpleModelerはRelaxerの後継となるモデルコンパイラです。OSSとして開発しています。

RelaxerはXMLスキーマ言語(RELAX)からJavaなどのプログラムを生成するスキーマコンパイラです。

RelaxerはXMLを扱うアプリケーション開発に非常に有益だったと思いますが、スコープがXMLに閉じているため応用範囲が限られました。ただ、プログラムの自動生成の可能性については十分認識することができました。

次の段階としてオブジェクトモデルからのプログラムの自動生成を行うために開発を始めたのがSimpleModelerです。SimpleModelerはオブジェクトモデルからJavaやScalaなどのプログラムを生成するモデルコンパイラです。

2008年から開発を始め、一応の実用化レベルの機能は提供できています。後述のPCP開発にも使用しています。

Scalaの内部DSLを主となるDSLとして採用したのですが、オブジェクト・モデルの記述にはあまり適さないことが分かってきたのでSmartDoxをベースとした外部DSLを主DSLとするように切り替える開発を進めていました。

同時に、オブジェクト・モデルのメタモデルの拡張をクラウド・アプリケーション向けに拡張する作業を進めています。

Kaleidox

モデル駆動開発をターゲットにしたアクション言語です。OSSとして開発しています。

モデル駆動開発のアキレス腱となっているのが、振る舞いの記述です。オブジェクト・モデルでは、静的構造は自動生成可能な精度のモデル記述が可能ですが、動的振る舞いについては状態機械モデルまでが自動生成可能な精度のモデル記述が可能なものの、それ以上の振る舞いについてはスコープ外になっています。

このため、モデル・コンパイラでプログラムの自動生成をする場合でもプログラミングとの併用が必須となり、ちらにしてもプログラミングが必要となるのであればプログラミングを主軸にし、モデリングは概念レイヤーのメモ書きレベルの使用に限るようなバランスが妥当ともいえます。

この「振る舞い」に関する問題がモデル駆動開発のアキレス腱となっていました。

この問題は、モデル駆動開発用のアクション言語によって解決できるのではないか、というアイデアのもと開発したのがKaleidoxです。

Kaleidoxについては本ブログで紹介してきました。スクリプト言語としては実用ゾーンに入って来たと思いますが、引き続き本命のアクション言語として活用できるように、SimpleModelerとの繋ぎ込みを進めていく予定です。

Arcadia

Arcadiaはモデル駆動開発をターゲットにしたWebフレームワークです。OSSとして開発しています。

モデルコンパイラでプログラムの自動生成を行う際に問題となるのが、自動生成したプログラムの実行基盤です。

この問題に対応するために、ArcadiaはWeb UIを構築するWebアプリケーションの自動生成を用意にするための以下のような仕組みを導入しています。

  • プログラムではなくメタデータ設定でWebアプリケーション開発を可能にする。
  • バックエンドのクラウド・プラットフォームとシームレスに連携できるようにする。
  • シナリオによるWeb入力機構を搭載している。
  • アクション言語(kaleidox)を使って処理の記述が可能になっている。

バックエンドのクラウド・プラットフォームとして後述するPrefer Cloud Platformも使用できますが、アダプタを作れば任意のクラウド・プラットフォームを使用することが可能です。

アクション言語であるkaleidoxとの統合は、モデル駆動開発との連携を指向したものです。

Arcadiaは基本部は開発済みです。KaleidoxとSimpleModelerが一段落した後に公開したいと考えています。

Prefer Cloud Platform

Prefer Cloud Platform(以下PCP)はボクがCTOをやっているEverforth社が提供する商用のクラウド・アプリケーション・プラットフォームです。

PCPを用いることでクラウド・アプリケーションを高速、低コストで開発することができます。

PCPは、モデル駆動開発の実行環境としても使用できるように設計されており、現時点でもSimpleModelerによる自動生成を活用して開発を行っています。

しかし、現時点ではPCP上で動作するクラウド・アプリケーションを自動生成するところまでは到達できていません。SimpleModeler、Kaleidox、Arcaidaが整備されることで、オブジェクト・モデルからのクラウド・アプリケーションの自動生成が可能になることを目指しています。

関連書籍

モデル駆動開発を行うためにはオブジェクト・モデルのメタモデルの整備も必要です。

この整備はwakhok時代から進めており、2008年当時の成果を以下の書籍にまとめています。いずれもwakhok時代に教科書として使うことを目的に書いたものです。

しかし、2008年当時とはクラウド環境をめぐる状況が大きく変わっており、それらの要素を取り込んだメタモデルの拡張が必要です。

上記の書籍の内容をベースに、SimpleModelerの開発を進めながらメタモデルの拡張も同時に行っています。

その成果もいずれ文書としてまとめていきたいと思います。

まとめ

本ブログが提唱しているModegrammingを支える開発ツール、実行プラットフォームの開発の近況について説明しました。

2008年から少しずつ進めてきた開発ですが、すでに商用化されているPCPに加えて、いくつかのOSSも実用ゾーンに入りつつあります。

OSSが実用ゾーンに入ってきたことで、クラウド・アプリケーション向けのオブジェクト・モデルのメタモデルを、実用化を前提として具体的に検討をすすめることが可能になってきました。メタモデルの拡張はSimpleModelerの開発と並行して行っています。

まだまだ開発途上ですが、本ブログで継続して開発の成果を報告していく予定です。

2020年4月30日木曜日

Kaleidox/スタック

アクション言語は複雑なアルゴリズムを記述するというより、入力データと状態の組み合わせに対してデータ変換を行い変換後のデータを後続のシグナルに乗せて発信するという処理が中心となります。

このような処理の記述にはパイプラインのセマンティクスが適しています。

パイプラインを記述するためのプログラミング後の構文としてはUNIXシェルの以下の形式が有力です。

cat file.txt | grep foo | sort

この記述方式は直感的で強力ですが、一般的なプログラミング言語の文法とセマンティクスが異なるため、汎用言語の一要素として併存させることは苦労が伴います。パイプラインで記述できない処理が出てきた時に、パイプライン以外の方式で記述した上で、それをパイプラインにどのように簡潔な形で統合していくのかという点が問題です。煩雑な記述方式で統合すると、"直感的で強力"な文法が失われてしまいます。

この問題への対応としてKaleidoxではスタックのメカニズムを用意しています。スタックを用いることで、パイプラインのセマンティクスに近い形で通常のプログラミング言語との"直感的で強力"な統合を目指しています。

スタック

式の評価結果はスタックにプッシュされます。

たとえばREPLから1、2、3と順に入力するとそれぞれの式の評価結果である数値がスタックにプッシュされていきます。

kaleidox> 1
1
kaleidox> 2
2
kaleidox> 3
3

スタックの様子はstackコマンドで表示することができます。先程入力した数値がスタック上に逆順で積まれていることが確認できました。

kaleidox> #stack
 1: 3
 2: 2
 3: 1
...略...

関数は必須引数数が定義されており、引数の数がこれに満たない場合は不足分をスタックから持ってくるようになっています。

前述のスタックの状態の元で関数+を引数なしで投入してみます。+関数の必須引数の数は2なので、スタックから2つの値をポップし、これを引数として利用します。

kaleidox> +
6

+関数実行後のスタックは以下になります。

kaleidox> #stack
 1: 1
...略...

より実用的な例としてCSVデータをチャートで表示する処理を考えてみます。

以下のCSVデータをcity.csvとして用意します。

都市,緯度,経度,平均気温,降水量
札幌,43.055248,141.345505,8.0,1158
仙台,38.254162,140.891403,11.9,1219
東京,35.680909,139.767372,15.3,1460
名古屋,35.154919,136.920593,14.9,1575
大阪,34.702509,135.496505,16.2,1400
広島,34.377560,132.444794,15.0,1603
福岡,33.579788,130.402405,16.0,1690
那覇,26.204830,127.692398,22.4,2128

table-load関数でCSVデータをtableオブジェクトとして読み込みます。

kaleidox> table-load file:city.csv
Table[5x8]
kaleidox> :show:print
┏━━━━━━┯━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━┯━━━━━━┓
┃都市  │緯度     │経度      │平均気温│降水量┃
┣━━━━━━┿━━━━━━━━━┿━━━━━━━━━━┿━━━━━━━━┿━━━━━━┫
┃札幌  │43.055248│141.345505│8.0     │1158  ┃
┃仙台  │38.254162│140.891403│11.9    │1219  ┃
┃東京  │35.680909│139.767372│15.3    │1460  ┃
┃名古屋│35.154919│136.920593│14.9    │1575  ┃
┃大阪  │34.702509│135.496505│16.2    │1400  ┃
┃広島  │34.377560│132.444794│15.0    │1603  ┃
┃福岡  │33.579788│130.402405│16.0    │1690  ┃
┃那覇  │26.204830│127.692398│22.4    │2128  ┃
┗━━━━━━┷━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━┷━━━━━━┛

続けて、table-select関数を使って読み込んだ表の必要部分だけ切り取ります。ここでは第0、1、3カラムを残し、都市、緯度、平均気温の表にしています。

kaleidox> table-select 0,1,3
Table[3x8]
kaleidox> :show:print
Table[3x8]
┏━━━━━━┯━━━━━━━━━┯━━━━━━━━┓
┃都市  │緯度     │平均気温┃
┣━━━━━━┿━━━━━━━━━┿━━━━━━━━┫
┃札幌  │43.055248│8.0     ┃
┃仙台  │38.254162│11.9    ┃
┃東京  │35.680909│15.3    ┃
┃名古屋│35.154919│14.9    ┃
┃大阪  │34.702509│16.2    ┃
┃広島  │34.377560│15.0    ┃
┃福岡  │33.579788│16.0    ┃
┃那覇  │26.204830│22.4    ┃
┗━━━━━━┷━━━━━━━━━┷━━━━━━━━┛

table-select関数は第1引数に選択するカラムを示す範囲を第2引数に対象のtableオブジェクトを取ります。第1引数のみ指定されてるので、第2引数はスタックよりtable-load関数の評価結果であるcity.csvを読み込んだtableオブジェクトが指定されます。

続けてtable-chart関数を使ってチャートの表示を行います。

kaleidox> table-chart :analyzes 'simple-regression

table-chart関数ではキーワードanalyzesにsimple-regressionを指定しているので、散布図の上に単回帰分析の結果が表示されます。キーワードの後ろに指定する引数ではtableオブジェクトを取ります。ここが省略されているので、スタックよりtable-select関数の評価結果であるカラム射影後のtableオブジェクトが指定されます。

この結果、以下のチャートが表示されます。

関数

ここまでREPLで試してきた処理では以下の3つの関数を順に実行しています。

  • table-load
  • table-select
  • table-chart

これは前出のUNIXシェルのパイプラインの記述方式を使うと以下のようなイメージです。

table-load file:csv | table-select 0,1,3 | table-chart :analyzes 'simple-regression

この処理を通常のLisp文法で関数化したものが以下のshowchart関数です。

(defun showchart (uri)
  (setq a (table-load uri))
  (setq b (table-select 0,1,3) a)
  (table-chart :analyzes 'simple-regression b))

前段の処理結果を後段に受け渡していくパイプライン的な処理ですが、この例でも分かるように手続き型的な記述方式では変数を使ってデータを受け渡していく形になります。

この記述方式でも実用的には問題ありませんが、UNIXシェルの記述方式に比べると煩雑であることは否めません。

KaleidoxではUNIXシェルのような記述はできませんが、関数呼び出しをシーケンシャルに並べてパイプライン的な処理を簡潔に記述することができます。

この記述を用いて関数化したものが以下のshowchart関数です。

(defun showchart (uri)
  (table-load uri)
  (table-select 0,1,3)
  (table-chart :analyzes 'simple-regression))

table-load, table-select, table-chartのそれぞれの評価結果をスタックを用いて後続の関数に受け渡しています。

スタックを用いてこのような記述方式を可能にすることで、パイプライン的な処理を簡潔に記述することが可能になっています。

まとめ

アクション言語は、汎用言語としての記述力も重要ですが、処理の中心はデータ変換のパイプライン処理になるので、パイプライン処理を簡潔に記述する記述能力も重要になります。

Kaleidoxではスタックを用いてパイプライン処理を簡潔に記述することを可能にしているわけです。

関数型言語ではFunctor(Scalaではmap関数)やMonad(ScalaではflatMap関数)を用いてパイプライン処理を記述することが可能になっています。この関数型言語方式もパイプラインの記述方式としては有力、というか汎用言語としては本命と思いますが、アクション言語にはやや重いのではないかというのがボクの見立てで、スタックによる記述方式を開発しました。

関数型言語方式とスタック方式の比較検討はいずれ行いたいと思います。

諸元

  • Kaleidox : 0.1.11

2020年3月31日火曜日

Kaleidox: モデル駆動開発

Kaleidoxはモデル駆動開発のアクション言語を指向しています。実用言語の観点から、データ操作の枠組みとしてRecordとTableを中心とした機能群を用意しています。

一方、モデル駆動開発に適用するためにはモデル側との連携も必要になります。

今回はモデル駆動開発のためのモデル定義とアクション言語の連携について、現時点で実装している簡単な機能を例に探っていきます。

初期設定

以下のinit.kldを用意します。

* env

db.default.driver="org.h2.Driver"
db.default.url="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1"

* voucher

** City

#+caption: 特性一覧
| 特性 | 名前                | 型     | 多重度 | ラベル       |
|------+---------------------+--------+--------+--------------|
| 属性 | name                | int    |      1 | 都市 |
| 属性 | latitude            | string |      1 | 緯度         |
| 属性 | longitude           | int    |      1 | 経度         |
| 属性 | average_temperature | int    |      1 | 平均気温     |
| 属性 | precipitation       | int    |      1 | 降水量       |

* prologue

store-create 'City 'city

この初期設定により以下の設定が行われます。

  • メモリDBの初期化
  • モデルの定義
  • モデルに従ったデータベースのテーブルの作成
メモリDBの初期化

envセクションで組み込みRDBのH2をメモリモードで起動するように記述しています。

モデルの定義

voucherセクションでモデルの定義を行っています。

モデルに従ったデータベースのテーブルの作成

prologueセクションでテーブルを作成する記述を行っています。

モデル

voucherセクションで以下のモデルを記述しています。

ボクは2008年ごろから帳票指向アーキテクチャをターゲットにしたモデリングの手法SimpleModelingを整備しています。

SimpleModelingではSimpleModelerというモデルコンパイラでプログラムの自動生成を行うことが可能です。

voucherはSimpleModelingのアーキタイプで「伝票」を記述するためのモデルです。一般のOOADではValue ObjectやDTO(Data Transfer Object)という方向性のモデルです。

SimpleModelingでは、voucher以外にも多数の種類のモデルを定義していますが、現時点ではKaleidoxではvoucherのみサポートしています。

現在SimpleModelerの新版を開発中で、これをKaleidoxに組み込めば各種モデルの操作をKaleidoxで行うことができるようになる予定ですが、現在は暫定的にvoucherのみ扱い可能にしています。

voucherセクションで定義しているvoucherは都市の緯度・経度、平均気温、降水量を定義した以下のものです。

* voucher

** City

#+caption: 特性一覧
| 特性 | 名前                | 型     | 多重度 | ラベル       |
|------+---------------------+--------+--------+--------------|
| 属性 | name                | int    |      1 | 都市 |
| 属性 | latitude            | string |      1 | 緯度         |
| 属性 | longitude           | int    |      1 | 経度         |
| 属性 | average_temperature | int    |      1 | 平均気温     |
| 属性 | precipitation       | int    |      1 | 降水量       |

この表の定義によってvoucher Cityが定義されます。

テーブルの作成

前述のinit.kldのprologueセクションは以下になっています。

* prologue

store-create 'City

store-create関数はテーブルの作成を行います。第1引数にモデル名Cityを指定しています。

このためKaleidox起動時にprologueセクションでこのstore-create関数が実行され、バウチャーCityのモデル定義に従ったテーブルCityがメモリDB内に作成されます。

今回はテスト目的でメモリDBを使用していますが、MySQLなどのRDBを使う場合にすでにテーブルが作成されている場合はこの処理は不要です。

データ格納

init.kldの設定によりKaleidox起動後はテーブルcityが作成されています。このテーブルにデータの格納を行ってみます。

都市,緯度,経度,平均気温,降水量
札幌,43.055248,141.345505,8.0,1158
仙台,38.254162,140.891403,11.9,1219
東京,35.680909,139.767372,15.3,1460
名古屋,35.154919,136.920593,14.9,1575
大阪,34.702509,135.496505,16.2,1400
広島,34.377560,132.444794,15.0,1603
福岡,33.579788,130.402405,16.0,1690
那覇,26.204830,127.692398,22.4,2128

「file:city.csv」によりcity.csvを読み込みます。 city.csvはTableオブジェクトとして読み込まれます。

kaleidox> file:city.csv
Table[5x8]
kaleidox> :show:print
┏━━━━━━┯━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━┯━━━━━━┓
┃都市  │緯度     │経度      │平均気温│降水量┃
┣━━━━━━┿━━━━━━━━━┿━━━━━━━━━━┿━━━━━━━━┿━━━━━━┫
┃札幌  │43.055248│141.345505│8.0     │1158  ┃
┃仙台  │38.254162│140.891403│11.9    │1219  ┃
┃東京  │35.680909│139.767372│15.3    │1460  ┃
┃名古屋│35.154919│136.920593│14.9    │1575  ┃
┃大阪  │34.702509│135.496505│16.2    │1400  ┃
┃広島  │34.377560│132.444794│15.0    │1603  ┃
┃福岡  │33.579788│130.402405│16.0    │1690  ┃
┃那覇  │26.204830│127.692398│22.4    │2128  ┃
┗━━━━━━┷━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━┷━━━━━━┛

読み込んだTableオブジェクトをテーブルCityに書き込みます。

Tableのヘッダにあるカラム名をキーにしてテーブルに書き込みます。このカラム名はVoucherモデルの名前だけでなくラベルとも照合されます。

たとえばVoucherモデルの定義ではCityオブジェクトの都市名を格納する属性はnameですが、ラベルが「都市」になっています。このためTableオブジェクトのカラム名nameだけでなくカラム名「都市」も格納対象となります。他のカラムも同様に、Cityオブジェクトの各属性とも対応付けられます。そして、Cityオブジェクトを格納するCityテーブルの該当するカラムとの対応付けも行われます。

テーブルへの追加格納はstore-insert関数で行います。

第1引数にテーブル名、第2引数にTableオブジェクトを指定します。ここではTableオブジェクトの読み込み直後で、Tableオブジェクトがスタックの先頭に積まれているので第2引数を省略してスタック上のTableオブジェクトを指定しています。

kaleidox> store-insert 'City
(0 0 0 0 0 0 0 0)

store-insert関数の返却値は新規作成したレコードのIDのリストです。CityテーブルはIDを持たないテーブルのためレコード数分の0を要素として持つリストが返されています。

データの読み込み

store-select関数でテーブルに格納したデータを読み込みます。

kaleidox> store-select 'City
Table[5x10]
kaleidox> :show:print
┏━━━━━━┯━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━━━━━━━━━━━━┯━━━━━━━━━━━━━┓
┃name  │latitude │longitude │average_temperature│precipitation┃
┣━━━━━━┿━━━━━━━━━┿━━━━━━━━━━┿━━━━━━━━━━━━━━━━━━━┿━━━━━━━━━━━━━┫
┃札幌  │43.055248│141.345505│8.0                │1158.0       ┃
┃仙台  │38.254162│140.891403│11.9               │1219.0       ┃
┃東京  │35.680909│139.767372│15.3               │1460.0       ┃
┃名古屋│35.154919│136.920593│14.9               │1575.0       ┃
┃大阪  │34.702509│135.496505│16.2               │1400.0       ┃
┃広島  │34.37756 │132.444794│15.0               │1603.0       ┃
┃福岡  │33.579788│130.402405│16.0               │1690.0       ┃
┃那覇  │26.20483 │127.692398│22.4               │2128.0       ┃
┗━━━━━━┷━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━┛

store-select関数のデフォルト動作ではモデルの属性名が使用されます。このため、都市はname、緯度はlatitudeといったヘッダ名を使用したTableオブジェクトとなっています。

プログラム的にデータを処理する場合はこの方が都合がよいですが、外部出力を行う場合はモデル側のラベル名がTableオブジェクトのヘッダ名になっている方が便利です。

このための指定を行うオプションとしてstore-select関数ではtable-headerスイッチを用意しています。

以下では(Lispの)キーワード指定によってtable-headerスイッチにlabelを指定しています。このためstore-select関数では、データを読み込むTableオブジェクトのカラム名をモデルのラベル名にしています。

kaleidox> store-select :table-header 'label 'City
Table[5x10]
kaleidox> :show:print
┏━━━━━━┯━━━━━━━━━┯━━━━━━━━━━┯━━━━━━━━┯━━━━━━┓
┃都市  │緯度     │経度      │平均気温│降水量┃
┣━━━━━━┿━━━━━━━━━┿━━━━━━━━━━┿━━━━━━━━┿━━━━━━┫
┃札幌  │43.055248│141.345505│8.0     │1158.0┃
┃仙台  │38.254162│140.891403│11.9    │1219.0┃
┃東京  │35.680909│139.767372│15.3    │1460.0┃
┃名古屋│35.154919│136.920593│14.9    │1575.0┃
┃大阪  │34.702509│135.496505│16.2    │1400.0┃
┃広島  │34.37756 │132.444794│15.0    │1603.0┃
┃福岡  │33.579788│130.402405│16.0    │1690.0┃
┃那覇  │26.20483 │127.692398│22.4    │2128.0┃
┗━━━━━━┷━━━━━━━━━┷━━━━━━━━━━┷━━━━━━━━┷━━━━━━┛

チャート表示

最後に、テーブルから読み込んでみたデータをチャートに表示しましょう。ここからは前回「Kaleidox/単回帰分析」と同じ処理です。詳細はそちらを参照してください。

まずTableオブジェクトからチャートに表示するデータを抽出します。

kaleidox> table-select 0,1,3 x
Table[3x8]
kaleidox> :show:print
Table[3x8]
┏━━━━━━┯━━━━━━━━━┯━━━━━━━━┓
┃都市  │緯度     │平均気温┃
┣━━━━━━┿━━━━━━━━━┿━━━━━━━━┫
┃札幌  │43.055248│8.0     ┃
┃仙台  │38.254162│11.9    ┃
┃東京  │35.680909│15.3    ┃
┃名古屋│35.154919│14.9    ┃
┃大阪  │34.702509│16.2    ┃
┃広島  │34.377560│15.0    ┃
┃福岡  │33.579788│16.0    ┃
┃那覇  │26.204830│22.4    ┃
┗━━━━━━┷━━━━━━━━━┷━━━━━━━━┛

このTableオブジェクトをtable-chart関数でチャートに表示します。

まず、抽出後のTableオブジェクトを変数xに束縛します。Tableオブジェクトは抽出直後なのでスタックの先頭に積まれています。setq関数の第2引数を省略することでスタック上のTableオブジェクトが束縛対象となります。

kaleidox> setq x
kaleidox> table-chart x

以下のようなチャートが表示されます。


また単回帰分析を行う場合はanalyzeスイッチにsimple-regressionを指定します。

kaleidox> table-chart :analyze 'simple-regression x

以下のようなチャートが表示されます。


まとめ

頭出しレベルですが、モデル駆動開発のイメージを確認するために簡単な連携例を説明しました。

基本的な方向性としては、モデル定義を行った後は簡単なアクション言語による記述のみでアプリケーションを記述したいということです。

モデル定義がのままプログラミングにつながることで、モデルをプログラムに翻訳することによって起きているプログラミングの工数を大幅に低減することできます。また、これと同じぐらい重要なのはモデルとプログラムのインピーダンスミスマッチをなくすることができることです。モデルとプログラミングが一体となることで、よりモデリングに集中することができます。

SimpleModelerの改版版は現在開発中ですが、これをKaleidoxに組み込むことでより広範囲のモデルをモデル駆動の対象としてアプリケーション開発に活用できることができるようになります。

諸元

  • Kaleidox : 0.1.10
気象データ

以下のページ「5.おもな都市の月平均気温・月降水量」のデータを使用しました。

http://www.biodic.go.jp/reports/2-2/hyo/aa126_001.html