見出し画像

ビジネスをモデル化する ~ BridgePoint を使ってみよう

はじめに

最新の IT 技術を駆使したビジネスシステム構築においては、「ビジネスシステムにおける概念モデルの重要性」でも説明しているように、ビジネスモデルを厳密に定義する、概念モデリングが必須です。ビジネスが扱う様々な主題領域を元に正しく作られた概念モデルがあれば、変換による自動生成の技術を使って、IT を活用したビジネスシステムに必要な様々なソフトウェアを、コンピュータを使って、自動的に生み出すことも可能です。ソフトウェアを生成する仕組みを作るのは、ソフトウェア開発者の仕事ですが、ビジネスモデルを定義する作業は、ビジネスを主導する人の責務です。概念モデリングを通じて、ビジネスに関わる現実世界の様々なエンティティを抜け漏れなく理解したり、矛盾のないビジネスシナリオ、プロセスを作成できます。
概念モデリングを実践するには、

  • 概念モデルとは何か

  • 現実世界の様々なモノ・コトから、概念クラスや Relationship をどうやって抽出していくか?

を正しく理解し、各自のビジネスを対象に概念モデリングが可能なスキルを身につけなければなりませんが、概念モデルを描くためのツールも必須です。そのツールは概念モデルが描けるだけでなく、描いたモデルを元に様々なソフトウェアが生成できなければ意味がありません。逆に言えば、この様なツールが無ければ、概念モデリングによって生み出される価値は半減以下になってしまいます。
本稿で紹介する BridgePoint は、正にその役割を果たすツールの一つです。Apache 2、EPL というオープンソースライセンスで提供されているので無償で使えます。
繰り返しますが、概念モデリングは、ビジネスを主導する人達の責務です。ということはつまり、BridgePoint は、ソフトウェア開発者が使うツールというだけでなく、Excel や PowerPoint 等と同じように、ビジネスを主導する人達が使うツールでもあるということです。IT システムの開発・運用・保守を担当するソフトウェア開発者へのインプットとして、ビジネスサイドの人達が BridgePoint で厳密な概念モデルを作成し、変換による自動生成技術を使えば、「顧客が本当に必要だったもの」で紹介されている様な誤解や食い違いを、完全にとは言いませんが、大幅に回避することも可能になるでしょう。
とはいっても、BridgePoint というツールは、1990年代にソフトウェア開発者用のツールとして作られたものなので、ソフトウェア開発の専門知識がない人が使い始めるには、なかなかに高い障壁が立ちはだかっているのも事実だと思います。著者は、30年以上、ソフトウェア開発に携わってきた技術屋なので、初心者が困るポイントがよくわからないのですが、ソフトウェア開発の専門知識を持たない人達が BridgePoint を各自の PC にインストールして、概念モデルを描くための基本操作が行える様な解説を、頑張って書きたいと思っています。
ここまで読んで、やってみようかな…と思った方、是非挑戦してみてくださいね。
”概念モデルとは何か?” については、「Art of Conceptual Modeling」の最初の章の「概念情報モデル」を読んで頑張って理解をお願いします。
”概念モデルからのコード自動生成なんてほんとにできるの?”と思われる方も当然多いかと思います。本稿で解説する”概念モデリングと変換による自動生成”は、eXecutable and Translatable UML という方法論を元に著者の長年の経験でラップアップしたものです。この方法論を使って開発されたソフトウェアは過去、そして今も、実際に世の中で動いています。「概念モデリングチュートリアル集」でも、チュートリアルとして概念モデリングから実際に動くソフトウェアを生成する方法を解説しているので、ご参照ください。

前提条件

BridgePoint のインストールにはインターネットに接続された パソコンが必要です。想定しうるすべての機種、OS を想定して解説するのは無理なので、また、筆者が持っているコンピュータ機器環境は、Windows 11 と Linux マシンしかないので、ユーザー数を考えて、Windows 11 がインストールされたパソコンを前提に話を進めます。Mac ユーザーの皆さん、ごめんなさい。ソフトウェア開発ツールのインストールに慣れている方は、著者のお友達が公開している「BridgePoint のインストール手順」を参考にしてください。本稿が想定しているぷらttフォーム以外でのインストールもできるはずです。
本稿での説明は、

  • マウスやタッチ画面での基本的な操作はできる

  • ブラウザでネット上のサイトを開いたり、ファイルのダウンロードができる

  • Excel や PowerPoint は使ったことがある

ぐらいの経験を有している事を前提にさせていただきます。また、インストールしようとしているパソコンへのログインは、管理者権限を持ったユーザーで行ってください。Windows 11 のエディションはどれでも構いません。Windows パソコンを買った時のバンドル OS、Windows 10 からのアップグレードでも OK です。

インストール

BridgePoint を動かすために必要なソフトウェアをまずはインストールします。インストールするソフトウェアは、Open JDK という名前のミドルウェアです。詳しくない方は、おまじないだと思って、以下の手順で、インストールをお願いします。
まず、以下の URL を ブラウザで開きます。

  • https://adoptopenjdk.net/index.html

開くと、

Open JDK のダウンロード

と表示されるので、赤枠で囲んだ青いボタンを選択し、

CPU Architecture の選択

赤枠で囲んだ、”.msi” のボタンを選択すると、ダウンロードが開始されます。 完了するとダウンロードフォルダーに、OpenJDK11U-jdk_x64_windows_hotspot_….msi という名前のファイルが格納されるので、そのファイルをダブルクリックし、実行を開始します。
※ 「このファイルの発行元は信頼されていないため、安全でない可能性があります。」と表示された場合は、”保護を解除して開く”を選択して実行してください。
実行が開始されると、インストールウィザードが表示されるので、

Open JDK のインストール

の様に、最初の画面の右下の、”次へ”を選択後、

Set JAVA_HOME variable 

を選択して表示された画面で、”ローカルハードディスクにインストール”を選択してから、”次へ”を選択します。次の画面で右下の”インストール”を選択してインストールを行います。

日本語入力設定

現在リリースされている BridgePoint の Windows 版は残念ながら完全な日本語対応にはなっていません。概念クラスや特徴値の名前、Relationship のフレーズ等は日本語入力できるのですが、説明文などは日本語を入力すると文字化けします。現在開発側に修正を要求していますが、直るまでは、以下の設定を行って BridgePoint を使ってください。
※ 「IT システム開発の元なんだから英語で全部いいんじゃない?」というのは現実的ではないですね。
Windows Vista まではおなじみだったコントロールパネルを使って設定を行います。Windows 11 でのコントロールパネルの開き方は、以下の通りです。

日本語入力を可能にする設定

以下に、テキストでも設定方法を書いておきます。特に、最後の環境変数設定などは、スペルミスを防ぐため本文からのコピー&ペーストを行うと間違いが少なくて済みます。

  1. Windows 11 のタスクバーの虫眼鏡アイコンをクリック

  2. 上の”検索”で、”コントロールパネル”と入力し、図に示すようなアイコンが表示されたら、そのアイコンを選択

  3. 右上の検索窓に、"環境変数” と入力し、表示された”環境変数を編集”を選択

  4. 新規(N)…”を選択

  5. 表示されたダイアログの以下の項目にそれぞれ入力

    • 変数名(N):  JAVA_TOOL_OPTIONS

    • 変数値(V):   -Dfile.encoding="UTF-8"

  6. ”OK” をクリックして設定完了

以上で、日本語入力用の設定は完了です。

次に、BridgePoint をインストールします。

  • https://xtuml.org

をブラウザで開きます。

BridgePoint ダウンロード - Step 1.

右上の ”DOWNLOAD”を選択します。

BridgePoint ダウンロード - Step 2

Nightly Builds の ”Download here” を選択します。

BridgePoint ダウンロード - Step 3

”Windows 64-bit” を選択すると、org.xtuml.bp.product-win32.win32.x86_64.zip というファイルがダウンロードされます。ダウンロードが完了したら、ファイルエクスプローラ等でそのファイルを開き、中のBridgePoint という名前のフォルダー一式を、適当な場所に全てコピーします。

C: 直下にコピーした場合

図は、ZIP ファイルの中の BridgePoint フォルダーを丸ごと、C: 直下(ルートディレクトリ)にコピーした場合です。
これで、BridgePoint のインストールは完了です。ダウンロードした ZIPファイルは削除してかまいません。
コピーしたフォルダーの中に、bridgepoint.exe というファイル(拡張子の表示設定をしていない場合は、図のように bridgepoint とのみ表示)があり、ファイルエクスプローラでダブルクリックすると、BridgePoint を起動できます。


概念モデルを作成する

BridgePoint を最初に起動すると、以下の様な画面が表示されます。

Welcome 画面

Workbench をクリックして、作業開始です。まずは、概念モデルを作成するためのプロジェクトを作成します。これから数ステップは、新しく概念モデルを作成する場合の儀式ぐらいに覚えておいてください。

プロジェクトの作成

図のように、Model Explorer の上で、マウスを右クリックしてメニューを表示し、”New”を選択して、”xtUML Project”を選択します。

プロジェクト名の入力

”Project name” に適当な名前を入力し Finish を選択します。入力した名前のフォルダーアイコンを持つプロジェクトが Model Explorer で表示されるので、それを右クリックして、

Package の作成

New → Package と選択して、”domains” と入力します。出来上がった domains を右クリックして、

モデル対象のドメインを作成

New → Component → Component と選択し、概念モデルを作成する対象のドメインの名前を入力して、ドメインを作成します。
出来上がった domains(緑色のCのアイコン)を右クリックし、これまでと同じような方法で、New → Package と選択して、ドメインと同じ名前、もしくは、ドメインの一部を表す適当な言葉で Package を作成します。
Package が作成されたら、追加されたアイコンを選択します。

概念情報モデル作成の為の準備完了

画面が上のように変わります。薄い水色が、概念情報モデルを描いていくキャンバスになります。
ここまでが、概念情報モデルを作成する前段階のおまじない、あるいは、儀式となります。

概念情報モデルを作成する

概念情報モデルでは、概念クラス、概念クラスの特徴値、概念クラス間の Relationship を作成します。
”商品販売”を例にした、概念情報モデルチュートリアル」で解説している概念情報モデルを例にして、作成方法を説明していきます。

概念クラスを作成する

概念クラスの作成は、前節で作成したキャンバスの上で右クリックし、

概念クラスの作成

Add → Classes で class を選択し、概念クラス名を入力して作成します。日本語でも構いませんが、下の方の、Class Key Letters に英語名も入力しておきます。

※ 薄い水色のキャンバス上で右クリックして作成しないとキャンバス上に概念クラスの四角はキャンバス上に表示されないのでご注意ください。

BridgePoint では、定義した概念モデルの各要素に説明文を付与できます。吟味された言葉を使って作成された概念モデルは、モデル図だけでモデル作成者以外の人がほとんど誤解なく読み解けるものなのですが、全てをモデル図だけで伝えるのはなかなかに難しいものです。概念モデルで要素を定義するたびに、説明文を付与するのが良い習慣となります。Model Explorer 上で説明文を入力したい要素のアイコンを選択して、

説明文の追加

Properties の XXX Description(XXXの部分はそれぞれの要素によって変わります)の右側の Value の欄をクリックして、表示されたエディタで説明文を書いていきます。

次に、特徴値を追加します。”顧客”は、顧客ID、顧客名、住所という3つの特徴値を持っています。まずは、顧客IDです。

特徴値の定義

特徴値を追加したい概念クラスをキャンバス上で選択して、Add → Attribute と選択し、追加したい特徴値の名前を入力して追加します。追加した特徴値はキャンバス上の概念クラスに追加されて表示されます。
※ 特徴値の英語は property ですが、BridgePoint では同じ概念を attribute(属性)と呼んでいます。混乱しそうですが適宜読み替えてください。
同じ手順で、顧客名、住所を追加します。

3つの特徴値を追加

図を見ると、3つの特徴値のデータ型が "integer" つまり、整数値になっているのが見てとれます。顧客ID はそれぞれの顧客インスタンスを識別する一意の値を持った方でなければならないので、uniquie_id というデータ型への変更が、他の二つは文字列なので、string というデータ型への変更が必要です。

顧客ID のデータ型を uniquie_id に設定する

Model Explorer で ”顧客ID” を右クリックし、Set Type… を選択します。設定可能なデータ型の一覧が表示されるので、"unique_id"を選択して OK をクリックします。この方法で、顧客名、住所のデータ型を”string” に変更します。

データ型変更完了

前述のとおり、顧客ID は、顧客インスタンスの識別子なので、Model Explorer 上で、顧客ID を選択して、

識別子設定

Add to Identifier… を選択し、Finish を選択して設定します。
以上で、顧客 という概念クラス定義は完了です。

顧客 の定義完了

Relationship を作成する

顧客を例に説明した手順で、”商品” の概念クラスを作成しておきます。

Relationship 追加前の状態

この状態で、BridgePoint の画面の右側の Pallete の classes の下にある Association を選択して、カーソルアイコンが変化してから、二つの四角の間に線を引きます。

すると、Edit association ダイアログが表示されるので、Relationship の両端のフレーズと多重度を定義します。
左側に”顧客”がある最初の行は、”顧客”から見て、”商品”側のフレーズと多重度を、左側に”商品”がある二行目の行は、”商品”から見て、”顧客”側のフレーズと多重度を設定します。間違いやすいですが、”左から見た右の端”と覚えて正しい定義を行ってください。多重度は、

  • 0..1 Conditionally, One

  • 1  Unconditionally, One

  • *  Conditionally, Many

  • 1..* Unconditionally, Many

と対応付けられます。この設定で、

binary relationship

二つの概念クラス間の Relationship が出来上がります。

Associative Class を定義する

次に、”注文”という名前の概念クラスと、注文ID(識別子)、個数、金額の、3つの特徴値を既に解説済みの方法で追加します。

”注文”という名前の概念クラスを追加

追加した概念クラスは、関連クラスなので、その定義を行います。Pallete の Classes の下の Associative Link を選択し、

Associative Class を定義

”注文”概念クラスから R1 の線に向けてマウスで線を描きます。

定義完了

これで、”注文”概念クラスが、Relationship ”R1”の関連クラスであるという定義ができました。単なるスケッチのモデルならこれで十分ですが、この三つの概念クラスのインスタンスを表で表現する場合、ある注文インスタンスが R1 でリンクが張られている顧客インスタンスと商品インスタンスがどれであるかを示す特徴値(参照特徴値)が無いので、この概念情報モデルは不完全です。Relationship を Formalizeすることによって、参照特徴値を追加します。
”R1”の線を右クリックして、

Relationship を Formalize

このケースではこのまま Finish を選択して定義を終えます。

Formalize 完了

結果として、”注文”概念クラスに、{I2, R1} が添付された二つの特徴値が追加されます。
“商品販売”を例にした、概念モデルチュートリアル」の多重度の検討では、R1 の両端の多重度を意図的に変えた16種類を検討していますが、R1 の線を右クリックして、

Relationship の多重度を編集

Edit association … を選択することによって変更が簡単に可能です。また、一旦定義した Relationship の多重度やフレーズを変更する場合にも、この作業を行います。

次は、「“商品販売”を例にした、概念モデルチュートリアル」の図6を例に、まだ説明していない事項の解説を行っていきます。
まず、顧客、商品仕様、注文の三つの概念クラスとR1 の Relationship ですが、これらは、全てこれまで説明した方法で定義が可能です。

図6 の一部

この状態から説明を開始します。

Super Sub Relationship を定義する

次に、”一品物商品仕様” と ”在庫管理商品仕様” という名前の二つの概念クラスを追加します。追加方法は既に解説済みなので省略します。

2つの概念クラスを追加

先ず、”商品仕様”を Super とする Relationship を作成します。Pallete で、Supertype を選択し、

Super 側の定義

”商品仕様”の四角の側から、下に向かってちょっとだけ線を引きます。
すると、底辺から線が伸びている三角形が追加されます。

Super Sub Relationship R2 が追加

※ 図6 では R6 になっていますが、ご容赦ください。
次に、一品物商品仕様を R2 の Sub として定義します。
Pallete で Subtype を選択し、

Sub 側の定義

Sub 側の概念クラスとしたい側の四角から、R2 の線に向けて線を引きます。すると、Edit association … ダイアログが表示されるので、Formalized に チェックを入れてから、Finish を選択します。
この操作で、Sub 側の定義が出来上がるとともに、Sub 側の概念クラスに、識別子の特徴値も加わります。同様な操作を”在庫管理商品仕様” にも行った図を以下に示します。

Super Sub Relationship R2 の定義完了

※ デフォルトでは、R2 の Sub 側の線は直線ですが、右クリックして表示されるコンテキストメニューの ”Routing” 設定で、上の図の様な線の描画に変更しています。これは、各自の趣味の問題なのでそのままでも構いません。
※ 在庫管理商品仕様の 特徴値の並びは、Model Explorer 側で、”在庫数”を選択した時に表示されるコンテキストメニューで ”Move Down” を選択することにより変更しています。

以上で、基本的な操作の説明は終わりです。これまで説明してきた操作方法で、図6を完成させます。

とりあえず追加

変更点は、

  • ”商品”、”在庫商品”という二つの概念クラスを追加

  • R3 と R4 の追加と Formalize

  • 定義済みだった概念クラスのキーレターの変更

です。この段階ではまだ微妙に定義が不足している部分があります。足りない部分を追加していく手順を解説していきます。

適切なデータ型

現行の概念情報モデルでは、金額や単価が、単に integer となっていますが、モデル化対象の主題領域の語彙としては、通貨単位の”円”がふさわしいでしょう。他に、”顧客” の ”顧客名”や”住所”も、単なる string であるのも微妙です。ここでは、金額、単価に絞って作業方法を説明します。
まず、domains の下の 商品販売 (Component)の直下に、”datatype"という名前の Package を追加します。追加方法は前の方で説明しているので振り返ってください。

ユーザー定義データ型を定義するための Package 作成

作成した datatypes package を右クリックして、New → Types → User DataType を選択します。
名前を入力するダイアログが表示されるので、”円” と入力します。モデルエクスプローラ上で追加された ”円”を右クリックして表示されたコンテキストメニューで、Set Types… を選択し、型が integer になっているか確認し、異なる基本データ型の場合は、integer に変更します。
これで、”円”というユーザー定義データ型が使えるようになるので、該当する特徴値の型を変更します。
次は、”在庫商品” の ”仕入れ日”という特徴値のデータ型を見てみます。 integer になっています。日付は、例えば、2000年1月1日から数えて何日目といったような表現であれば、ぎりぎり許せる範囲のデータ型ではありますが、やはり、日付や日時を意味するデータ型の方がふさわしいでしょう。
日付や時間に関しては、BridgePoint のサンプルとして提供されている Time というパッケージに必要なデータ型が定義されているので、そちらを使います。
先ず、先ほど説明した、datatypes パッケージと同じ階層に、”External Entities” という名前で package を追加して、一旦、BridgePoint を終了します。
次に、ブラウザで 

  • https://github.com/kae-made/artifacts-laundromat-in-hotel-tutorial

を開き、緑色の ”Code”ボタンを選択し、Download ZIP をクリックします。ダウンロードした ZIPファイルを解凍し、その中の、model フォルダーの下の LaundromantInHotel フォルダーを、BridgePoint の workspace にそのままコピーします。BridgePoint を再度起動すると、ConceptualModeling と同じ階層に、LaundromantInHotel というプロジェクトが現れます。この中の components → LaundromantInHotel → External Entities の Time という component を選択して右クリックし、Copy を選択し、商品販売 component の下の、External Entities package に Paste します。
これで、Time package で定義されているデータ型が利用可能になるので、"在庫商品” 概念クラスの ”仕入れ日”を Model Explorer で右クリックして、Set Type… を選択して、timestamp にデータ型を変更します。

仕入れ日のデータ型を timestamp に変更する

以上で、データ型の説明は終わりにします。

計算可能な特徴値

さて、図6をよーく見ると、”在庫管理商品仕様”の特徴値の”在庫数”には"(M)"がついているのが見て取れます。これは、この特徴値の値が、概念情報モデルの定義から自動的に計算可能な値であることを意味しています。具体的には、この概念クラスのインスタンスの ”在庫数”は、そのインスタンスに R5 でリンクされた ”在庫商品” のインスタンス群(多重度が ’*’ なので0~複数)の数である、ということです。
この事実を、BridgePoint で定義するには、まず、Model Explorer で、”在庫数”を右クリックして、Set as Derived Attribute を選択します。

計算可能な特徴値の厳密な定義

すると Properties 編集 View に、図の様な Action Semantics Field という項目が現れるので、概念モデルの振舞を記述する Object Action Language を使って 

SELECT MANY inventoryProducts RELATED BY Self->IP[R4.'現品'];
Self.在庫数 = CARDINALITY inventoryProducts;

”在庫数” 特徴値の値の計算方法が厳密に定義できます。
”在庫数” 特徴値の右側に{M} が追加されて、図6の概念情報モデルは完成です。※ 在庫商品の特徴値が足りなかったことに気づいたので追加してます。

全てを網羅した概念情報モデル

概念クラスの読み方

さて、BridgePoint で概念情報モデルを描いていく方法を説明してきましたが、作成したモデルの理解の仕方を念のため、ここで説明しておきます。
それぞれの四角は、概念クラスです。例えば、”顧客”という名前が付いた四角は、それぞれの顧客ではなく、”顧客というもの”という分類を表しています。そして、「”顧客というもの”は、顧客ID、顧客名、住所の3つのデータをそれぞれ必ず持っていますよ」と表明しています。この”顧客というもの”を、概念クラス、それぞれの顧客を概念インスタンスと呼んでいます。例えば、北条義時さん、梶原景時さん、和田義盛さんという名前の3人の顧客がいるとすると、この三人は”顧客”という概念クラスの、それぞれの名前が"顧客名"になり、加えて、三人を識別するための”顧客ID”と”住所”というデータをそれぞれ持っている概念インスタンスであることを意味します。他の四角も同様です。例えば、”商品”という名前が付いた四角は、”商品というもの”を表明する概念クラスであり、具体的な商品をたとえば、名刀童子切、義経愛用赤糸縅大鎧、だとすれば、それぞれが、”商品”という外苑情報クラスの概念インスタンスとなり、データとしては、それぞれ、商品仕様ID というデータを持つことになります。また、”商品”と”一品物商品仕様”という二つの概念クラスの間に、R4 という Relationship が定義されています。この Relationship の両端は、多重度が 1 となっているので、”商品”の概念インスタンスである、名刀童子切、義経愛用赤糸縅大鎧という二つの概念インスタンスがあれば、「それぞれに対応する各一つづつの、”一品物商品仕様”の概念インスタンスが必ずあるよ」という表明です。
更に読者の理解を確実にするためにもう少し続けますね。今度は、”在庫管理商品仕様”を取り上げます。この概念クラスの概念インスタンスとして、かわらけ、と、弓矢、があるとします。この二つは、実際に売り物用の在庫として存在する、かわらけ、弓矢、ではなく、カタログ的な商品名を表しています。実際の売り物用の在庫として存在する、かわらけ、弓矢、は、R3 という Relationship でつながった ”在庫商品”という概念クラスの概念インスタンスです。例えば、かわらけが3000枚、弓矢が10000本、在庫としてある場合、

概念クラスと概念インスタンス、及び、Relationship とリンク

図の右側のような様を左の様にモデル化しています。一つの仕様に対して現物が複数あるので、R3の在庫商品側の多重度は、*(0以上)と表明されていて、在庫管理商品仕様側のだじゅうどは、1 と表明されています。誤解を避けるために、概念情報モデル上で概念情報モデル間に張られた線を Relationship と呼び、それを雛形に概念インスタンス間に張られたつながりを、リンク と呼んで区別します。弓矢の場合、弓矢のカタログ仕様に対して、10000本の在庫があるので、R3 のリンクが10000個あることになります。逆に言えば、R3 のリンクの数を数えればカタログ仕様に対する在庫が現在いくつあるかを数えることができます。数えた数は、在庫管理製品仕様の在庫数に一致します。
更に、”一品物商品仕様”と”在庫管理製品仕様”の二つの四角は、R2 という Relationship で、”商品仕様”という四角とつながっています。これは、「”商品仕様”という概念クラスの概念インスタンスが一つあった場合、”一品物商品仕様”か、”在庫管理製品仕様” のどちらかですよ」という表明です。

Super - Sub Relationship

例として、2つの一品物商品仕様と2つの在庫管理商品仕様が出てきましたが、それぞれに対応する商品仕様の概念インスタンスがあって、それぞれ一つづつ、R2 のリンクでで、「どちらか」という状況を表すことになります。
最後に、”注文”という名前の四角は、”注文というもの”という分類で、実際のそれぞれの現実の注文が、この概念クラスの概念インスタンスであり、全ての注文の概念インスタンスは、注文ID、個数、金額、顧客ID、商品仕様ID、発注日というデータをそれぞれ持っているわけです。また、R1 という Relationship が定義されているので、それぞれの注文は、ただ一つの顧客の概念インスタンスとただ一つの商品仕様の概念インスタンスとリンクされている事を意味しています。もう少し優しく言うと、「注文はただ一人の顧客が、ある一つの商品仕様のみに対して購入予約する」と、このモデルは表明している事になります。R1 についてもう少し詳しく見てみます。両端の多重度が * (0以上)と定義されているので、一人の顧客は、同じ商品仕様に対して複数同時に注文を行うことはできませんが、異なる商品仕様に対しては同時に複数注文が可能であり、一つの商品仕様に対して、複数の顧客からの同時の購入予約ができると表明されている事になります。多重度が違うと、ビジネスの様相が大きく変わります。その辺り、「”商品販売”を例にした、概念モデルチュートリアル」の”多重度の検討”で詳しく解説しているので、読んでみてください。
誤解のないように付け加えておきますが、ここで取り上げている商品販売の概念情報モデルは、著者が「商品販売というビジネスはこうあるべきだ」と主張するものではなく、あくまでも、説明用に簡素化したものであることにご留意ください。「Art of Conceptual Modeling」の解説を理解して、各自のビジネスをモデル化してください。

概念インスタンスの作成

前のセクションで、分類としての”概念クラス”と、それを雛形にした実際に存在する概念インスタンスの話をしました。BridgePoint は、概念情報モデルの図が描けるだけの単なるお絵描きツールではなく、ツール上で概念インスタンス群を作成して、実際にビジネスがどのように動いていくのか、シミュレーションが可能な Verifier の機能を持っています。この機能の活用は、見方によっては、既にプログラマーの仕事の領域に踏み込んでしまうようにも思えますが、昔の Excel のマクロによる機能拡張(結構以前から非推奨ですが…)ぐらいのレベルとも考えられるので、プログラミング未経験者でも使えるよう意識しながら、ビジネスの流れをモデル化する概念振舞モデルとそれを使ったシミュレーションを BridgePoint で行うための基本操作を解説していきます。
先ずは、概念インスタンスを作成する方法を解説します。
Model Explorer で、”商品販売”パッケージを右クリックし、New → Function を選択し、CreateInstance という名前で Function(「Art of Conceptual Modeling」ではドメインオペレーションと呼んでいます)を作成します。

Domain Operation の作成

Model Explorer 上の ”商品販売” パッケージの直下に CreateInstance というアイコンが追加されるので、それをダブルクリックします。
エディタが開くので、以下の文を入力します。

CREATE OBJECT INSTANCE customer1 OF C;
customer1.顧客名 = "北条義時";
customer1.住所 = "鎌倉市西御門2‐5";

CREATE OBJECT INSTANCE customer2 OF C;
customer2.顧客名 = "梶原景時";
customer2.住所 = "高座郡寒川町一之宮8-6-6";

CREATE OBJECT INSTANCE customer3 OF C;
customer3.顧客名 = "和田義盛";
customer3.住所 = "三浦市初声町和田";

プログラムっぽいのが出てきたぁ~、と思った方、しばしのご辛抱を。
これは、BridgePoint で使える Object Action Language(OAL)というユーザーフレンドリーな、概念情報モデルを操作するための言語で書かれています。ある概念クラスの概念インスタンスを作成する場合には、

  • CREATE OBJECT INSTANCE インスタンス変数名 OF 概念クラスのキーレター ;

と書きます。前セクションで例に挙げた3人の顧客を例にしています。インスタンス変数名は、作成した概念インスタンスを後の行で参照するための入れ物です。概念クラスのキーレターは、概念クラスを定義した時に入力したキーレターです。顧客のキーレターは、C なので、”顧客”という概念クラスの概念インスタンスを作成することになります。文の最後には、”;” をつけて文の終わりであることを示します。
インスタンス変数名 に ”.”をつけた後に、特徴値の名前を続けると、その名前の特徴値の更新や参照ができます。例では、customer1、customer2、customer3 という3人分の”顧客”の概念インスタンスを作成し、それぞれの、顧客名、住所を更新しています。”顧客” には、他に、顧客ID という特徴値がありますが、識別子指定されているので、BridgePoint 側が Verifier で起動したときに自動的に異なる値を BridgePoint が設定してくれます。
”CREATE OBJECT INSTANCE ~ OF ~ ;” と同じ形式で、前のセクションで例に挙げた商品仕様関連の概念インスタンスを作成します。前のセクションでは、かわらけが3000枚、弓矢が10000本としていましたが、多重度は、1、0..1、1..*、* の4種類しかなく、多重度が1より大きい場合は、2 も 3 も 3000 もモデル的には変わらない(3 で正しくビジネスの流れが表現できているのなら3000でも正しい)ので、少ない数にしています。

CREATE OBJECT INSTANCE ps1 of PS;
ps1.商品名 = "かわらけ";
ps1.単価 = 100;
CREATE OBJECT INSTANCE ips1 of IPS;
RELATE ps1 to ips1 ACROSS R2;
かわらけの在庫数 = 3;
index1 = 0;
WHILE index1 < かわらけの在庫数
	CREATE OBJECT INSTANCE ip of IP;
	ip.仕入れ日 = TIM::create_date( day:22, hour:10, minute:0, month:7, second:0, year:2022 );
	RELATE ips1 TO ip ACROSS R3;
	index1 = index1 + 1;
END WHILE;

CREATE OBJECT INSTANCE ps2 of PS;
ps2.商品名 = "弓矢";
ps2.単価 = 2500;
CREATE OBJECT INSTANCE ips2 of IPS;
弓矢の在庫数 = 10;
index2 = 0;
WHILE index2 < 弓矢の在庫数
	CREATE OBJECT INSTANCE ip OF IP;
	ip.仕入れ日 = TIM::create_date( day:21, hour:14, minute:0, month:6, second:0, year:2022 );
	RELATE ips1 TO ip ACROSS R3;
	index2 = index2 + 1;
END WHILE; 

ここでいくつか新しいキーワードが出てきたので、順に説明していきます。
まず、

  • RELATE インスタンス変数名1 TO インスタンス変数名2 ACROSS Relationship の名前 ;

これは、「インスタンス変数名1 が指す概念インスタンスと、インスタンス変数名2 が指す概念インスタンスの間に Relationship の名前 で指定された Relationship のリンクを結ぶ」という意味です。例に挙げたかわらけでは、ps1 が”商品仕様”の概念インスタンスで、ips1 が”在庫管理商品仕様” で、R2 のリンクを作っています。
次に、

  • WHILE 条件文 実行文ブロック END WHILE ;

です。これは、条件文で書いている条件が成り立っている間、実行文ブロックで書かれているアクションの実行を繰り返すという意味です。河原家の例では、この前に、作りたい”在庫商品”の概念インスタンスの数を、かわらけの在庫数”という変数で3 に設定しています。index1 は、何番目の概念インスタンスを作っているのかを保持する変数です。実行文ブロックでは、”在庫商品”の概念インスタンスを作成して、ips1 と R3 のリンクを作成しています。実行文ブロックの最後で、index1 に 1 を足しています。実行文ブロックを "かわらけの在庫数"回実行すると、条件文が満たされなくなるので、この実行ループは完了します。
例に挙げたアクション記述では、弓矢についても同様なパターンで10個、概念インスタンスを作成して R3 のリンクを張っています。

WHILE ~ END WHILE ; は有限回で終了するようにアクションを記述しなければなりません。無限に続く様なアクションを書いた場合、それは、ビジネスシナリオの中に将棋の千日手の様な、永遠に続く無意味な繰り返しがあることを意味します。

補足情報

せっかく、アクションを書いたので、さっそく実際に動かしてみましょう。

概念モデルを動かす

Model Explorer で、ConceptualModeling アイコンを右クリックし、Launch Verifier を選択します。

Launch Verifier

1回目は、図の様な設定画面が表示されるので、ConceptualModeling にチェックを入れて、”Log model execution activity" にもチェックを入れて、"Debug" をクリックします。

Session Explorer と Breakpoint の設定

Model Explorer が表示された場所に、Session Explorer という View が表示されます。CreateInstances を選択して、アクション記述 Editor を開き、図で示している一行目の左横のグレイの帯をダブルクリックすると、薄緑色の丸が表示されます。これは、ブレークポイントと言って、「実行時にそこで止まれ」という指示になります。
これで、CreateInstances オペレーションを実行する準備が整いました。Session Explorer の CreateInstances を右クリックして、”Execute”を選択します。

Execute operation

※ 何も起こらない場合は、Debug View が表示されているか確認してください。表示されていない場合は、メニューの Window → Show View → Debug を選択すれば表示できます。
実行が開始され、次にどの行を実行するかを示す矢印が表示されます。1行目にブレークポイントが設定されているので、1行目で停止した状態になります。

Debugging & Step by Step Execution

図の下に描いてあるメニューに表示された、内側の赤枠で示したアイコンをクリックすると、一行づつアクションが実行されていきます。

show instances

図は、5行目まで実行した状態を示しています。Variables View に作成した概念インスタンスが順次追加されて表示されていきます。
※ 残念ながら Visual Studio の様に変数にカーソルを持っていくとその変数の値が表示されるような機能はついていません。
CreateInstances の最後の行まで実行すると、Verifier は待ちの状態になります。
ここで、CreateInstances を追加したのと同じ方法で、TestQuery というオペレーションを追加(商品販売パッケージを右クリック → New → Function)します。アクション記述 Editor が開いたら、

SELECT MANY productSpecSet FROM INSTANCES OF PS;
FOR EACH productSpec IN productSpecSet
	商品名 = productSpec.商品名;
	単価 = productSpec.単価;
	
	SELECT ONE inventryProductSpec RELATED BY productSpec->IPS[R2];
	SELECT ONE oneProductSpec RELATED BY productSpec->OIPS[R2];
	IF NOT_EMPTY inventryProductSpec
		SELECT MANY inventrySet RELATED BY inventryProductSpec->IP[R3.'現品'];
		在庫数 = CARDINALITY inventrySet;
	ELSE
		// oneProductSpec is not empty
		SELECT ONE oneProduct RELATED BY oneProductSpec->P[R4.'現品'];
	END IF;
END FOR;

と入力して保存してオペレーションを追加します。各行の解説は、とりあえずおいておいて、CreateInstances の時と同様、1行目にブレークポイントを設定し、Session Exproler で TestQuery を右クリックして、Execute を選択します。

Executing TestQuery

図は、5行目までを実行したところです。Variables View に変数の値が表示され、CreateInstances で作成した概念インスタンスやその特徴値の値、リンクなどが保持されているのが確認できます。
新しく出てきたキーワードを解説します。

  • SELECT MANY インスタンス群変数名 FROM INSTANCES OF 概念クラスのキーワード ;

これは、既に存在している全ての概念クラスのインスタンスを取り出して、インスタンス群変数名 に格納するということです。TestQuery の 1行目は、PS つまり、商品仕様の概念インスタンスを全て取り出しています。CreateInstances では、二つの概念インスタンスを作っているので、それらが変数に格納されます。

  • FOR EACH インスタンス変数名 IN インスタンス群変数名 実行ブロック END FOR ;

インスタンス群変数名 に格納された概念インスタンスを取り出して、インスタンス変数名 の変数に格納して、それぞれの変数が指している 概念インスタンスを対象に実行ブロックのアクションが実行されます。

インスタンス群変数名の変数から取り出される概念インスタンスの順番は不定です。格納されている概念インスタンスを、I1、I2、I3 とすると、I1、I2、I3 の場合もあれば、I3、I1、I2 、などなどもあれば、全てが同時に事項ブロックのアクションが実行されることもあると思って、実行ブロックのアクションを記述しなければなりません。

補足コメント
  • SELECT ONE リンクされたインスタンス変数名 RELATED BY 元のインスタンス変数名 -> 概念クラスのキーレター [ Relationship の名前 ] ;

前に RELATE キーワードを説明しましたが、ある概念インスタンス(元のインスタンス変数名)に Relationship (Relationship の名前)でリンクが張られた概念クラス(概念クラスのキーレター)の概念インスタンスを リンクされたインスタンス変数名の変数に格納します。TestQuery の6行目と7行目は、R2 の Super ‐ Sub Relationship の Super 側から Sub 側にたどっています。Super 側から見た R2 の多重度は 0..1 なので、SELECT の次が ONE になっています。
TestQuery の9行目には、ONE の部分が MANY に置き換わったアクションが書かれています。これは、”在庫管理商品仕様”から見て R3 の”在庫商品”側の多重度が、'*' つまり 0以上の多数になっているので、MANY になっています。investrySet には、かわらけ の場合は、かわらけの在庫商品が、弓矢の場合は、弓矢の雑魚商品の概念インスタンスが格納されます。また、10行目の様に、インスタンス群変数名 の前に CARDINALITY をつけると、その変数に格納されている概念インスタンスの数を取得できます。この行で算出した在庫数と、その時の inventryProductSpec.在庫数 の値は一致しているはずです。

  • IF 条件文 条件文が満たされる場合の実行ブロック ELSE 条件文が満たされない場合の実行ブロック END IF ;

いわゆる条件分岐があるアクションを記述するためのキーワードです。条件文の状況によって、実行されるブロックが変わります。ELSE の前に、

  • ELSE IF 別の条件文 別の条件文が満たされる場合の実行ブロック

を追加して、より複雑な条件分岐を記述することもできます。TestQuery の 8行目の条件文では、

  • NOT_EMPTY インスタンス(群)変数名

となっていますが、NOT_EMPTY をつけると、インスタンス(群)変数名 が空でない場合に、条件を満たす事になります。NOT_EMPTY の代わりに、EMPTY をつけると、空の場合に条件が満たされます。

	SELECT ONE inventryProductSpec RELATED BY productSpec->IPS[R2];
	SELECT ONE oneProductSpec RELATED BY productSpec->OIPS[R2];

ですが、この二行は、R2 の Super 側の”商品仕様”の概念インスタンスは、”在庫管理商品仕様(IPS)”か、”一品物商品仕様(OIPS)”のどちらかなので、RELATED BY キーワードで辿ると、前者の場合は、inventryProductSpec に該当する”在庫管理商品仕様(IPS)”の概念インスタンスを指す値がせっとされ、oneProductSpec には該当する概念インスタンスが無いので、空になるわけです。後者の場合は、セットされる変数と空になる変数が逆になります。

状態モデルを作成する

次は、「”商品販売”を例にした、概念モデルチュートリアル」の図10で解説している状態モデルの作成を行います。
商品販売の概念情報モデルを開いて、”注文”を選択、右クリックで、

Add Instance State Machine

Add → Instance State Machine と選択します。”注文”に ”current_state:state<State_Model>”という名前の特徴値が追加されたことを確認し、”注文”をダブルクリックすると、状態モデルを描くための空色のエディタが開きます。
どこでもよいので、状態モデル Editor で右クリックし、New → State を選択し、

Create State

”引当て待ち”と入力して、”OK”をクリックすると、状態が追加されます。
同じ方法で、

  • 決済待ち

  • 配送待ち

  • 注文処理完了

という3つの状態を追加します。

4つの状態を定義

次にイベントを定義します。状態モデル Editor の水色の下地のどこでもよいので、右クリックし、Add → Event を選択します。名前を入力するダイアログが表示されるので、”注文発生”と入力し、イベントを作成します。
同じ方法で、

  • 在庫引当完了

  • 決済完了

  • 配送完了

と、全部で4つのイベントを作成します。この段階で Model Explorer で確認すると、

作成された状態とイベント

の様に、注文 → Instance State Machine の下に追加した状態群とイベント群が表示されているのが確認できます。4つのイベントのうち、注文発生だけは、単に事象が発生しました、というだけでなく、注文を構成するための付加情報が必要なので、Model Explorer の ”注文発生”イベントを右クリックし、New → Parameter で必要な付加情報を運ぶ、以下の変数を追加していきます。また、特徴値のデータ型の設定と同様な方法で、データ型も適切な型を設定します。

  • 顧客ID ‐ どの顧客からの注文か、を示す。型は unique_id

  • 商品仕様ID - どの商品仕様への注文か、を示す。型は unique_id

  • 個数 - 購入したい商品の数。 方は integer

イベントの定義が終わったら、状態遷移を定義していきます。まず、”引当て待ち”状態への遷移です。この遷移は、”注文発生”というイベントが発生した時に”注文”の概念インスタンスが生成するという遷移です。なので、Palletteで、”Creation Transition”を選択してから

Define Creation Transition

マウスで、水色のキャンバスから”引当て待ち”に向かって線を引いて定義します。引いた線を選択して、右クリックして、”Assign Event…”を選択すると、定義済みのイベントから選択するダイアログが表示されるので、"O1:注文発生”を選択します。
次に、”引当て待ち” → ”決済待ち”の遷移を追加します。Palletteの Transition を選択して、遷移元(引当て待ち)から遷移先(決済待ち)に線を引けば、遷移が追加されます。イベントは”O2:在庫引当完了” を割り当てます。同じ方法で、他の遷移も定義していきます。

遷移の定義完成

”4. 注文処理完了”は、注文で必要なアクションが全て終わって消えていく状態なので、この状態の Properteis で、

Set final state

”Final State Indicator” の値を ”Final State”に変更します。
これで、状態モデルの、状態、イベント、遷移の定義ができました。以降、それぞれの状態のエントリアクションを書きながら、Object Action Language の残りのキーワードを説明していきます。

状態のエントリアクション記述

まず、”1. 引当て待ち" です。ここでは、発生したイベントが運んでくる、顧客ID、商品仕様IDを使って該当する”顧客”、”商品仕様”それぞれの概念インスタンスを見つけて、R1 のリンクを張ります。在庫数を確認し、在庫数がイベントが運んできた個数より多ければ、引当て完了とし、決済待ち状態になります。

SELF.個数 = rcvd_evt.個数;
SELECT ANY productSpec FROM INSTANCES OF PS WHERE SELECTED.商品仕様ID == rcvd_evt.商品仕様ID;
SELECT ANY customer FROM INSTANCES OF C WHERE SELECTED.顧客ID == rcvd_evt.顧客ID;
RELATE customer TO productSpec ACROSS R1 USING SELF;
SELECT ONE inventryProductSpec RELATED BY productSpec->IPS[R2];
SELECT ONE oneProductSpec RELATED BY productSpec->OIPS[R2];
enough = FALSE;
IF NOT_EMPTY inventryProductSpec
	IF inventryProductSpec.在庫数 >= rcvd_evt.個数
		enough = TRUE;
	END IF;
ELSE
	IF rcvd_evt.個数 == 1
		ehough = TRUE;
	END IF;
END IF;
IF enough
		GENERATE O2:在庫引当完了 TO SELF;
END IF;

※ 発注日の設定は省略してます。
SELF は、この状態機械(状態モデルを雛形にしたそれぞれの概念インスタンスの状態マシン)を持つ概念インスタンスのことです。”注文”という概念クラスは、”個数”という名前の特徴値を持っていたことを思い出してください。rcvd_evt は、このエントリアクションの実行のきっかけとなる状態遷移を引き起こしたイベント(このケースでは、”注文発生”イベント)を意味します。イベントが情報を運ぶ場合は、'.' に続いて、そのパラメータの名前を書くことにより、運ばれてきた値を参照できます。

  • SELECT ANY インスタンス変数 FROM INSTANCES OF 概念クラスのキーレター WHERE SELECTED.特徴値 論理比較 ;

この形式は、概念クラスのキーレターで指定された概念クラスの概念インスタンスのうち、特徴値の値が論理比較の内容を満たすもののうち、どれか一つを取り出してその参照をインスタンス変数に格納します。
ANY の部分を MANY に変えると、条件に合致する概念インスタンスを全て取り出すこともできます。また、WHERE 以降は複数の特徴値の比較や、もっと複雑な論理式にもできます。

  • RELATE 一方のインスタンス変数 TO 他方のインスタンス変数 ACROSS Relationship の名前 USING 関連インスタンス変数 ;

R1 は、Associative 概念クラスを持つ Relationship なので、USINGキーワードで Associative のインスタンスを指定します。

  • GENERATE 概念クラスのキーレター イベント番号 : イベント名 TO 送信先のインスタンス変数 ;

送信先のインスタンス変数で指定された概念インスタンスに対して、概念クラスのキーレター イベント番号 : イベント名 で指定されたイベントを発生します。イベントの指定は、”: イベント名" の部分の省略も可能です。18行目の例では、送信先が SELF となっているので、送信した状態機械自身が受信することになります。
ちょっと横道にそれますが、例の”O1:注文発生”イベントを発生させるドメインオペレーション(Function)を、CreateOrder という名前で用意する場合は、

found = false;
SELECT ANY customer FROM INSTANCES OF C WHERE SELECTED.顧客ID == param.顧客ID;
SELECT ANY productSpec FROM INSTANCES OF PS WHERE SELECTED.商品仕様ID == param.商品仕様ID;
IF NOT_EMPTY customer AND NOT_EMPTY productSpec
	found = TRUE;
	GENERATE O1:注文発生(顧客ID: param.顧客ID, 商品仕様ID:param.商品仕様ID, 個数:param.個数) TO O CREATOR;
END IF;
RETURN found;

の様なアクションになります。6行目は、GENERATE キーワードを使った書き方の一つの例です。() 内の記述はイベントが運ぶ情報の指定、TO 以降の最後の CREATOR は、”O1:注文発生”が生成イベントであり特定の概念インスタンスが送付先ではない事を明示します。

次に、”2. 決済待ち” のアクションです。

SELECT ONE customer RELATED BY SELF->C[R1.'発注者'];
SELECT ONE productSpec RELATED BY SELF->PS[R1.'購入予約'];
SELF.金額 = SELF.個数 * productSpec.単価;
customer.決済要求( 注文ID:SELF.注文ID, 代金:SELF.金額 );

この状態は、商品の引当は完了しているので、R1 のリンクを辿って”顧客”、”商品仕様”の概念インスタンスを持ってきて、”注文”の金額を確定し、顧客に対して、決済要求を行っています。
”customer.決済要求”は、”顧客”という概念クラスのオペレーションです。このアクション記述を行う前に、Model Explorer で”顧客” を選択して右クリックし、New → Operation で追加します。出来上がった”決済要求”オペレーションを更に選択し、ドメインオペレーション(Function)に引数を追加する方法と同じように、New → Parameter で、”注文ID:unique_id”、”代金:円”、を追加しておくと、アクション記述で利用できるようになります。

概念モデリングでは、現実のビジネスシステムにおいて、どんな仕組みで決済要求が現実世界の顧客に届くのかという問題は、商品販売という主題領域外の事項ということで、モデル化対象外という立場をとります。仕組みの問題は、システムを開発するソフトウェア技術者や人間工学の専門家が解決すべき主題領域です。
概念モデリングでは、この様なドメイン(主題領域)の区別と割り切りができるかどうかがスキルアップできるかどうかのキーとなります。

補足コメント

「あれ?”1. 引当て待ち” 状態では、在庫が要求された個数より少なかった場合にどうするか、何も書いてない?」と思われた方、半分正解、半分間違いです。在庫数が足りない場合は、そのまま、”1.引当て待ち”状態にとどまります。そして、他の誰かから、"O2:在庫引当完了" イベントが送られてきたら遷移が発生し、”2. 決済待ち” 状態のエントリアクションが実行されて状態が確定します。あくまでも参考として、ですが、ある在庫管理商品仕様の商品が納品された時に在庫引当待ちの”注文”の概念インスタンスに対して引当てを知らせるイベントを送信するドメインオペレーション(Function)のアクション(InventryGoodsDelivered)を紹介しておきます。

SELECT ANY inventryProductSpec FROM INSTANCES OF IPS WHERE SELECTED.商品仕様ID == param.商品仕様ID;
IF NOT_EMPTY inventryProductSpec
	index = 0;
	WHILE index < param.納品数;
		CREATE object instance ip OF IP;
		RELATE ip TO inventryProductSpec ACROSS R3;
	END WHILE;
	SELECT ANY order RELATED BY inventryProductSpec->PS[R2]->O[R1] WHERE SELECTED.個数 < inventryProductSpec.在庫数;
	IF NOT_EMPTY order
		GENERATE O2:在庫引当完了 TO order;
	END IF;
END IF;

新しく表れた文法がいくつかありますが、もう説明を加えなくても理解できると思われるので、説明は省略します。

"3. 配送待ち”のエントリアクションは省略(BridgePoint の使い方の解説という本稿の目的にかなう内容はありません)して、”4. 注文処理完了”のアクションを紹介します。この状態は、Final State、つまり、この状態のアクションが完了すると、この状態機械の持ち主の”注文”の概念インスタンスは消滅することになります。そのため、この状態では、ビジネスシナリオから派生するアクションに加えて、概念情報モデル上の後始末が必要です。

SELECT ONE customer RELATED BY SELF->C[R1.'発注者'];
SELECT ONE productSpec RELATED BY SELF->PS[R1.'購入予約'];
UNRELATE customer FROM productSpec ACROSS R1 USING SELF;

UNRELATE キーワードは、前述の RELATE の対義語の Relationship のリンクを切るアクションです。この様に、ある概念インスタンスを削除する場合に、その概念インスタンスが他の概念インスタンス群とリンクを張っている場合は、全てそのリンクを切る必要があります。

以上、Object Action Language のキーワードの説明も含め、状態モデルの描き方について解説してきました。いくつか取り上げていないキーワードもありますが、各自の状態モデル、及び、アクションを定義する方法の解説としては十分でしょう。状態モデルが定義された概念クラスの概念インスタンスは、状態モデルを雛形にした、それぞれ独立したそれぞれの状態機械を持ち、バラバラに発生するイベントを受信しながら振舞っていく事を忘れずに、概念振舞モデルの作成を行ってください。

参考までに、BridgePointで実際に開けるモデル一式を https://github.com/kae-made/artifacts-product-sales-tutorial/model/TutorialSample から公開しているので、手っ取り早く BridgePoint でモデルを見てみたい方は、こちらをクローンして開いてみてください。

本稿の解説を終える前に、サンプルとして作成した概念モデルは、全くの不完全なモデルであることをご了承ください。BridgePoint の利用法を解説するために単純化したモデルであり、もちろん、「商品販売とはこういうものだ」というような主張も一切ありません。紹介した”注文”の状態モデルも、複数の”注文”の概念インスタンスが同時に状態機械で動きだしたら、あっという間に引当て処理が破綻することは、簡単なシミュレーションですぐに確認できます。練習と思って実際に試してみるとよいでしょう。
複数の注文インスタンスからの引当て要求は当然のことながら限られた在庫商品に対する競合が生じます。この競合は、システム開発におけるソフトウェアが解決するべき問題ではなく、ビジネスシナリオ上で解決するべき問題、つまり、概念情報モデルと概念振舞モデルの定義で解決すべき問題です。概念モデリングによるビジネスシナリオ上の競合の解決方法は、これから作成予定ですので、乞うご期待。

サンプルモデルに関する留意点

概念モデルの振舞を試す

「え?ここまで説明してきて、”練習と思って実際に試してみるとよいでしょう?”って無理無理…」という声が聞こえてきそうなので、Verifier の使い方を紹介することにします。ここまで紹介してきた”商品販売”の概念モデルは、著者の怠慢で振舞モデルは定義していないので、https://github.com/kae-made/domain-model-csharp-adaptor-samples  から公開している、別の概念モデルをサンプルとして説明をつ続けることをご容赦ください。
この概念モデルは、”Process Management”という主題領域(ドメイン)をモデル化したものです。
Process Management は、

  • 有限の資源を使って多段階の処理を行っていくような何らかのプロセスを制御・管理する

    • 一連のプロセスを構成する

    • 構成したプロセスを適切に進行する

    • 現在進行中のプロセス群の状況可視化

という主題領域(ドメイン)で、概念情報モデルは、

Process Management の概念情報モデル

と定義されています。何らかの資源(Resource)を使って、指令(Order Spec)を元に働く処理ステップ(Process Step)の連なり、及び、一つの処理ステップ(Process Step)の完了から次の処理ステップ(Process Step)を開始するための後始末と準備処理(Intermediate Work)から構成される一連の処理(Process)を、起動要求(Requester)によって必要な資源(Resource)を割当てつつ、開始・処理していく様を、概念モデルとして定義しています。Order Spec以外の概念クラスは、状態モデルを持ち、ドメイン全体の振舞を定義しています。

概念モデリングの作成スキルを極めたプロフェッショナルにとっても、静的な絵を見ただけで、そのモデルが想定通りの振舞をするかどうかを判断するのは極めて困難です。”想定通り概念モデルが振舞うか”とは、

  • ある状態で、

    • ”ある状態” については、「概念情報モデルを使う」で解説している通り、概念インスタンス群とその特徴値の値、及び、概念インスタンス間のリンク群で定義されます。

  • ある出来事が発生した時に、

    • ”ある出来事” は、概念クラスの状態モデルで定義されたイベントに相当します。

  • イベントを受信した概念インスタンスの状態遷移によって引き起こされる一連のアクションにより、概念インスタンスの特徴値の更新、概念インスタンスの生成・削除、概念インスタンス間のリンク・アンリンク、が行われた結果として生み出された”状態”が、現実の世界での想定状況と一致している

ということです。BridgePoint の Verifier による検証は、

  • ”ある状態”を作り出す

  • ”ある出来事”を起こす

為のアクションを記述した Function をモデルに追加することによって行います。

Verifier 用の Function 定義

Function は、Model Explorer 上で、Function を追加したいパッケージを右クリックして、New → Function を選択して追加します。
このモデルでは、
TestInitialize のアクションは、

assingnerName = "Test";
SELECT ANY resourceAssigner FROM INSTANCES OF RA WHERE SELECTED.Name == assignerName;
IF EMPTY resourceAssigner
	CREATE OBJECT INSTANCE resourceAssigner OF RA;
	resourceAssigner.Name = param.assignerName;

	CREATE OBJECT INSTANCE resource OF RES;
	resource.Name = "Res0Of" + param.assignerName;
	RELATE resource TO resourceAssigner ACROSS R6;

	CREATE OBJECT INSTANCE resource OF RES;
	resource.Name = "Res1Of" + param.assignerName;
	RELATE resource TO resourceAssigner ACROSS R6;

	CREATE OBJECT INSTANCE resource OF RES;
	resource.Name = "Res2Of" + param.assignerName;
	RELATE resource TO resourceAssigner ACROSS R6;

END IF;

cmdName = "CmdA";
SELECT ANY orderSpec FROM INSTANCES OF OS WHERE SELECTED.Command == cmdName;
IF EMPTY orderSpec
	CREATE OBJECT INSTANCE orderSpec OF OS;
	orderSpec.Command = cmdName;
END IF;

cmdName = "CmdB";
SELECT ANY orderSpec FROM INSTANCES OF OS WHERE SELECTED.Command == cmdName;
IF EMPTY orderSpec
	CREATE OBJECT INSTANCE orderSpec OF OS;
	orderSpec.Command = cmdName;
END IF;

cmdName = "CmdC";
SELECT ANY orderSpec FROM INSTANCES OF OS WHERE SELECTED.Command == cmdName;
IF EMPTY orderSpec
	CREATE OBJECT INSTANCE orderSpec OF OS;
	orderSpec.Command = cmdName;
END IF;

cmdName = "CmdD";
SELECT ANY orderSpec FROM INSTANCES OF OS WHERE SELECTED.Command == cmdName;
IF EMPTY orderSpec
	CREATE OBJECT INSTANCE orderSpec OF OS;
	orderSpec.Command = cmdName;
END IF;

と記述されていて、このアクションを実行すると、”Test” という名前を持つ Resource Assigner の概念インスタンスが1つ、それに、R6 でリンクされる3つの Resource の概念インスタンス、及び、”CmdA”~”CmdD”の名前を持つ、4つの Oder Spec が作成されます。
それでは、実際にやってみましょう。
以下の手順で、Verifier を起動します。

Verifier の起動

Verifier 用の View セットが開くので、Session Explorer で、Verify1Initialize を右クリックして起動を行います。

ドメインの初期状態を作成するために Verify1Initialize を実行する

Console に、

  • User invoked function: Verify1Initialize

と表示され、実行が完了します。Session Explorer に表示された概念クラスの子要素を表示すると、

Verify1Initialize によって生成された概念インスタンス群とリンク

の様に、生成された概念インスタンス群とその特徴値、及び、リンクの状態を見ることができます。
同様に、Verify2CreateRequester を起動すると、Requester の概念インスタンスが生成され、資源(Resource)要求を行い、割り当てられて、Process が開始され、VerifyNotifyProcessStepDone を複数回実行することにより、各 Process Step の実行と、後処理、準備処理が繰り返されていきます。それぞれの Function の実行後に、概念インスタンス群、その特徴値、リンクをチェックしていく事によって、想定通りの振舞が成されているかをチェックしていきます。

Process Management の概念モデルでは、扱われている、Resource(資源)や Process(プロセス)が、”現実世界の具体的には何に相当するのか”については一切触れていません。触れていないが故に、何らかの資源を使って処理単位ごとに片付けや次の準備をしながら多段階の処理を行っていくような様々な現実の状況に対して、利用可能になっています。資源は工場の機械でも、何らかの作業の専門家でも、コインランドリーの洗濯機でも、輸送に使うトラックでも、家庭用医療機器でも何でも構いません。プロセスについても、工場のオートメーションによる製品製造でも、医療の検体調査でも、洗濯でも、荷物の輸送でも、症状の経過観察でも何でも構いません。

補足

コンピュータ上で動かしてみる

ここまでくると、実際にコンピュータやサーバーで実行可能なプログラムコードが欲しくなりませんか?BridgePoint の Verifier で動かせるといっても、なんとなく物足りないし、折角苦労して作った概念モデル図も、まだまだ、絵に描いた餅の域を出ていません。
BridgePoint は、C/C++ で書かれたプログラムコードを概念モデルから生成する機能をもともと持っています。
C/C++ コードの生成は、先ず、以下の様に、Model Compilers の設定を行い、

C/C++ コード生成用セッティング

そして、Model Explorer でプロジェクトアイコンを右クリックし、”Build Project” を選択すると、コード生成が行われます。

プロジェクトのビルドと C/C++コードの生成

BridgePoint のワークスペースのプロジェクトのファルダーの下に、gen という名前のフォルダーが作成され、その下の code_generation/_ch の下に C/C++ソースコード一式が生成されます。
C/C++ のプログラムコードは、コンパクトで実行スピードも速いので組込み機器の制御等には適していますが、ここでは、ビジネス支援を目的とした、デジタルトランスフォーメーションやデジタルツインを実現する IT システム向けのコードとして求められるスケーラビリティやセキュリティ、ホスティング環境との親和性が高い C# コードを生成する著者自作のアプリケーションを紹介します。

アプリのインストールは、各自の責任において行ってください。ウイルス対策等万全を期してはおりますが、紹介しているアプリケーションのインストール・実行で直接的・間接的に発生する不具合、障害等に関し、一切の責任は負いませんのでご注意ください。
インストーラは、https://github.com/kae-made/domainmodel-code-generator-csharp/tree/main/CodeGenerator  で公開しているプロジェクト群を Visual Studio 2022 でビルドすれば作成できますので、念には念を入れたい方は、各自の環境でビルドしてお使いください。

ご注意

https://github.com/kae-made/domainmodel-code-generator-csharp を Web ブラウザで開き、Releases をクリックして、Windows PC 上で動く、GUI 付きの C# ジェネレータアプリケーションのインストーラーが入っている GeneratorWpfAppInstaller.zip  をダウンロードします。ダウンロードした ZIP ファイルを解凍し、SetupDomainModelCsharpGUIGenerator.msi ファイルをダブルクリックして実行すれば、通常のデスクトップアプリのインストールと同じように、C# ジェネレータのインストールが完了します。

C# ジェネレータアプリのインストール

アプリケーション実行ファイルは、

  • C:\Program Files (x86)\Knowledge & Experience\SetupDomainModelCsharpGUIGenerator

フォルダーにあります。DomainModelCsharpGUIGenerator.exe をダブルクリックすると、上図の最後に示したペインを持つ GUI が表示されます。
C# コード生成の為の設定を行います。

コード生成用の設定

各項目の設定は、

  • Project Name

    • ProcessManagement と入力します。生成する C# のプロジェクト名として使われます。

  • Meta Model

    • BridgePoint をインストールしたフォルダーの下の、tools\mc\schema\sql\xtumlmc_schema.sql を選択します。

  • Base Data Type

    • BridgePoint をインストールしたフォルダーの下の、tools\mc\schema\Globals.xtuml を選択します。

  • Domain Model

    • BridgePoint で ”Build Project”で生成された、gen\code_generation\ProcessManagement.sql を選択します。

  • Generate Folder

    • 生成されたコードを格納するためのフォルダーを指定します。適当なフォルダーを作って選択してください。

最低限必要な設定を入力すると、”Generate C# Code”が有効になるので、クリックして、C# コード一式を生成します。生成結果は、右側のツリービューで確認できます。

生成された C#コード

さて、ここから先は、プログラミング経験の全くない読者にはつらい作業になってしまいますが、もうひと踏ん張り頑張るか、知り合いのソフトウェア技術者に頼んで、最後までお試しいただけると幸いです。
生成されるコードや生成の仕組みの詳細については、

を解読してください。

生成された C# コード一式は、Visual Studio 2022 でビルド可能です。”ビルド”とは、人間が読めるテキストをコンピュータが認識できるフォーマットに変換するすることです。本稿で取り扱っている範囲に必要な機能は、Visual Studio 2022 の無償版で提供されているので、Visual Studio 2022 コミュニティ エディション – 最新の無料バージョンをダウンロードする (microsoft.com) からダウンロードし、インストールして試してみてください。
C# Generator アプリケーションが生成したファイルの中に、”ProcessManagement.sln” というファイルがあるので、Visual Studio 2022 でこのファイルを開きます。開いたら、メニューの ”ビルド”→”ソリューションのビルド”を選択してビルドを行います。結果として、

拡張子が".dll"のファイルが生成される

生成先のフォルダーの下の、”bin" フォルダーの”Debug”、もしくは、”Release”のどちらかの、"net5.0" の下に、ProcessManagement.dll が出来上がります。

「ん?で?」ですね、このままだと。ご安心ください。C# ジェネレータアプリのインストールと同じ手順で、https://github.com/kae-made/domain-model-csharp-adaptor-samples の Releases から、DomainModelViewerInstaller.zip をダウンロードし、ZIP ファイルを解凍して、中に入っている、SetupWPFApp.msi ファイルを実行すると、BridgePoint の Verifier の様に、Function の実行や、概念クラスの概念インスタンス群、特徴値、リンクの状況を可視化するアプリケーションがインストールされます。インストール場所は、

  • C:\Program Files (x86)\Knowledge & Experience\DomainModelViewer

で、DomainModelViewer.exe  がアプリケーションの実行ファイルです。
このファイルをダブルクリックして実行し、

概念モデルから生成された DLL ファイルをロードする

右上の”Load”ボタンをクリックして、概念モデルから生成された C# コードをビルドして出来上がった DLL ファイルを選択します。

Domain Model Viewer 

左側が、ProcessManagement で定義した概念クラスのリストで、真ん中が、Function のリストです。真ん中のリストの中から一つ選択して、引数の値を設定し、”Invoke”をクリックすると、該当する Functionが実行されます。

Function の実行

図では、TestInitialize を選択していますが、前に紹介した Verify1Initialize とほぼ同等のアクションが記述された Function です。こちらも、Resource の概念インスタンスを3つ作成するので、Function の実行後に、左のリストから”Resource”を選択すると、概念クラスのリストの下に、3つの概念インスタンスの識別子特徴値の値のリストが表示されます。

概念インスタンスのリスト表示と概念インスタンスの詳細表示ビュー

概念インスタンスのリストから一つ選択すると、新たにパネルが表示され、選択した概念インスタンスの詳細が表示されます。概念インスタンスへのイベント送信や、Relationship でリンクされた概念インスタンスのリストが表示されます。
DomainModelViewer 自体はそっけない地味な見た目のアプリケーションですが、BridgePoint で作成したどんな概念モデルにも対応可能なように作られています。GUI を 3D 化すれば、Metaverse 的なアプリフロントエンドの開発も可能です。
https://github.com/kae-made/domain-model-csharp-adaptor-samples からは、GUI アプリケーションだけでなく、Web API アプリを介して概念モデルから生成されたコードを使うサンプルアプリケーションも公開されています。こちらを使えば、労力少なく、インターネット上で連携する IT システムに、生成コードを組み込むこめます。

最後に

いかがだったでしょうか?BridgePoint のインストールから、概念モデル作成の基本的な操作、おまけとして、作成済みの概念モデルからの C# コード生成、挙句に、GUI アプリ化までを紹介しました。
本稿が、プログラミングの知識が少ない インフォメーションワーカーが、BridgePoint を Excel や PowerPoint 並みに使いこなせるようになる手助けになれば幸いです。
基本操作を習得したら、次は、「概念モデリングチュートリアル ~ ホテルのコインランドリー」に挑戦してみてください。


この記事が気に入ったらサポートをしてみませんか?