2020年12月31日木曜日

SimpleModel/テクノロジー

クラウド・アプリケーションを構成する以下の各種要素技術に対して、SM2020のメタモデル設計の方針検討を行っています。

  • 関数
  • CQRS
  • Event Sourcing
  • Eventually Consistency
  • マイクロサービス
  • BigData
  • AI
  • IoT
  • DevOps

前回はCQRS、Event Sourcing、Eventually Consistency、マイクロサービスについて検討しました。

今回は、BigData、AI、IoT、DevOpsについて検討します。また、検討項目にDXを追加することにしました。

BigData

アプリケーション実行中に得られるデータを分析して、有益なデータを抽出し、アプリケーションにフィードバックして活用することが普通になってきました。アプリケーションの基本機能として、実行結果データの分析が必要となってきているといえます。

BigDataを実現する仕組みとしては、以下のような構成を取ることになるでしょう。

  • アプリケーションの実行結果の記録機構
  • アプリケーション実行結果データの収集・保管機構
  • 保管データ整理機構
  • 整理データの分析機構
  • 分析データのアプリケーション取込み機構

アプリケーションの実行結果の記録機構はログまたはデータベースに記録することになります。

アプリケーションでは採取するログデータと記録用のデータベースのエンティティが設計のポイントです。

アプリケーション実行結果データ収集・保管機構はdata lakeやdata warehouseといったサブシステムを中心としたメカニズムになります。

アプリケーションではdata lakeやdata warehouseの基盤の上でデータフォーマットの調整などが主な仕事となるでしょう。

保管データ整理機構はdata lakeやdata warehouse上に格納した生データから、分析に適した正規化を施したデータを作成します。

アプリケーションでは分析に適した正規化データの設計が必要になります。

整理データの分析機構はHadoopやSparkといった大規模演算基盤上に構築したバッチやイベントハンドラとして実現することになるでしょう。

アプリケーションでは、アプリケーションのユースケースに沿った活用方法で直接使用できるデータに変換する処理を行うことになります。

分析データのアプリケーション取込み機構は整理データから作成したデータをアプリケーション側に取り込む処理です。

アプリケーションではデータを取り込むための受け皿としてデータベースのエンティティなどを用意する必要があります。

モデリングの検討

アプリケーションの実行結果の記録機構に対して、アプリケーションではログデータのフォーマットと記録用のデータベースエンティティの設計が必要になります。

アプリケーションのモデリングの観点ではログのフォーマットはデータの最終的な利用方法から逆算して必要十分な情報が取得できるように設計することになります。このため、ユースケースモデルからの一連の連鎖でログのフォーマットまでモデルの連鎖を追跡できると理想的です。

データベースのエンティティという観点では、SM2008からeventエンティティを用意しています。eventエンティティによってアプリケーション上重要な出来事はデータベース上に記録されるので、ここからBigDataに必要な情報を収集することができます。

アプリケーション実行結果データの収集・保管機構から保管データ整理機構にかけてはデータ変換処理になります。

整理データの分析機構に対してもデータ変換処理という観点で考えればよいでしょう。

分析データのアプリケーション取込み機構に対しては、SM2008からsummaryエンティティを用意しています。整理データの分析機構で生成したデータをsummaryエンティティに書き込むことで、アプリケーションで利用することができます。

AI

AIは大きく分けて、従来型の知識ベースや推論エンジンによるAI(推論型AI)と、最近主流となっている学習型AIの2種類があります。

推論型AIに対してアプリケーションでの利用の観点では、外部のサブシステムとして用意したAIエンジンを手続き呼び出しで使用するという形になるでしょう。

一方、学習型AIの場合はアプリケーションの実行結果を使用して学習を行う必要がある点が異なります。このため、アプリケーションとは密結合のアプローチとなります。

学習型AIでは実行結果に対して何らかの計算を行い、計算結果をフィードバックするという処理になりますが、これは前述のBigDataと基本的には同じものです。BigDataの場合はSQL的な集計処理になりますが、学習型AIの場合は深層学習などの複雑な計算になる点が異なります。

モデリングの検討

SM2008ではAIシステムの設計はスコープ外で、外部のAIシステムを利用するというアプローチを取っています。SM2020でも基本的なプローチは同じです。

ただし、推論型AIと学習型AIではモデリングのアプローチもかなり異なりそうです。それぞれについて検討します。

推論型AI

推論型AIの実現方式は外部のAIシステムをRPCなどで利用するという形になります。アプリケーションのモデリングの観点ではこれをアプリケーション内のモデルでどのように表現するのかという選択になります。

シンプルなのはAIサブシステムをサービスとしてモデル化しオペレーション呼び出しで利用する方法です。

ドメイン知識などを保持したエンティティとして実現したい場合は、SM2008から用意しているruleエンティティを使用します。

学習型AI

学習型AIの場合、エンジンそのものは推論型AIと同様に外部システムとして利用する形を想定していますが、アプリケーションの実行結果のデータを使って学習を行う点が大きな相違点です。

学習データの取り込み方式は基本的に前述のBigDataと同じものになります。このためBigDataで議論したアプローチを取ることになります。

学習型AIをアプリケーションから利用する方法ですが、以下の3つが考えられます。

  • サービスへのオペレーション呼び出し
  • ruleエンティティ
  • summaryエンティティ

サービスへのオペレーション呼び出しとruleエンティティは推論型AIと同じアプローチです。

summaryエンティティはBigDataと同じアプローチです。

IoT

ビジネス・アプリケーションあってもIoTを扱うケースが増えてくるのは確実です。アプリケーションでIoTを使う場合、IoTの基盤機能そのものを自ら実現するのではなく、外部のIoT基盤を外部サービスとして使用する方式を想定することにします。

IoT基盤とアプリケーションの接続方式として以下のものが有力です。

  • RPCによるオペレーション呼び出し
  • RPCによるコールバック
  • サービス・バスによるイベント駆動
  • リアクティブ・ストリームによるイベント駆動

RPCによるオペレーション呼び出しはIoT基盤の提供するAPIのオペレーションを、アプリケーションから直接呼び出す方式です。

こちらは、アプリケーションからIoT基盤側を呼び出す方式ですが、IoTの応用では逆にいイベント駆動であるIoT基盤からアプリケーションを呼び出す方式が主となります。

RPCによるコールバックはIoT基盤にコールバックを登録し、コールバックでイベント駆動処理を行う方式です。

サービス・バスによるイベント駆動は汎用のサービス・バスにコールバックを登録し、コールバックでイベント駆動処理を行う方式です。IoT基盤で発生したIoTイベントをより汎用的な形に変換してサービス・バスに流し、サービス・バスに登録されているアプリケーションのイベント・ハンドラを起動します。より汎用的なサービス・バスのイベントを使用する点が異なります。

RPCによるコールバックとサービス・バスによるイベント駆動はいずれもイベントハンドラによるコールバックによる実現方式です。このため、アプリケーションの規模が大きくなるとコールバック地獄と呼ばれるアンチパターンに陥る可能性が高まります。

この問題の解決方法として有力なのがリアクティブ・ストリームです。

関数の回でも取り上げましたが、イベント駆動型のアプリケーションはリアクティブ・ストリームで記述するのが関数型時代の定石といえます。

モデリングの検討

IoTアプリケーションのモデリングはモデル駆動アプリケーションのモデリングという側面が大きいといえます。

イベント駆動というアプリケーションの特性からはコールバック処理がアプリケーションの軸となりますが、いわゆるコールバック地獄とよばれるアンチパターンになりがちです。

コールバック地獄を起こさずイベント駆動のアプリケーション・ロジックを記述する手法として期待しているのがリアクティブ・ストリームです。

リアクティブ・ストリームは一種のパイプラインなので、パイプラインとして抽象化することでモデル化が可能と思われます。ただ、伝統的に使用されているデータフローより動的な側面が大きいと思うので別のメタモデル要素を導入するのが妥当と考えています。SM2020ではこのあたりの検討を行う予定です。

IoTアプリケーションの特性からはイベントの階層化の設計が重要です。SM2020では以下の階層で対応するアプローチを検討中です。

  • IoTイベント
  • 生イベント
  • ビジネス・イベント

    イベント駆動で使用するイベントはeventエンティティと連携するのがSM2008のアプローチでした。SM2020でも引き続きこのアプローチを軸に考えていますが、IoT対応で発生するイベント階層との対応関係について整理していく予定です。

    DevOps

    DevOpsはソフトウエア開発と開発したソフトウェアの配備や運用などを統合した考え方で、運用配備を含めたソフトウェア開発の自動化と見える化を目指しています。

    2000年代初頭の段階では、なかなかそこまでは実現のスコープに入ってきていませんでした。

    UMLでも配備モデルを記述することは可能でしたが、当時はChefなどのDevOpsのライフサイクル全体をカバーした配備・運用ツールなどは存在せず、配備モデルも青写真レベルに留まっていることが一般的でした。

    現在ではツール類を始めとした環境が整っているので、本格的なモデル駆動開発への組み込みも可能と思われます。

    モデリングの検討

    アプリケーション・モデリングの観点では以下の点が重要と考えています。

    • 配備モデルの定義と適用
    • 運用性を高めるためのモデル要素
    • テスト性を高めるためのモデル要素

    モデル駆動開発にDevOpsを適用することを考えると、作成したアプリケーション・モデルを直接、配備や運用の記述データとして使用できると理想的です。この中心となるのが配備モデルです。配備を考えていく上では、モデルの物理的な側面を記述するコンポーネントやモジュールといったモデル要素が重要になってきます。

    SM2008では配備モデルはスコープ外でしたが、SM2020ではDevOpsの観点で配備モデルの設計を行っていきたいと考えています。

    運用性を高めるためのモデル要素としては、エンティティを監視するための属性の追加といったものが考えられます。JMX(Java Management Extension)といったプラットフォームのモニタリングツールと連動させることによって運用性が高まります。

    このような監視のための属性を抽出するためには、運用フェーズのユースケース分析なども必要になってきます。

    テスト性を高めるためのモデル要素としては、エンティティの内部状態を見える化して検証可能にするための属性追加といったものが考えられます。

    運用性やテスト性を高めるためのモデリング上のアプローチは他にも色々あると思うので、SM2020の中に取り込んできたいと考えています。

    DX

    DX(Digital Transformation)は色々な切り口があると思いますが、ここでは企業システムを最適化したビジネス・モデル、業務プロセスをサイバー空間上で新規構築すること、とします。

    基幹システムの入出力の部分を紙ベースからIT化するというものであれば、OOAD(Object-Oriented Analysis and Design)の出番は限定的ですが、ITベースのビジネス・モデル、業務プロセスを一から設計するとなると、超上流からOOADによるモデリングが必要になってきます。

    ビジネス・モデリングを受けてのアプリケーション開発では、通常のOOADによるモデリングになります。

    IoTと同様にDXの場合も、DX基盤といったものを軸にアプリケーション構築を行うようになるケースが多いと考えられるので、モデリング段階では抽象度の高いモデルで設計しDX基盤向けのコードを自動生成するというようなアプローチが有効と思われます。

    モデリングの検討

    SM2020はビジネス・モデリングはスコープ外ですが、ビジネス・モデリングで作成したモデルをモデル駆動開発用に連携させていくことでモデル駆動開発に組み込むアプローチを取っています。ステレオタイプといった拡張機構を使用して超上流のモデルをSM2020内に埋め込んだりリンクを張ったりといった連携を想定しています。

    DXアプリケーションのモデリングについては、IoT基盤との連携を軸に検討していく予定です。鍵となるモデルはワークフローと状態機械と考えています。

    まとめ

    今回は、BigData、AI、IoT、DevOps、DXについて検討しました。

    前々回、前回と合わせて以下の項目について検討しました。

    • 関数
    • CQRS
    • Event Sourcing
    • Eventually Consistency
    • マイクロサービス
    • BigData
    • AI
    • IoT
    • DevOps
    • DX

    全体としてイベント駆動アプリケーションのモデリングがさらに重要になってきていると感じました。

    このため状態機械の価値がさらに高まりました。状態機械は従来は現場の開発ではあまり活用されてきていないと思いますが、モデル駆動開発の助けを借りて本格的に活用していく必然性が増してきたかもしれません。

    また、アプリケーション全体の振る舞いを統合する概念が重要になってくると思います。一つのアプローチはユースケースをハブにして帰納的に束ねていくことでしょう。ユースケースの価値もさらに高まってきたと思います。

    特に重要と感じたのが以下の3つのフロー系のモデルです。

    • データフロー
    • ワークフロー
    • リアクティブストリーム

    SM2020ではこれらのモデルについてモデルのセマンティクスと記述方法、使い分けの指針などの整備に力をいれていきたいと思います。

    2020年11月30日月曜日

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

    クラウド・アプリケーションを構成する以下の各種要素技術に対して、SM2020のメタモデル設計の方針検討を行っています。

    • 関数
    • CQRS
    • Event Sourcing
    • Eventually Consistency
    • マイクロサービス
    • BigData
    • AI
    • IoT
    • DevOps

    前回は関数について検討しました。

    今回は、CQRS、Event Sourcing、Eventually Consistency、マイクロサービスについて検討します。

    CQRS

    CQRS(Command Query Responsibility Segregation)は、ざっくりいうとコマンド投入とその結果引き起こされるデータ更新の確認処理を分離するアーキテクチャです。

    従来型のCRUD(CreateReadUpdate/Delete)がデータの作成更新が同期型であるのに対して、データの作成更新が非同期で行われる点が重要です。

    CQRSのアーキテクチャを取ることによって、データ作成更新のボトルネックを分散させることができ、スケーラビリティを高めることができるメリットがあります。

    ただし、利用者からのデータの見え方が参照系と更新系で非対称になるためUX上の見せ方が重要になってきます。

    モデリングの検討

    CQRSのアーキテクチャをモデリングで扱う場合の論点として以下のものを考えています。

    • ユースケース
    • イベント駆動処理
    • サービス設計
    ユースケース

    CQRSでは、UX上の見せ方が重要となるため、適切なUXをできるだけ上流で設計していくことが重要です。

    この目的で使用することになるモデルはユースケースです。

    イベント駆動処理

    CQRSアーキテクチャに則ったアプリケーションを作成する場合、ESB(Enterprise Service Bus)を使用したイベント駆動アーキテクチャが有力な選択肢です。

    ESBアプリケーションを通常のオブジェクト指向で都度モデリングしてもよいのですが、かなり複雑なモデルになってしまいます。一方、CQRS向けのESBアプリケーションはかなりの定型化ができそうなので、うまい抽象モデルを見つけることができれば、シンプルなモデルとこのモデルからの自動生成を組み合わせて効率的な開発ができそうです。

    SM2020では、このような目的の抽象モデルの開発を行っていきたいと考えています。

    サービス設計

    CQRSでは、参照系、更新系でそれぞれオペレーションが定義されることになりますが、それぞれのオペレーションがCQRSのなかでどのような役割を担っているのか、それぞれのオペレーション間の関係がどうなっているのかという点のモデリングも必要となってきます。

    たとえば、CQRSのイベント駆動処理部の振る舞いを変えたときに、どのオペレーションにどのような影響がでるのかといった点をモデル上で検査できるというような用途を想定しています。

    Event Sourcing

    Event Sourcingは、オブジェクトの状態をイベント列を使って表現、管理していく方式です。スケーラビリティやアベイラビリティを担保する上で非常に有力なアプローチです。

    イベント列から状態を計算する方式などを実際の製品開発で試してみましたが、実装が複雑になる、性能的な要件が厳しいなどの問題もあり、なかなか一筋縄ではいかない感じです。

    このため、状態に関しては従来どおりリソース側の属性で管理するのが現実解ではないかと思います。

    ただし、イベントの発行・記録とリソースの状態遷移を連動させるという方式設計はアプリケーションの見通しをよくし、拡張性や保守性を高めるのに寄与するので積極的に採用したいところです。

    モデリングの検討

    実現方式は実行プラットフォームに依存する部分が多いと考えられます。ただし、どの実行プラットフォームでも有効な抽象モデルがあると考えられるので、これを探っていきたいと考えています。

    SimpleModelでは、従来よりイベントエンティティを重要なモデル要素として扱ってきました。

    イベントエンティティを発展させる形でEvent Sourcingとの接点を探っていきたいと考えています。

    マイクロサービス

    クラウド・アプリケーションでスケーラビリティやアベイラビリティを高めるための実現方式としてマイクロサービスが注目されています。

    マイクロサービスといっても単なるSOA的なものから、メッセージ中心の分散プラットフォームまで色々な形態が考えられます。

    一つの典型的な方式は、複数のサービス間をスケールアウト可能なRPCを使って接続するというものです。RPC層でスケーラビリティやアベイラビリティの透過性を担保できる場合は、モデリング的には通常のRPCとして扱うことで十分と思われます。

    モデリングの検討

    前述したとおり、RPC層でスケーラビリティやアベイラビリティの透過性を担保できる場合は、モデリング的には通常のRPCと同様の枠組みで扱うことになると思います。

    具体的にはサービスとオペレーションとしてモデリングします。ただし、ステレオタイプを使って、マイクロサービス用のRPCであることを定義していく形を想定しています。

    また、マイクロサービスはRPCなどを使った通信が発生するので、オブジェクト指向だけでなくコンポーネント指向の観点から疎結合・凝集、配備の問題をモデルの上で扱っていく必要があります。

    Eventually Consistency

    Eventually Consistencyは、オペレーション完了時にオペレーションによって変化したデータ更新が保証されず、オペレーション完了後のどこかの時点でデータ更新が最終的には行われることを指します。

    従来型のCRUDのオペレーションではオペレーション完了時に、オペレーション内で作成・更新したデータベースのレコードがデータベース内に完全に反映され永続化されることが保証されます。

    一方、Eventually Consistencyの性質を持つオペレーションの場合は、オペレーション完了時にこれを保証しません。つまり、オペレーション完了直後に更新したデータを参照した場合に、古いデータを取得してしまう、ということを許容します。

    アプリケーション開発的には扱いづらい性質であり、できれば避けたいところですがクラウド・アプリケーションでは以下のような理由により必要なケースが多々発生します。

    • スケーラビリティ
    • イベント駆動処理
    • バッチ処理
    スケーラビリティ

    クラウド・アプリケーションでは、多数のクライアントを同時接続できることが重要です。

    ここでボトルネックになるのはデータベースの更新処理です。

    同一レコードに対する書き込み処理が重なると、排他制御によってレスポンス性能、スループット性能のどちらも大幅に低減します。排他制御そのものは避けることはできないので、その他の部分で何らかの対策を取る必要があります。

    その有力な対策の一つが Eventually Consistency です。

    Eventually Consistency の性質を取ることによって、処理本体とオペレーション呼び出しの完了を分離することができます。オペレーション呼び出しは処理本体をバックグラウンドでの実行スケジュールするだけで完了できるので、レスポンス性能は大幅に更新します。

    システム全体のスループット性能も、バックグランド処理をキューイングするなどして平準化したり、複数の処理を一つにまとめたりすることで向上させることが可能になります。

    イベント駆動

    アプリケーション・ロジックがESBを使用したイベント駆動で実現されている場合には、処理の実行が非同期となるためオペレーションの完了に同期させることが困難です。

    この場合はEventually Consistencyを前提にオペレーションの性質を定義する必要があります。

    バッチ処理

    Webのレスポンスタイムの上限は3秒程度とするケースも多いと思いますが、アクションの実行時間がこれを超える場合にはアクションをバックグラウンドで実行することになります。この場合、当然ながらEventually Consistencyを前提としたオペレーションになります。

    モデリングの検討

    スケーラビリティ、イベント駆動、バッチ処理の観点からEventually Consistencyについて見てきました。

    共通しているのは、メインの処理はバックグラウンドで行われ、オペレーションの返却値では処理の結果を返すことができないということです。

    また、処理はバックグラウンド処理で行われますが、必ずしも成功するとは限りません。

    上記の点からアプリケーションの設計においては以下の2つの機能が必要になります。

    • バックグラウンド処理の結果確認
    • バックグラウンド処理リカバリ

    いずれも、通常のアプリケーション処理として都度モデリングを行ってもよいのですが、かなりの定型化が可能という予感もあります。

    実行時のクラウドプラットフォーム側のフレームワーク次第という面も大きいので、フレームワークとの連携を想定した上でモデリングの定型化を図っていきたいと考えています。

    ユースケース

    ユースケース・モデルの段階で以下のようなEventually Consistencyの影響を取り込んでいく必要があります。

    • リカバリ方式
    • オペレーションの特性情報

    SM2020のユースケースモデル設計で上記の性質の定義方法を検討する予定です。

    オペレーションの特性情報

    サービスのオペレーションによる更新処理に対してステレオタイプなどを用いてEventually Consistencyであることの明示することが有効と思われます。

    SM2020のユースケースモデル設計で上記の性質の定義方法を検討する予定です。

    モデリングの検討

    CQRS、Event Sourcing、Eventually Consistency、マイクロサービスといったクラウド・アプリケーションのアプリケーション・アーキテクチャの整理とモデリングでの対応について検討しました。

    検討の結果、以下の項目がSM2020で検討していく候補として抽出できました。

    ユースケース

    以下の場合にユースケース段階で考慮が必要であることが分かりました。

    CQRS
    利用者のUX
    Eventually Consistency
    データが反映されるタイミング

    上記の項目をユースケースモデルに取り込んでいく予定です。

    イベント・エンティティ

    CQRSでのESB利用やEvent Sourcingでイベントが重要なモデル要素になっています。

    SimpleModelでは元々イベント・エンティティを軸に静的モデルと動的モデルを連携させるモデル体系になっています。

    このイベント・エンティティを拡張してESBやEvent sourcingでの利用をアシストする方法について検討したいと思います。

    ESB

    CQRSやEventually Consistencyなどの実現方式としてESBが有力であることが分かりました。

    ESBアプリケーションを都度スクラッチでモデリングしてもよいですが、可能であればCQRSやEventually Consistencyの観点からのESBの使い方にフォーカスした抽象モデルを定義し、この抽象モデルを使用してモデリングと実装を連携させていくというアプローチを考えていきたいと思います。

    オペレーション

    オペレーションの特性情報として以下の項目が候補になります。

    • CQRS上の特性
    • Eventually Consistency上の特性
    • マイクロサービス上の特性
    コンポーネント指向

    ESBやマイクロサービスを用いたアプリケーションでは、疎結合/凝集、配備の問題が重要になってくるので、オブジェクト指向に加えてコンポーネント指向でのモデリングも必要になってきます。

    SM2020ではESB、マイクロサービスを視野に入れたコンポーネント指向のモデリングの枠組みを整備したいと考えています。

    まとめ

    今回は9つ挙げた要素技術の中でCQRS、Event Sourcing、Eventually Consistency、マイクロサービスを取り上げました。

    次回はBigData, AI, IoT, DevOpsについて検討を行う予定です。

    2020年10月31日土曜日

    SimpleModel/関数

    前回は以下に示すクラウド・アプリケーションの各種特性に対してアプリケーション・アーキテクチャへの影響を整理した後、SimpleModel 2020(SM2020)のメタモデル設計の方針検討を行いました。

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

    続けてラウド・アプリケーションを構成する以下の各種要素技術に対して、SM2020のメタモデル設計の方針検討を行います。

    • 関数
    • CQRS
    • Event Sourcing
    • Eventually consistency
    • マイクロサービス
    • BigData
    • AI
    • IoT
    • DevOps

    今回は、関数について検討します。

    関数

    プログラミング言語における「関数」は、C言語の手続き的な関数から、Haskellのような純粋関数型言語の関数まで非常に広い幅があります。

    ここでは、Haskellのような純粋関数型言語やScalaのようなオブジェクト指向と関数型のハイブリット言語における紳士協定的な関数まで、数理モデルに基づく特性を意図した「関数」を関数と呼ぶことにします。

    プログラミングにおける関数の長所としては以下のものを挙げることができます。

    • バグが出にくい
    • 生産性が高い
    • 並列・分散処理の記述に適している

    ボクの体感でも静的型付け言語の場合、オブジェクト指向プログラミングより関数型プログラミングの方が圧倒的に生産性が高く、バグも出にくいと思います。

    ただし、関数型言語には以下の短所があります。

    • 実行時性能がやや不利
    • 状態を持つプログラムの記述が困難
    • 外界との入出力の記述が大変

    実行時性能がやや不利な点は近年のハードウェアの進化により、よほどのクリティカルな箇所でない限り実用上の問題にはならないでしょう。

    しかし、「状態を持つプログラムの記述が困難」と「外界との入出力の記述が大変」についてはかなり大きな問題です。この問題はモナドの実用化により大きく緩和されましたが、それでもオブジェクト指向言語に比べると大きな制約であるのは確かです。

    得意とするプログラミングの分野という観点からは以下のことが言えると思います。

    • 関数型はアルゴリズムの記述に向いている
    • オブジェクト指向型は外部世界の制御に向いている

    また関数型は並列・分散処理に向いているという特性も重要です。

    関数型は数理モデルに近い形でアルゴリズムを記述できるので、適切な並列・分散フレームワークを使用することで並列・分散処理そのものはフレームワーク内で自動的に行うことが可能になることを期待できます。一方、オブジェクト指向の場合は並列・分散処理を意識したプログラミングが必要になりがちです。

    上記の点から、アプリケーションはできる限り純粋関数型で記述して、外部世界との接続する部分や状態、永続データを扱う部分をオブジェクト指向で記述するというのが、現代的なプログラミングスタイルとなります。

    プログラミングの世界がこのような状況になっている以上、プログラミングよりも数理モデル寄りであるモデリングでは、オブジェクト指向と関数型のハイブリッドなアプローチが有効であることが予想されます。

    このハイブリッドなアプローチについてSM2020で検討を進めていく予定です。

    モデリングの検討

    SM2020での関数に対するアプローチは、今の所以下の3つを考えています。

    • ルール
    • データーフロー
    • リアクティブストリーム
    ルール

    UMLでは直接関数を取り扱うことはできませんが、シングルトン・オブジェクトのオペレーションにステレオタイプをつけるなどの独自拡張で対応可能です。

    ただ、モデリングの中で関数が単独で登場することは稀で、一連の関数群として定義することが多いでしょう。

    SMでは複数の関数群をルールとして束ねて管理します。ルールは分類子にスレレオタイプruleをつけて表現します。stereotypeSM2020でもこの方式を踏襲します。

    ルールは以下のような形で類型化が可能です。

    • 表構造
    • 木構造
    • プログラム
    • AI

    たとえば、市町村別配送料といったルールは簡単な表構造で表現可能です。このような場合、モデル内で表データを定義して、ここからプログラムの自動生成を行うなどの手段が考えられます。

    データフロー

    データフローはユースケース登場後のOOADではあまり使われませんが、ビジネス・アプリケーションのモデリングには有力な技法です。

    複数のデータストアに対して入出力を行うビジネス・ロジックの多くは、データフローを使ってモデル化することができます。

    また、クラウド・アプリケーションでの重要な応用分野であるBigData, AI, IoTは多種多様なデータソースからのデータを収集し、このデータを複合的に分析・計算することで新しいデータを出力することになるので、データフローモデルを使ってモデリングすることの価値が高いと思われます。

    数理モデルとも近い位置にあるモデルなので、適切な実行基盤を得ることができれば、プログラムの自動生成の対象にすることができるのではないかと期待しています。この実行基盤として候補となるのが次項のリアクティブストリームです。

    データフローについては、メタモデル内の位置づけやドメイン・モデルなどとの連携について検討を進める予定です。

    リアクティブストリーム

    イベント駆動のロジックを考える場合、伝統的なオブジェクト指向のアプローチではいわゆるcall back hellとなりがちです。独立して存在するコールバックの集まりが有機的な連携を行い一つのアプリケーションロジックとして動作することになるわけですが、アプリケーションが大きくなってくると、アプリケーションロジックの見通しが悪くなり、仕様追加や変更などを行うことのコストが増大してきます。

    この問題を解決する技術がリアクティブストリームです。

    リアクティブストリームには以下の長所もあります。

    リアクティブストリームは通しのよい関数型プログラミングで、イベント駆動アプリケーションの一連の処理をわかりやすい形で記述することができます。

    また、Akka Streamsのような適切な実行基盤を使えばアプリケーションレベルで意識することなく並列・分散処理を行うことができます。

    これらの性質を兼ね備えている要素技術がリアクティブストリームです。並列・分散が日常化するクラウド・アプリケーションでは重要な技術になってくると考えています。

    このリアクティブ・ストリームで実現するアプリケーションロジックをモデリングの中でどのように扱っていくのかという点はSM2020の中で検討していく予定です。前回説明したとおり、以下のようなモデル図を使ったモデリングが有力と考えています。

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

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

    まとめ

    今回は9つ挙げた要素技術の中で関数を取り上げました。

    次回はCQRS、Event Sourcing、Eventually Consistencyについて検討を行う予定です。

    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

    2020年2月29日土曜日

    Kaleidox: 単回帰分析

    KaleidoxプログラムではTableオブジェクトとRecordオブジェクトを中心に演算を行っていきます。

    このためTableオブジェクトとRecordオブジェクトを操作するための機能を多数サポートする予定にしています。

    今回はそういった便利な機能の中で、Tableオブジェクトのチャート表示と単回帰分析機能について説明します。

    データ

    単回帰分析を行う対象のデータを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

    データの読み込み

    KaleidoxのREPLからURIリテラルで上記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-chart関数

    データを読み込んだ直後にtable-chart関数を投入すると、以下に示すようにTableオブジェクトから必要な情報を取得して散布図を表示します。

    kaleidox> table-chart

    デフォルトでは表の第1列を項目名、第2列をX軸、第3列をY軸と解釈して自動でデータを読み込みます。

    Kaleidoxは関数の投入結果をスタックとヒストリに保存しています。table-chart関数を引数なしで起動するとスタックの先頭にあるオブジェクトを引数として使用するのでこのようなことが可能になっています。

    historyコマンドで確認するとCSVファイルをローディングした結果のTableオブジェクトは6番目に格納されていました。今後はヒストリの6番目のTableオブジェクトを使用します。

    kaleidox> :history
     1: nil
     2: Table[3x10]
     3: Matrix[1x10]
     4: Matrix[2x10]
     5: Matrix[1x2]
     6: Table[5x8]
     7: Window

    行列

    回帰分析のような数値演算を行う場合、通常はTableオブジェクトを行列に変換してから行列に対して線形代数の演算を行っていきます。

    Kaleidoxの場合はtable-matrix関数でTableオブジェクトから行列を抽出することができます。

    kaleidox> table-matrix #6
    Matrix[4x8]
    kaleidox> :show
    Matrix[4x8]
    ┌                                ┐
    │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│
    └                                ┘

    この例から分かるように、Tableオブジェクトの持つ表データのヘッダ行と数値以外の情報が入っている列を取り除いた情報を行列に再構築してくれます。

    ただし今回は行列は使用しません。

    table-select関数

    回帰分析のような数値演算を行う場合、通常はMatrixオブジェクトを使用しますが、単回帰分析のような定番の分析手法は表に対して直接使用できるようになっています。

    この記事の先頭でtable-chart関数によってTableオブジェクトの内容から自動抽出した情報を散布図として表示する操作を行いました。

    この散布図に回帰分析の結果を重ねて表示してみることにします。

    file.csvのデータをそのまま使ってもよいのですが、都市の緯度と経度に対して単回帰分析を行っても面白くないので、都市の緯度と平均気温に対して単回帰分析を行ってみます。

    まずTableデータの第1列に都市名、第2列に緯度、第3列に平均気温を取るTableオブジェクトを生成します。これはtable-chart関数が散布図を描く時に、デフォルトでは第1列に項目名、第2列にX軸の値、第3列にY軸の値を想定しているためです。

    この変換はtable-select関数で行うことができます。以下の例ではtable-select関数の引数に範囲オブジェクト「0,1,3」を指定しています。この結果オリジナルの表の第1列、第2列、第4列の内容をこの順番で並べたTableオブジェクトが生成されます。なお範囲オブジェクトの添字は0ベース、表の表現では添字は1ベースで表現しています。

    kaleidox> table-select 0,1,3 #6
    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関数を適用すると以下の散布図が表示されました。

    kaleidox> table-chart

    単回帰分析

    単回帰分析を行った結果をチャート上に表示する場合はanalyzeオプションにsimple-regressionを指定します。

    先程作成したTableオブジェクトのヒストリを確認します。

    :history
     1: nil
     2: Table[3x10]
     3: Matrix[1x10]
     4: Matrix[2x10]
     5: Matrix[1x2]
     6: Table[5x8]
     7: Window
     8: Table[3x8]

    8番目にあることが分かったので「#8」でアクセスすることができます。

    単回帰分析の結果を散布図上に表示するためにはanalyzeオプションにsimple-regressionを指定します。

    kaleidox> table-chart :analyze 'simple-regression #8

    上記のtable-chart関数の結果、以下の単回帰分析付きの散布図が表示されました。


    まとめ

    CSVファイルから読み込んだTableオブジェクトに対して、table-selection関数による簡単な加工のみで散布図の表示、単回帰分析の結果表示を行うことができました。

    通常のプログラミング言語でこの処理を行うとCSVファイルの読み込み、チャート機能の利用、数値演算処理による単回帰分析など案外大変なコーディングが必要になりますが、Kaleidoxではあっさりと実現できました。

    このようなことが可能になるのは、Kaleidoxで汎用データ構造であるTableオブジェクトを言語の中軸機能と位置付け、Tableオブジェクトを対象にさまざまな関数を用意しているからです。

    Kaleidoxはアクション言語として設計していますが、PIM(Platform Independent Model)的な抽象処理のみが記述できるだけだと実用性に乏しくなります。そういった抽象的な機能と同時に今回のTableデータ処理のような地味な実用機能もサポートし、シームレスに連携できることが必要だと考えています。

    諸元

    • Kaleidox : 0.1.10
    気象データ

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

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

    2020年1月31日金曜日

    Kaleidox: Matrix

    BigDataやAIなどがアプリケーションを構成する重要部品となってきています。このBigDataやAIをアプリケーションで扱う上で重要な技術要素として行列(matrix)があります。

    Kaleidoxでは行列をMatrixオブジェクトとして記述して各種行列演算をすることができます。

    入力

    Matrixオブジェクトの入力方法として以下の方法について見ていきます。

    • Matrixリテラル
    • matrix-load関数
    Matrixリテラル

    Matrixオブジェクトのリテラルは以下のように二重のカギ括弧で囲まれたエリアに改行と空白を区切り記号として記述したものです。

    [[
    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
    ]]

    REPLから入力すると以下のようになります。

    kaleidox> [[
    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
    ]]
    Matrix[4x8]
    kaleidox> :show
    Matrix[4x8]
    ┌                                ┐
    │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│
    └                                ┘
    matrix-load関数

    matrix-load関数でCSVファイルの内容からMatrixオブジェクトを生成します。matrix-load関数では内容の中から自動的に行列化可能な数値部分を取り出してMatrixオブジェクトにします。

    日本の都市について緯度経度と平均気温、降水量を記述した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

    matrix-load関数を使うと以下のようにMatrixオブジェクトを取得することができます。

    kaleidox> matrix-load file:city.csv
    Matrix[4x8]
    kaleidox> :show
    Matrix[4x8]
    ┌                                ┐
    │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│
    └                                ┘
    Tableオブジェクト

    TableオブジェクトからMatrixオブジェクトを取得することができます。

    引き続き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

    このCSVファイルをtable-load関数を使って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オブジェクトを起点にさまざまな操作を行うことができますが、ここではmatrixメソッドを使用してMatrixオブジェクトに変換しています。matrix-load関数と同様に行列化可能なデータを抽出してMatrixオブジェクト化しています。

    kaleidox> .matrix
    Matrix[0x8]
    kaleidox> :show
    Matrix[4x8]
    ┌                                ┐
    │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│
    └                                ┘

    参照

    Matrixオブジェクトを参照して各種データを取得することができます。

    準備としてcity.csvに入っているデータをMatrix化したものを変数xに束縛します。

    kaleidox> setq x (matrix-load file:city.csv)
    Matrix[4x8]
    kaleidox> x
    Matrix[4x8]
    kaleidox> :show
    Matrix[4x8]
    ┌                                ┐
    │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│
    └                                ┘
    行の参照

    Matrixオブジェクトの行はrowメソッドで取得することができます。引数に行番号を指定します。行番号は0始まりです。

    kaleidox> x.row(0)
    [43.055248 141.345505 8.0 1158.0]
    列の参照

    Matrixオブジェクトの列はcolumnメソッドで取得することができます。引数に列番号を指定します。列番号は0始まりです。

    kaleidox> x.column(3)
    [1158.0 1219.0 1460.0 1575.0 1400.0 1603.0 1690.0 2128.0]
    データの参照

    Matrixオブジェクトのデータはatメソッドで取得することができます。引数に列番号、行番号を指定します。

    kaleidox> x.at(2,3)
    14.9

    演算

    準備として2✕2の正方行列を変数xに束縛します。

    kaleidox> setq x [[
    1 2
    3 4
    ]]
    Matrix[2x2]
    kaleidox> :show
    Matrix[2x2]
    ┌       ┐
    │1.0 2.0│
    │3.0 4.0│
    └       ┘
    加算

    加算は+メソッドです。

    kaleidox>+ x x
    Matrix[2x2]
    kaleidox> :show
    Matrix[2x2]
    ┌       ┐
    │2.0 4.0│
    │6.0 8.0│
    └       ┘
    積算

    積算は*メソッドです。

    kaleidox> * x x
    Matrix[2x2]
    kaleidox> :show
    Matrix[2x2]
    ┌         ┐
    │7.0  10.0│
    │15.0 22.0│
    └         ┘
    逆行列

    逆行列はinvメソッドで行います。

    kaleidox> x.inv
    Matrix[2x2]
    kaleidox> :show
    Matrix[2x2]
    ┌                                       ┐
    │-1.9999999999999996 0.9999999999999998 │
    │1.4999999999999998  -0.4999999999999999│
    └                                       ┘
    ランク

    行列のランクはrankメソッドで取得します。

    kaleidox> x.rank
    2

    出力

    Matrixオブジェクトの出力方法として以下の方法について見ていきます。

    • matrix-save関数
    • Table

    準備としてcity.csvに入っているデータをMatrix化したものを変数xに束縛します。

    kaleidox> setq x (matrix-load file:city.csv)
    Matrix[4x8]
    kaleidox> x
    Matrix[4x8]
    kaleidox> :show
    Matrix[4x8]
    ┌                                ┐
    │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│
    └                                ┘
    matrix-save関数

    Matrixオブジェクトはmatrix-save関数を使ってCSV形式でファイルに保存することができます。

    第1引数に保存するファイル名、第2引数にMatrixオブジェクトを指定します。

    kaleidox> matrix-save file:output.csv x
    t

    matrix-save関数で保存したCSVファイルoutput.csvには以下のCSVが格納されます。

    "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"
    Table

    Matrixオブジェクトのtableメソッドで行列データをTableオブジェクトに変換することできます。表のカラム名は1からの連番となります。

    kaleidox> x.table
    Table[4x8]
    kaleidox> :show:print
    ┏━━━━━━━━━┯━━━━━━━━━━┯━━━━┯━━━━━━┓
    ┃1        │2         │3   │4     ┃
    ┣━━━━━━━━━┿━━━━━━━━━━┿━━━━┿━━━━━━┫
    ┃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┃
    ┗━━━━━━━━━┷━━━━━━━━━━┷━━━━┷━━━━━━┛

    Tableオブジェクトを起点にMatrixオブジェクトによる行列演算の結果を各種応用に利用していくことができます。

    まとめ

    今回はKaleidoxで行列を扱うMatrixオブジェクトについて説明しました。

    Matrixの演算に加えて、CSVによる外部入出力、Tableオブジェクトとの連携を容易に行うことができます。モデル駆動開発の場合でも、BigDataやAIの応用を考えた場合、アクション言語ではドメインモデルと行列を併用してシームレスに連携できる必要があるはずです。Matrixオブジェクトはこのような応用で便利に使用できると思います。

    諸元

    • Kaleidox : 0.1.9
    気象データ

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

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