はじめに
先に作成した環境を使って、Business Centralでルール開発をする流れを試してみます。
ODMで比較的シンプルなルールを作る手順を示してくれている以下の記事があります。
ODM for Developerをさわってみた②ルール開発
これは、会員のランクを元に割引率を判断するルールを作成しているものですが、これにならって同じようなルールをBAM OEで作成する場合どのような流れになるか見ていきたいと思います。
※実際のケースでは、VS Codeを使ってDRLでルールを記述する、Excelを使って表形式でルールを記述する、というルール開発方法が主流のようですが、残念ながらその方法でルール作成、デプロイ、実行までの一連の手順を示したちょうどよい感じのチュートリアルが見あたりませんでした。初心者にとってはマニュアルからその辺りの手順を読み解くのが大変なので、ここでは手っ取り早く動かせそうなBusiness Centralを使って流れを確認してしてみます。
関連記事
Business Automation Manager Open Edition メモ - (1) 概要
Business Automation Manager Open Edition メモ - (2) KIE Server, Business Central 構成
Business Automation Manager Open Edition メモ - (3) Business Centralを使用したルール開発
Business Automation Manager Open Edition メモ - (4) KIEサーバー上のルール呼び出し
Business Automation Manager Open Edition メモ - (5) Embedded形態でのルール開発(DRL編)
Business Automation Manager Open Edition メモ - (6) Embedded形態でのルール開発(DMN編)
Business Automation Manager Open Edition メモ - (7) kogitoでのルール開発(スタンドアローン)
Business Automation Manager Open Edition メモ - (8) kogitoでのルール開発(OpenShiftへのデプロイ)
前提知識
ルールを定義していくにあたり、事前におさえておく必要がある用語について整理します。
BRMSは"ビジネス・ルール"を外だしにして効率よくルールを管理する仕組みを提供してくれるものです。つまり条件設定を行ってそれを元にして何らかの判断結果を受け取るということになります。
具体的には、ローン審査を行う業務において申請者の様々な条件(年齢、職業、現時点での借入金額、etc...)を元にローン可否を判断する、とか、保険料算定業務において申込内容(保険商品、付帯特約、保険対象の各種条件、etc...)を元に保険料を算出するといったことが挙げられます。
これらの条件、結果を表すオブジェクト(ルールのサービスを呼び出す際の入出力データ)はBAM OEではファクトと呼ばれ、"データオブジェクト"として定義することになります(実体はgetter/setterを保持するJavaのクラス)。
このファクトを元にしてルール定義を作成していきます。基本的には DRL(Drools Rule Language) という専用のルール記述言語でルール記述していくことになります。このDRLではWHEN-THENという構文で条件とアクションを指定していくことになりますが、一からDRLでルールを記述するとこの構文を知らないといけないので、これを補足するためにいくつかGUIベースの補助ツールが提供されています。Business Centralでは、例えばGUIベースでWHEN-THENのルール定義の入力をガイドしてくれる ガイド付きルール、表形式でルールの記述を行うためのガイド付きディシジョンテーブル などが提供されています。
BAM OE - Business Centralによるルール作成の流れ
スペースの作成
一連のルールは"プロジェクト"という単位で作成していきます。プロジェクトは"スペース"と呼ばれる単位で管理されます。
作業スペースをいくつか分けて、各作業スペースごとにプロジェクトを管理する、というイメージです。
Business Centralの初期画面から「設計」を選択します。
最初はMySpaceというスペースが用意されています。必要に応じてスペースを作成します。
プロジェクト作成
以降、このプロジェクトにルールを追加していきます。
データオブジェクトの作成
実際のルールを作成していく前に、ルールの記述で使うデータの定義をしていきます。
ODMでいうところのXOMに相当するものをここで作成していきます。
※BAM OEでは、ODMのBOMに相当するオブジェクトは存在しないようです。
ここでは以下のような変数/型を持つオブジェクトを作成していきます。
- rank/String : 会員のランクを示す変数(プラチナ|ゴールド|など...)
- discount_rate/Double: 割引率を示す変数
- message/String: ルール判定に関連するメッセージを保持する変数
※デフォルトで、com.<スペース名>.<プロジェクト名>
というパッケージ下にオブジェクトが作成されることになります。BAM OEの実装は基本的にJavaなので、最終的にはこのパッケージ下にデータ定義用のJavaのクラスが作成されることになります(変数定義と各変数に対するgetter/setterメソッドを持つクラス)。
データオブジェクト編集画面が開くので、「フィールドを追加」ボタンをクリックします。
「ソース」タブを見ると、実体としては以下のようなJavaのクラスが生成されていることが分かります。
ルール記述
ここから実際のルールを記述していきます。BAM OEではDRL(Drools Rule Language)と呼ばれる言語でルールを記述していくのがメジャーなようですが、初心者が一からゴリゴリとDRLでルールを記述していくのはハードルが高いので、GUIベースでルールを記述する仕組みが提供されています。
ここでは、「ガイド付きルール」(Guided Rule)、および、「ガイド付きディシジョンテーブル」(Guided Decision Table)の2つの方法でルールを作成してみます。
いずれも、GUIのインターフェースでルールを記述していくと最終的にDRLが生成されます。
ガイド付きルールの作成
プロジェクトの画面からアセットの追加ボタンをクリックし、「ガイド付きルール」を選択します。
名前を指定し、当オブジェクトを作成するパッケージを選択します。ここではデータ・オブジェクトと同パッケージにします。
データオブジェクトのタブを開きます。当ガイド付きルールと同じパッケージのデータオブジェクトはデフォルトで使用可能になっています。
※異なるパッケージのデータオブジェクトを使用したい場合はここで明示的に使用するデータオブジェクトを追加する必要があります。
元のモデルタブに戻ってルールを編集していきます。
WHEN-THENで"条件"とその条件に合致したときに"アクション"を指定していきます。
このガイド付きルールでは、rank指定がnullだった場合にdiscount_rateを0にしてrank必須である旨のメッセージをセットする、ということを定義します。
WHEN句の指定
先に作成したデータオブジェクト"Loyalty"を指定します。
WHEN句に「Loyaltyがあります」という表記が追加されますのでそれをクリックします。
変数名として「loyalty」を指定します。
※インスタンス変数を指定するイメージ
WHEN句の表記が「Loyalty[loyalty]があります」に変わりますので、再度そこをクリックします。
WHEN句にrankが表示されるので、その右側のプルダウンから「はnull」を選択
これでWHEN句が設定できました。
「rankがnullだった場合...」という指定をしたことになります。
THEN句の指定
次に「rankがnullだった場合」のアクションをTHENの所に指定していきます。
THENの右端の「+」ボタンをクリックします。
「loyaltyのフィールド値を変更」を選択します。
※ここでは、loyaltyオブジェクトにdiscount_rateの指定、および、messageに値を設定する操作を行うことを想定しています。すなわち、先にインスタンス化したオブジェクトのフィールド値を変更する操作を行いたいので上のメニューを選択しています。
discount_rate指定
THEN句に「Loyalty[loyalty]の値設定」と表示されるので、その横の編集ボタン(鉛筆マーク)をクリックします。
フィールドを追加のプルダウンからdiscount_rateを選択
discount_rateが追加されるのでその横の編集ボタン(鉛筆マーク)をクリックします。
discount_rateの右側の入力欄に固定値として「0.0」を指定します。(デフォルトで0.0になっているので変更不要)
message指定
「Loyalty[loyalty]の値設定」をクリックします。
messageが追加されるのでその横の編集ボタン(鉛筆マーク)をクリックします。
messageの右側の入力欄に固定値として「ランクが入力されていません」を指定します。(入力欄の幅が短くて表示上後ろが見えていませんが...)
これで、THEN句の指定が完了です。
「rankがnullだった場合」のアクションとして「discount_rateに"0.0"を指定」、「messageに"ランクが入力されていません"を指定」というルールを定義したことになります。
ソース(DRL)確認
ここで定義したルールはDRLとして生成されます。「ソース」タブでDRLのソースが確認できます。確認後、「保存」をクリックして作成したルールを保存します。
※ここでソースレベルでの編集は行えません。
ガイド付きディシジョンテーブルの作成
プロジェクトの画面からアセットの追加ボタンをクリックし、「ガイド付きデシジョンテーブル」を選択します。
名前を指定し、当オブジェクトを作成するパッケージを選択します。ここではデータ・オブジェクトと同パッケージにします。また、「ウィザードを使用」にチェックします。
先の画面で「ウィザードを使用」にチェックを入れていると、ディシジョンテーブル作成用のウィザードが表示されますのでこれに従って作成していきます。
インポート
そのまま「次へ」
※使用するデータオブジェクトと同じパッケージにしているのでここでインポートは不要
ファクトパターンを追加
制約を追加
ここでは条件の判断の元になるフィールド(WEHN句で使用するフィールド)を選択します。
「利用可能なパターン」からLoyalty、「利用可能なフィールド」からrankを選択
「条件」からRankを選択し、下段のカラムヘッダー、オペレータ、計算タイプを設定して次へ。
※ここでは、「Rankが"ゴールド"だったら...」というルールを作っていく想定です。
アクションを追加してファクトを更新
「利用可能なパターン」からLoyalty、「利用可能なフィールド」からdiscount_rateを選択
「選択済みのフィールド」からdiscount_rateを選択し、下段のカラムヘッダーを設定して次へ。
アクションを追加してファクトを挿入
展開するカラム
行の追加
作成された表に行を追加して具体的な値を設定していきます。
「モデル」タブにて、メニューから「挿入」-「行の追加」を選択
以下のように表に行が追加されるので、Rankとそれに応じたDiscount Rateを入力していきます。
ソース(DRL)確認
ここで定義したルールはDRLとして生成されます。「ソース」タブでDRLのソースが確認できます。確認後、「保存」をクリックして作成したルールを保存します。
※表の各行がそれぞれ独立したルールとして定義されている様子が確認できます
※ここでソースレベルでの編集は行えません。
テストシナリオ作成
プロジェクトの画面からアセットの追加ボタンをクリックし、「テストシナリオ」を選択します。
名前とパッケージを指定し、ソースタイプにRULEを指定してOKをクリック
表の"GIVEN"の列には入力として与える条件を指定するオブジェクト、"EXPECT"の列にはルール適用結果が返されるオブジェクトを指定します。ここでは、GIVEN列にLoyaltyのrank、EXPECT列にLoyaltyのdiscount_rate、messageを指定します。
次に、テストシナリオとして列を追加していきます。GIVENにはテストケースとして与える条件の具体的な値を、EXPECTにはその時返される値の期待値を指定していきます。
例えばここでは以下のような5つのテストケースを指定してみます。
(2行目と5行目はあえてエラーになるケースを設定しています)
テスト実行ボタンをクリックすると、設定したテストケースが検査されてテストレポートが表示されます。
右側にはテストレポートとして5件中3件成功、2件が失敗したという結果が表示されます。グラフ上では期待値と実際のルール適用結果が異なる箇所が赤いセルでハイライトされます。
カーソルを赤くハイライトされたセルに合わせると、期待値と実際のルール適用後の値の違いが表示されます。
また、どのルールが実行されたかのカバレッジもレポートして表示してくれます。
テストシナリオのエクスポート/インポート
上で作成したテストシナリオを"エクスポート"すると以下のようなCSV形式のファイルが生成されます。
"#",Scenario description,GIVEN,EXPECT,EXPECT
"#",Scenario description,Loyalty,Loyalty,Loyalty
"#",Scenario description,rank,discount_rate,message
1,,プラチナ,0.3,
2,Error scenario for Gold,ゴールド,0.3,
3,,ゴールド,0.2,
4,,null,0.0,ランクが入力されていません
5,Error scenario for null,null,0.05,Rank is Null
BusinessCentral上でヘッダーだけ作ってそれをCSVファイルとしてエクスポートし、テストデータはExcelなどで整備してからインポートし直す、といったことができるので、大量のテストデータを準備してテストする必要がある場合はそのような方法を取ると便利そうです。
カバレッジ・レポートのエクスポート
カバレッジ・レポートをエクスポートすると、以下のようなCSV形式のファイルが生成されます。
AVAILABLE RULES,RULES FIRED,PERCENTAGE OF RULES FIRED
9,5,55.55555555555556
RULE,NUMBER OF TIMES
CalculateDiscountRate_10 (com.testspace01.customerloyalty01),1
Row 1 CalculateDiscountRate (com.testspace01.customerloyalty01),1
CalculateDiscountRate_11 (com.testspace01.customerloyalty01),2
Row 2 CalculateDiscountRate (com.testspace01.customerloyalty01),2
CheckNull (com.testspace01.customerloyalty01),2
TEST SCENARIO INDEX,TEST SCENARIO NAME,RULE INDEX,FIRED RULE,RULE STATUS,MESSAGE
1,,1,CalculateDiscountRate_10 (com.testspace01.customerloyalty01),EXECUTED,
1,,2,Row 1 CalculateDiscountRate (com.testspace01.customerloyalty01),EXECUTED,
2,Error scenario for Gold,1,CalculateDiscountRate_11 (com.testspace01.customerloyalty01),EXECUTED,
2,Error scenario for Gold,2,Row 2 CalculateDiscountRate (com.testspace01.customerloyalty01),EXECUTED,
3,,1,CalculateDiscountRate_11 (com.testspace01.customerloyalty01),EXECUTED,
3,,2,Row 2 CalculateDiscountRate (com.testspace01.customerloyalty01),EXECUTED,
4,,1,CheckNull (com.testspace01.customerloyalty01),EXECUTED,
5,Error scenario for null,1,CheckNull (com.testspace01.customerloyalty01),EXECUTED,
デプロイ
最後に作成したプロジェクトをKIE Serverにデプロイします。
これでサーバーへのデプロイまで完了しました。