🚧 THIS PAGE IS BEING TRANSLATED 🚧
👷 Contributors are invited. Please read CONTRIBUTING and CONTRIBUTING TRANSLATION guidelines.
🖖 Please remove this note once you're done translating.
Tentang Grule | Tutorial | Rule Engine | GRL | GRL JSON | Algoritma RETE | Fungsi-fungsi | FAQ | Benchmark
Mohon dicatat bahwa Grule menggunakan Go 1.13
Untuk menggunakan Grule didalam proyek anda, cukup dengan mudah masukannya.
$go get github.com/hyperjumptech/grule-rule-engine
Dalam file .go
anda,
import (
"github.com/hyperjumptech/grule-rule-engine/ast"
"github.com/hyperjumptech/grule-rule-engine/builder"
"github.com/hyperjumptech/grule-rule-engine/engine"
"github.com/hyperjumptech/grule-rule-engine/pkg"
)
Sebuah fakta
dalam grule adalah hanya sebuah pointer kepada sebua instance dari suatu struktur
Struktur ini bisa berisi properti-propert seperti halnya struktur normal golang biasa, dan juga berisi fungsi
atau yang daldam dunia OOP disebut juga dengan method
type MyFact struct {
IntAttribute int64
StringAttribute string
BooleanAttribute bool
FloatAttribute float64
TimeAttribute time.Time
WhatToSay string
}
Seperti cara umum bahasa Golang, hanya atribut-atribut yang terlihat saja yang dapat di akses dari dalam mesin Grule, hanya atribut dan fungsi yang berawalan huruf besar.
Grule juga dapa memanggil fungsi-fungsi dalam fakta.
func (mf *MyFact) GetWhatToSay(sentence string) string {
return fmt.Sprintf("Let say \"%s\"", sentence)
}
Mohon dicatat, ada beberapa persyaratan.
- Fungsi dalam fakta harus bisa terlihat, memiliki huruf besar di awal.
- Jika fungsinya ada balikan, hanya boleh ada 1 balikan saja.
- Dalam argumen dan balikan, jika itu adalah
int
,uint
ataufloat
, harus menggunakan varian 64-bit-nya. Sepertiint64
,uint64
,float64
. - Fungsi yang dipangging tidak disarankan mengubah nilai data dari atribut-atribut dalam fakta, ini menyebabkan deteksi RETE pada working memory menjadi mustahil. Jika anda tetap HARUS merubah beberapa atribut, anda harus memberitahu Grule menggunakan fungsi
Changed(varname string)
yang sudah disiapkan.
Untui menambahkan fakta kedalam DataContext anda harus membuat sebuah instance dari fakta
anda.
myFact := &MyFact{
IntAttribute: 123,
StringAttribute: "Some string value",
BooleanAttribute: true,
FloatAttribute: 1.234,
TimeAttribute: time.Now(),
}
Anda bisa membuat banyak fakta sesuai kebutuhan anda.
Berikutnya, anda hendak menyiapkan DataContext
dan menambahkan instance
fakta anda kedalamnya.
dataCtx := ast.NewDataContext()
err := dataCtx.Add("MF", myFact)
if err != nil {
panic(err)
}
Pada dasarnya, KnowledgeLibrary
adalah sebuah pustaka berisi kumpulan cetak-biru KnowledgeBase
.
Dan KnowledgeBase
adalah kumpulan dari banyak rule yang berasal dari kumpulan definisi (GRL)
yang diambil dari banyak sumber.
Kita menggunakan RuleBuilder
untuk membangun KnowledgeBase
dan menambahkannya kedalam KnowledgeLibrary
Sebuah DRL, bisa dibuat dari sebuah string sederhana, disimpan didalam file atau tersimpan di suatu tempat di internet. DRL ini digunakan untuk membangun satu atau lebih rule
Sekarang, mari kita buat KnowledgeLibrary
dan RuleBuilder
untuk membangun rule kedalam KnowledgeLibrary
yang sudah disiapkan.
knowledgeLibrary := ast.NewKnowledgeLibrary()
ruleBuilder := builder.NewRuleBuilder(knowledgeLibrary)
Sekaran kita bisa menambahkan sebuah rule (didefinisikan dalam GRL)
// mari kita siapkan sebuah definisi rule
drls := `
rule CheckValues "Check the default values" salience 10 {
when
MF.IntAttribute == 123 && MF.StringAttribute == "Some string value"
then
MF.WhatToSay = MF.GetWhatToSay("Hello Grule");
Retract("CheckValues);
}
`
// Tambahkan definisi diatas kedalam pustakan dan kita namakan 'TutorialRules' dengan versi '0.0.1'
byteArr := pkg.NewBytesResource([]byte(drls))
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", byteArr)
if err != nil {
panic(err)
}
Anda dapat memuat GRL dari berbagai dan banyak sumber.
fileRes := pkg.NewFileResource("/path/to/rules.grl")
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", fileRes)
if err != nil {
panic(err)
}
atau jika anda inginkan anda bisa memuat dari sumber file dengan pola
bundle := pkg.NewFileResourceBundle("/path/to/grls", "/path/to/grls/**/*.grl")
resources := bundle.MustLoad()
for _, res := range resources {
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", res)
if err != nil {
panic(err)
}
}
byteArr := pkg.NewBytesResource([]byte(rules))
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", byteArr)
if err != nil {
panic(err)
}
urlRes := pkg.NewUrlResource("http://host.com/path/to/rule.grl")
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", urlRes)
if err != nil {
panic(err)
}
bundle := pkg.NewGITResourceBundle("https://github.com/hyperjumptech/grule-rule-engine.git", "/**/*.grl")
resources := bundle.MustLoad()
for _, res := range resources {
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", res)
if err != nil {
panic(err)
}
}
Sekarang, didalam KnowledgeLibrary
kita memiliki sebuah KnowledgeBase
dengan nama TutorialRules
dengan versi 0.0.1
. Untuk menjalankan rule ini, anda harus membuat sebuah instance dari KnowledgeBase
ini dan mengambilnya dari KnowledgeLibrary
. Ini akan dijelaskan dalam sesi berikutnya.
Untuk menjalankan sebuah KnowledgeBase
, kita perlu membuat sebuah instance dari KnowledgeBase
, diambail dari KnowledgeLibrary
knowledgeBase := knowledgeLibrary.NewKnowledgeBaseInstance("Tutorial", "0.0.1")
Setiap instance yang anda dapatkan dari KnowledgeLibrary
adalah tiruan dari cetak-biru KnowledgeBase
. Tiruan ini adalah instance yang berbeda dan membuat eksekusi terhadapnya bersifat thread-safe. Setiap tiruan instance ini juga membawa WorkingMemory
-nya sendiri. Ini sangat berguna jika anda ingin menjalankan banyak eksekusi multithread dari rule-engine (contohnya dalam sebuah web-server yang melayani setiap permintaan menggunakan mesin rule).
Ini memberikan peningkatan performa yang cukup besar dikarenakan anda tidak perlu membangun ulang KnowledgeBase
dari GRL setiap kali anda memulai thread baru. KnowledgeLibrary
akan membuat tiruan dari struktur AST
dalam cetak biru KnowledgeBase
kedalam instance baru.
Ok, sekarang mari kita jalankan KnowledgeBase
yang didapat dari KnowlegeLibrary
dengan menggunakan DataContext
yang sudah disiapkan.
engine = engine.NewGruleEngine()
err = engine.Execute(dataCtx, knowledgeBase)
if err != nil {
panic(err)
}
Jika anda perhatikan, pada GRL diatas,
rule CheckValues "Check the default values" salience 10 {
when
MF.IntAttribute == 123 && MF.StringAttribute == "Some string value"
then
MF.WhatToSay = MF.GetWhatToSay("Hello Grule");
Retract("CheckValues");
}
Rule ini mengubah atribut MF.WhatToSay
dimana ini mengacu pada WhatToSay
dalam struktur MyFact
.
Jadi cukup mengakses variable tersebut untuk mengambil hasilnya.
fmt.Println(myFact.WhatToSay)
// this should prints
// Lets Say "Hello Grule"
## Resources
GRLs can be stored in external files and there are many ways to obtain and load
the contents of those files.
### From File
```go
fileRes := pkg.NewFileResource("/path/to/rules.grl")
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", fileRes)
if err != nil {
panic(err)
}
You can also load multiple files into a bundle with paths and glob patterns:
bundle := pkg.NewFileResourceBundle("/path/to/grls", "/path/to/grls/**/*.grl")
resources := bundle.MustLoad()
for _, res := range resources {
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", res)
if err != nil {
panic(err)
}
}
bs := pkg.NewBytesResource([]byte(rules))
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", bs)
if err != nil {
panic(err)
}
urlRes := pkg.NewUrlResource("http://host.com/path/to/rule.grl")
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", urlRes)
if err != nil {
panic(err)
}
headers := make(http.Header)
headers.Set("Authorization", "Basic YWxhZGRpbjpvcGVuc2VzYW1l")
urlRes := pkg.NewURLResourceWithHeaders("http://host.com/path/to/rule.grl", headers)
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", urlRes)
if err != nil {
panic(err)
}
bundle := pkg.NewGITResourceBundle("https://github.com/hyperjumptech/grule-rule-engine.git", "/**/*.grl")
resources := bundle.MustLoad()
for _, res := range resources {
err := ruleBuilder.BuildRuleFromResource("TutorialRules", "0.0.1", res)
if err != nil {
panic(err)
}
}
You can now build rules from JSON! Read how it works
If you want to have faster rule set loading performance (e.g. you have very large rule sets and loading GRL is too slow), you can save your rule set into GRB (Grules Rule Binary) file. Read how to store and load GRB