需要があるかわからないですが、業務で使用したので備忘までに書いておきます。
Droolsとは
オープンソースのBRMS(Business Rule Management System)。Redhat製。
BRMSを使うことで、ビジネスルール(if文の分岐)をアプリケーションから外出しにすることが出来ます。
DroolsではDRLと呼ばれる独自言語やExcelでビジネスルールを記述します。
Kotlinで動かす
DroolsはJavaのライブラリが提供されているので、Kotlinでも動かすことが出来ます。
サンプルコードはGitHubにあげてあります。
実装内容
りんごの仕分け(ランク付け)を行います。
りんごには重さがあって、重さによってランクをS、A、B、C、Dの5段階に分けるというルールをKotlinとDroolsを使って実装していきます。
環境
- Kotlin: 1.2.21
- Gradle: 4.3.1
- Drools: 7.5.0.Final
- IntelliJ IDEA
gradleの設定
dependenciesに以下の2行を追加します
compile "org.kie:kie-api:7.5.0.Final"
compile "org.drools:drools-decisiontables:7.5.0.Final"
アプリの実装
りんごはKotlinのdata classを使って実装します
data class Apple(val size: Long, var rank: String = "")
ルールを実行するルールエンジンの取得。実装はこちらの記事を参考にさせて頂きました。
fun getKieSession(filepath: String) : KieSession? {
val kieServices = KieServices.Factory.get()
val kieFileSystem = kieServices.newKieFileSystem()
val file = Paths.get(filepath).toFile()
// (debug) xlsをdrl形式で表示する
file.inputStream().use {
val sc = SpreadsheetCompiler()
println(sc.compile(it, InputType.XLS))
}
var kieSession: KieSession? = null
file.inputStream().use {
// inputStreamからの読み込み
kieFileSystem.write(
"src/main/resources/rules.xls",
kieServices.resources.newInputStreamResource(it)
)
val kieBuilder = kieServices.newKieBuilder(kieFileSystem).buildAll()
// ルールファイル記述内容のチェック
val results = kieBuilder.results
if (results.hasMessages(Message.Level.ERROR)) {
println(results.toString())
throw IllegalStateException(">>>ルールファイルの記述に問題があります。")
}
kieSession = kieServices
.newKieContainer(kieServices.repository.defaultReleaseId)
.newKieSession()
}
return kieSession
}
取得したルールエンジンを元にルールを実行します。
fun main(args: Array<String>) {
val filepath = if(args.isNotEmpty()) {
args[0]
} else {
throw IllegalArgumentException("ルールファイルが指定されていません")
}
val apples = listOf(
Apple(size = 1),
Apple(size = 5),
Apple(size = 10),
Apple(size = 30),
Apple(size = 70),
Apple(size = 120)
)
val kieSession = getKieSession(filepath)
kieSession?.let {
apples.forEach { apple ->
it.insert(apple)
it.fireAllRules() // ルール実行
println("Size: ${apple.size} -> Rank: ${apple.rank}")
}
it.dispose()
}
}
ルール定義
Excelを使ってルールを記述します。
CONDITIONの列に判断条件を書き、ACTION列に条件に合致した場合に実行する処理を書きます。
今回の場合、サイズが
- 100以上 -> Rank S
- 99〜50 -> Rank A
- 49〜10 -> Rank B
- 9〜5 -> Rank C
- 5未満 -> Rank D
というルールになります。
CONDITIONのeval($param)
という記述はCONDITION列のコード(100 > size && size >= 50
とか)をJavaのコードとして解釈し実行してくれるものです。
実行してみる
$ ./gradlew run -Pargs="data/rules1.xls"
(省略)
Size: 1 -> Rank: D
Size: 5 -> Rank: C
Size: 10 -> Rank: B
Size: 30 -> Rank: B
Size: 70 -> Rank: A
Size: 120 -> Rank: S
サイズごとにランクをつけて返してくれました。
$ ./gradlew run -Pargs="data/rules2.xls"
(省略)
Size: 1 -> Rank: D
Size: 5 -> Rank: D
Size: 10 -> Rank: D
Size: 30 -> Rank: D
Size: 70 -> Rank: C
Size: 120 -> Rank: A
ルールの変更によって結果が変わったことがわかります。
まとめ
このくらいの条件ならコードにif文を書けばいいじゃないか
BRMSを使用することでビジネスルールをコードと分離でき、運用側・業務側でルールを変更することが可能となり、仕様変更に柔軟な対応を行うことが出来ます。
BRMS製品の一つであるDroolsはJavaのライブラリが提供されており、KotlinでもDroolsを利用したアプリを作成することが可能です。