0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

この記事誰得? 私しか得しないニッチな技術で記事投稿!
Qiita Engineer Festa20242024年7月17日まで開催中!

【Drools】DSL機能を使ってルールの可読性を高める

Last updated at Posted at 2024-06-11

はじめに

Drools では、DRL (Drools Rule Language) 構文で記述したルールによって、入力データが特定の条件をみたしたときの処理を自動化できます。

以下は、人の年齢に応じてドリンクを決定するルールです。

rule "Child"
    when
        $person : Person( age < 20 )
        $drink : Drink()
    then
        $drink.setName( "Orange Juice" );
        $drink.setCharge( 100 );
end

rule "Adult"
    when
        $person : Person( age >= 20 )
        $drink : Drink()
    then
        $drink.setName( "Beer" );
        $drink.setCharge( 200 );
end

when 節では入力データに関する条件が、then 節では条件をみたしたときに実行する処理が記述されています。
プログラミング言語にある程度慣れている人であれば、おおよそどんなことをやっているか判断できるでしょう。
しかし、プログラミング経験がない方にとっては、DRL を一目で理解することは難しいと思われます。

今回の記事では Drools の DSL 機能を使って、Drools のルールをよりわかりやすくする方法を紹介します。

DroolsのDSL機能について

DSL (Domain Specific Languages) は、日本語ではドメイン固有言語、またはドメイン特化言語などと呼ばれます。
Java などのプログラミング言語と異なり、特定の目的を果たすことにフォーカスして設計される言語を意味します。
アプリの依存関係を定義する目的で利用される、Gradleのビルドスクリプト等が例として挙げられます。

Droolsでは、ルールの記述に用いるDSLをDSLファイルに、DSLを用いたルール定義をDSLRというファイルで記述できます。
DSL・DSLRファイルをDroolsに読み込ませると、内部的にDRLファイルに変換したうえで、ルールを実行することができます。

DSLファイルは、次のような形式で記述されます。

[when]{ルールの条件を表すフレーズ} = {DRL構文}
[then]{ルールのアクションを表すフレーズ} = {DRL構文}

ここで定義している{ルールの条件を表すフレーズ}・{ルールのアクションを表すフレーズ}を、DSLRファイルで利用することができます。
定義したフレーズが、プログラマーでない方にとってもわかりやすい表現になっていれば、ルールの可読性も向上することが期待されます。

サンプルアプリ

例として、最初に紹介したドリンク判定のルールをDSLで書いて動かしてみます。
サンプルコードのプロジェクトはGithubにあげています。

環境、ライブラリバージョン

  • windows11
  • openjdk 17
  • Drools 8.44.0.Final

データクラス

通常のDRLでルールを実行する場合と同様、データクラスを定義します。

Person.java
public record Person(
    String name, 
    int age
){}
Drink.java
public class Drink {

    private String name;

    private int charge;

    public String getName() {
        return name;
    }

    public int getCharge(){
        return charge;
    }

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

    public void setCharge(int charge){
        this.charge = charge;
    }

    @Override
    public String toString() {
        return "name: " + name + ", " + "charge: " + charge;
    }

}

Personクラスはイミュータブルでいいので、手軽にレコードクラスで書いてます。

DSLファイル

条件、アクション部に用いるDSLフレーズを定義します。

DrinkRule.dsl
[when]来店客の年齢が {age} 才未満 = $person : Person(age < {age})
[when]来店客の年齢が {age} 才以上 = $person : Person(age >= {age})
[when]ドリンクが注文される = $drink : Drink()

[then]"{name}"を提供する = $drink.setName( "{name}" );
[then]料金は {charge} 円 = $drink.setCharge( {charge} );

{age}, {name}などと書いている箇所で、DSLRに記載した値を受け取ることができます。

DSLRファイル

DSLファイルに定義したフレーズを使って、ルールを記述していきます。

DrinkRule.dslr
import org.example.dslsample.Person
import org.example.dslsample.Drink

expander DrinkRule.dsl

rule "Child"
    when
        来店客の年齢が 20 才未満
        ドリンクが注文される
    then
        "オレンジジュース"を提供する
        料金は 100 円
end

rule "Adult"
    when
        来店客の年齢が 20 才以上
        ドリンクが注文される
    then
        "ビール"を提供する
        料金は 200 円
end

DSLRをDRLへ変換するために、expander属性でDSLファイル名を指定しています。

動作確認

実際にルールを動かしてみます。
以下がテストコードの一部です。
呼び出し部分のJavaコードは、通常のDRLで記載したルールを動かす場合と変わりません。

SampleDslTest.java
public class SampleDslTest {
    
    @Test
    public void test_ドリンク判定ルール_Child() {
        KieServices ks = KieServices.Factory.get();
        KieContainer kieContainer = ks.getKieClasspathContainer();
        KieSession kieSession = kieContainer.newKieSession();

        // set up
        var person = new Person("太郎", 13);
        var drink = new Drink();
        kieSession.insert(person);
        kieSession.insert(drink);

        // execute
        kieSession.fireAllRules();

        // assert
        assertEquals("オレンジジュース", drink.getName());
        assertEquals(100, drink.getCharge());

        kieSession.dispose();
    }
...

テストを実行すると、今回は13歳の太郎君が来店したので、飲み物はオレンジジュースと判定されることがわかります。
import文などプログラムチックなものは残っているものの、かなりルールの可読性が向上したと感じます。

今回紹介したDSL機能は、業務担当者(※)と協力して、アプリに組み込むルールを作成する際に有用ではないかと思われます。

(※)ここではIT職以外の方で、特定の業務知識をもち、作成したアプリケーションで日々の業務を行う人を想定しています

業務担当者とルールを検討する、実装したルールをレビューしてもらう、といったことがDSL機能を使うことでやりやすくなるのでは、と考えています。

参考

Drools 公式ドキュメント

通常のDRLを使ったルールの実行方法については、こちらもご参照ください

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?