偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

規(guī)則引擎與商業(yè)CRM的完美邂逅:將智能決策融入商業(yè)擴(kuò)展

開(kāi)發(fā) 架構(gòu)
在easyRule引入商機(jī)流轉(zhuǎn)業(yè)務(wù)過(guò)程中,從調(diào)研到選型再到最終落地,遇到了各種大大小小的問(wèn)題,但最終的效果還是比較明顯的,對(duì)團(tuán)隊(duì)的整體效率提升非常明顯,這里有幾點(diǎn)總結(jié)與建議與大家分享。

一、背景介紹

商業(yè)CRM系統(tǒng)的商機(jī)模塊業(yè)務(wù)復(fù)雜、場(chǎng)景繁多、規(guī)則調(diào)整頻繁,商機(jī)流轉(zhuǎn)效率一定程度決定了銷(xiāo)售開(kāi)單的效率。如何高效配合產(chǎn)品側(cè)完成業(yè)務(wù)規(guī)則調(diào)整,商機(jī)流轉(zhuǎn)經(jīng)歷了硬編碼到半配置化的優(yōu)化升級(jí),過(guò)程中遇到了一些問(wèn)題,也總結(jié)了一些經(jīng)驗(yàn),今天來(lái)和大家掰開(kāi)揉碎了講一講這其中遇到的問(wèn)題和解決方案。

1.1 什么是CRM

先看一下CRM的官方定義:

CRM(Customer Relationship Management):客戶關(guān)系管理,是指企業(yè)為提高核心競(jìng)爭(zhēng)力,利用相應(yīng)的信息技術(shù)以及互聯(lián)網(wǎng)技術(shù)協(xié)調(diào)企業(yè)與顧客間在銷(xiāo)售、營(yíng)銷(xiāo)和服務(wù)上的交互,從而提升其管理效率,向客戶提供創(chuàng)新式的個(gè)性化的客戶交互和服務(wù)的過(guò)程。

其最終目標(biāo)是:吸引新客戶、保留老客戶以及將已有客戶轉(zhuǎn)為忠實(shí)客戶,增加市場(chǎng)。

可以這么簡(jiǎn)單的理解,CRM的核心價(jià)值就是:將潛在客戶更高效的轉(zhuǎn)化為客戶,將客戶更高效的轉(zhuǎn)化為長(zhǎng)期客戶。

圖片圖片

介紹完什么是CRM,那CRM系統(tǒng)就很容易理解了,用于支撐企業(yè)進(jìn)行客戶關(guān)系管理的系統(tǒng),就可以稱作CRM系統(tǒng)。這個(gè)定義比較寬泛,每個(gè)公司對(duì)CRM中功能邊界也不完全一樣,大家初步理解這個(gè)概念就行。比如轉(zhuǎn)轉(zhuǎn)商業(yè)CRM系統(tǒng),主要包含:商機(jī)管理、客戶管理、銷(xiāo)售/運(yùn)營(yíng)人員管理、業(yè)績(jī)管理、效率監(jiān)控等功能模塊。

1.2 商機(jī)業(yè)務(wù)介紹

要想把潛在客戶變成客戶,就需要銷(xiāo)售人員進(jìn)行跟進(jìn),對(duì)潛在客戶進(jìn)行產(chǎn)品的售賣(mài),用戶購(gòu)買(mǎi)產(chǎn)品后,變成客戶。這個(gè)潛在客戶,我們稱作“商機(jī)”,也就是一次成單的機(jī)會(huì),有的CRM系統(tǒng)中,也稱為“線索”。

上圖是潛在用戶到客戶簡(jiǎn)單的流轉(zhuǎn)圖上圖是潛在用戶到客戶簡(jiǎn)單的流轉(zhuǎn)圖

從商機(jī)生成到最終成單,銷(xiāo)售跟進(jìn)過(guò)程中,涉及一些概念,比如商機(jī)池(公海池、私海池)、商機(jī)狀態(tài)/來(lái)源/類型/等級(jí)、商機(jī)的流轉(zhuǎn)等。

商機(jī)池:各種商機(jī)的集合。公海池:該集合里的商機(jī)當(dāng)前不歸屬于任何銷(xiāo)售,所有銷(xiāo)售均可以看到公海里的商機(jī)。私海池:綁定了特定銷(xiāo)售的商機(jī)集合,比如銷(xiāo)售A的商機(jī)私海池,只有銷(xiāo)售A可以看到和跟進(jìn),其他銷(xiāo)售不可見(jiàn)、不可跟進(jìn)。商機(jī)流轉(zhuǎn):商機(jī)在跟進(jìn)過(guò)程中,被不同的銷(xiāo)售跟進(jìn),狀態(tài)發(fā)生不同的變化。流轉(zhuǎn)規(guī)則:流轉(zhuǎn)過(guò)程中會(huì)有各種各樣的業(yè)務(wù)規(guī)則限制,比如銷(xiāo)售最多可以認(rèn)領(lǐng)100條商機(jī)、負(fù)責(zé)手機(jī)類目的銷(xiāo)售不能認(rèn)領(lǐng)電腦類目的商機(jī)、銷(xiāo)售剛放棄的商機(jī)不能立馬重新認(rèn)領(lǐng)、單位時(shí)間內(nèi)不進(jìn)行電話溝通的商機(jī)將流出銷(xiāo)售私海等等。

二、商機(jī)流轉(zhuǎn)遇到的問(wèn)題

2.1 商機(jī)流轉(zhuǎn)業(yè)務(wù)特點(diǎn)

這里舉一個(gè)例子來(lái)說(shuō)明商機(jī)的流轉(zhuǎn),業(yè)務(wù)背景:商機(jī)對(duì)應(yīng)用戶主營(yíng)類目為手機(jī),銷(xiāo)售A、B負(fù)責(zé)手機(jī)類目,銷(xiāo)售C負(fù)責(zé)電腦類目,銷(xiāo)售D也負(fù)責(zé)手機(jī)類目。

圖片圖片

這是一個(gè)簡(jiǎn)單的流程,實(shí)際流程比這個(gè)復(fù)雜。從這個(gè)簡(jiǎn)易的流程介紹中,可以窺見(jiàn)部分商機(jī)流轉(zhuǎn)模塊的業(yè)務(wù)特點(diǎn),總結(jié)起來(lái)有三點(diǎn):

  • 狀態(tài)的多樣性

圖片圖片

  • 狀態(tài)間轉(zhuǎn)換場(chǎng)景繁多

圖片圖片

  • 流轉(zhuǎn)規(guī)則復(fù)雜多變

圖片圖片

2.2 商機(jī)流轉(zhuǎn)業(yè)務(wù)痛點(diǎn)

之前商業(yè)CRM中關(guān)于流轉(zhuǎn)的處理邏輯,好多都是硬編碼,舉個(gè)銷(xiāo)售認(rèn)領(lǐng)某條商機(jī)的例子:

//狀態(tài)校驗(yàn)
if(checkClueStatus(param)){
 return “狀態(tài)不合法”;
}
//綁定人校驗(yàn)
if(checkClueBindUser(param)){
 return “上一個(gè)綁定人不可以為···”;
}
//私海容量校驗(yàn)
if(checkPrivateClueCount(param)){
 return “私海庫(kù)已滿,無(wú)法操作··”;
}
//類目校驗(yàn)
if(checkClueCate(param)){
 return “類目不匹配,無(wú)法操作··”;
}
//任務(wù)是否完成校驗(yàn)
if(checkClueTaskFinished(param)){
 return “任務(wù)未完成,無(wú)法操作··”;
}  ······
bind(param);//綁定操作
log();//日志記錄操作

從代碼中可以看出,銷(xiāo)售從公海進(jìn)行認(rèn)領(lǐng)一條自己覺(jué)得有價(jià)值的商機(jī)時(shí),并不是直接就讓該商機(jī)流入到該銷(xiāo)售私海中,這個(gè)過(guò)程會(huì)有各種規(guī)則的業(yè)務(wù)校驗(yàn)。

2.2.1 痛點(diǎn)

  1. 硬編碼實(shí)現(xiàn)的業(yè)務(wù),維護(hù)成本大;
  2. 業(yè)務(wù)規(guī)則經(jīng)常調(diào)整,難以應(yīng)對(duì)變化,產(chǎn)研配合效率低;
  3. 業(yè)務(wù)規(guī)則調(diào)整需要配合修改代碼,重新上線后生效。

2.2.2 訴求

  1. 規(guī)則抽取成可配置項(xiàng),調(diào)整方便;
  2. 校驗(yàn)相關(guān)閾值,可隨時(shí)動(dòng)態(tài)調(diào)整,無(wú)需上線;
  3. 代碼優(yōu)雅度適當(dāng)提高。

帶著我們的痛點(diǎn)和訴求,接下來(lái)看看可以找到什么樣的解決方案。然后我們進(jìn)入了調(diào)研階段,發(fā)現(xiàn)對(duì)于這種策略比較密集的業(yè)務(wù),規(guī)則引擎是一個(gè)可參考方向,然后就開(kāi)始了解規(guī)則引擎相關(guān)細(xì)節(jié),了解完后,發(fā)現(xiàn)和業(yè)務(wù)問(wèn)題匹配度很高。接下來(lái),先介紹一下規(guī)則引擎相關(guān)的基本知識(shí)。

三、什么是規(guī)則引擎

3.1 什么是規(guī)則

規(guī)則就是:條件 --> 推理 --> 結(jié)果。一個(gè)完整的規(guī)則是需要這三部分元素的,平時(shí)大家討論規(guī)則,某些時(shí)候只是在討論第一部分的條件,比如學(xué)校的行為規(guī)范,咱們國(guó)家的各種法律條文,可能關(guān)注的部分是需要滿足什么條件(不能做什么什么),后面的推理和結(jié)果省去了。比如學(xué)生準(zhǔn)則里的不辱罵同學(xué),這是一個(gè)條件,那怎么算辱罵呢,這是推理過(guò)程,辱罵后會(huì)發(fā)生什么呢,會(huì)受到老師批評(píng),這是結(jié)果。

那什么是推理引擎和規(guī)則引擎呢?

  • 推理引擎:如果由程序來(lái)處理推理過(guò)程,那么這個(gè)程序就叫做推理機(jī)/推理引擎。
  • 規(guī)則引擎:基于規(guī)則的推理機(jī)易于理解、易于獲取、易于管理,被廣泛采用。這種推理引擎被稱為“規(guī)則引擎”。是一種嵌入在應(yīng)用程序中的組件,實(shí)現(xiàn)了將業(yè)務(wù)決策從應(yīng)用程序代碼中分離出來(lái),并使用預(yù)定義的語(yǔ)義模塊編寫(xiě)業(yè)務(wù)決策。接受數(shù)據(jù)輸入,解釋業(yè)務(wù)規(guī)則,并根據(jù)業(yè)務(wù)規(guī)則做出業(yè)務(wù)決策。

3.2 推理引擎原理

圖片圖片

  • 模式匹配器決定選擇執(zhí)行哪個(gè)規(guī)則,何時(shí)執(zhí)行規(guī)則;
  • 議程管理模式匹配器挑選出來(lái)的規(guī)則的執(zhí)行次序;
  • 執(zhí)行引擎負(fù)責(zé)執(zhí)行規(guī)則和其他動(dòng)作。

推理引擎通過(guò)決定哪些規(guī)則滿足事實(shí)或目標(biāo),并授予規(guī)則優(yōu)先級(jí),滿足事實(shí)或目標(biāo)的規(guī)則被加入議程,具體過(guò)程:

  1. 將初始數(shù)據(jù)(fact)輸入至工作內(nèi)存(Working Memory)。
  2. 使用Pattern Matcher將規(guī)則庫(kù)(Rules repository)的規(guī)則(rule)和數(shù)據(jù)(fact)比較。
  3. 如果執(zhí)行規(guī)則存在沖突(conflict),即同時(shí)激活了多個(gè)規(guī)則,將沖突的規(guī)則放入沖突集合。
  4. 解決沖突,將激活的規(guī)則按順序放入Agenda。
  5. 執(zhí)行Agenda中的規(guī)則。
  6. 重復(fù)步驟2至5,直到執(zhí)行完畢Agenda中的所有規(guī)則。

推理方式分為正向推理和反向推理

  • 正向推理(演繹法):事實(shí)驅(qū)動(dòng),正向推理,直到無(wú)事實(shí)可用或者得出結(jié)論為止;
  • 反向推理(歸納法):目標(biāo)驅(qū)動(dòng),提出假設(shè),尋找支持該假設(shè)的證據(jù),如果能找到證明,結(jié)論正確,如果不能,換假設(shè)繼續(xù)。

常見(jiàn)的模式匹配算法有Rete,LFA,TREAI,LEAPS。Rete算法是目前效率最高的一個(gè)演繹法推理算法,許多規(guī)則引擎都是基于Rete算法來(lái)進(jìn)行推理計(jì)算的。

3.3 Rete算法

3.3.1 Rete算法簡(jiǎn)介

  1. Rete在拉丁語(yǔ)中是“net”,有網(wǎng)絡(luò)的意思。Rete算法由Carnegie Mellon University的Dr Charles L. Forgy設(shè)計(jì)發(fā)明,是一個(gè)用來(lái)實(shí)現(xiàn)產(chǎn)生式規(guī)則系統(tǒng)(production/inference)的高效模式匹配算法。
  2. RETE算法可以分為兩部分:規(guī)則編譯(rule compilation)和運(yùn)行時(shí)執(zhí)行(runtime execution)。
  • 規(guī)則編譯:是指根據(jù)規(guī)則集生成推理網(wǎng)絡(luò)的過(guò)程。
  • 運(yùn)行時(shí)執(zhí)行:指將數(shù)據(jù)送入推理網(wǎng)絡(luò)進(jìn)行篩選的過(guò)程。
  1. 相關(guān)概念:
  • 事實(shí)(fact):對(duì)象之間及對(duì)象屬性之間的關(guān)系
  • 規(guī)則(rule):是由條件和結(jié)論構(gòu)成的推理語(yǔ)句,一般表示為if…Then。一個(gè)規(guī)則的if部分稱為L(zhǎng)HS(left-hand-side),then部分稱為RHS(right hand side)。
  • 模式(module):就是指IF語(yǔ)句的條件。這里IF條件可能是有幾個(gè)更小的條件組成的大條件。模式就是指的不能在繼續(xù)分割下去的最小的原子條件。

3.3.2 Rete算法原理

圖片圖片

這是Rete算法的原理圖,Rete算法涉及兩種網(wǎng)絡(luò)和6種不同作用的節(jié)點(diǎn)。

  • 網(wǎng)絡(luò)節(jié)點(diǎn):Type Node、Select Node、Join Node、Teminal Node、Alpha Memory、Beta Memory
  • alpha網(wǎng)絡(luò):過(guò)濾working memory,找出符合規(guī)則中每一個(gè)模式的集合,生成alpha memory(滿足該模式的集合)。
  • Beta網(wǎng)絡(luò):有兩種類型的節(jié)點(diǎn)Beta Memory和Join Node。前者主要存儲(chǔ)Join完成后的集合。后者包含兩個(gè)輸入口,分別輸入需要匹配的兩個(gè)集合,由Join節(jié)點(diǎn)做合并工作傳輸給下一個(gè)節(jié)點(diǎn)。

3.3.2.1 Rete推理網(wǎng)絡(luò)生成過(guò)程

圖片圖片

  1. 創(chuàng)建root節(jié)點(diǎn)(根節(jié)點(diǎn)),推理網(wǎng)絡(luò)的入口。
  2. 拿到規(guī)則1,從規(guī)則1中取出模式1(模式就是最小的原子條件,所以規(guī)則模式的關(guān)系是1:n)。

a)   檢查模式1中的參數(shù)類型,如果是新類型,添加一個(gè)類型節(jié)點(diǎn)。

b)   檢查模式1對(duì)應(yīng)的Alpha節(jié)點(diǎn)是否存在,如果存在記錄下節(jié)點(diǎn)的位置;如果沒(méi)有,將模式1作為一個(gè)Alpha節(jié)點(diǎn)加入到網(wǎng)絡(luò)中。同時(shí)根據(jù)Alpha節(jié)點(diǎn)建立Alpah內(nèi)存表。

c)   重復(fù)b,直到處理完所有模式。

d)   組合Beta節(jié)點(diǎn):Beta(2)左輸入節(jié)點(diǎn)為Alpha(1),右輸入節(jié)點(diǎn)為Alpha(2);Beta(i)左輸入節(jié)點(diǎn)是Beta(i-1),右輸入節(jié)點(diǎn)為Alpha(i),并將兩個(gè)父節(jié)點(diǎn)的內(nèi)存表內(nèi)聯(lián)成為自己的內(nèi)存表。

e)   重復(fù)d,直到所有Beta節(jié)點(diǎn)處理完畢。

f)   將動(dòng)作Then部分封裝成最后節(jié)點(diǎn)做為Beta(n)。

  1. 重復(fù)2,直到所有規(guī)則處理完畢。

3.3.2.2 Rete匹配過(guò)程

圖片圖片

  • 導(dǎo)入需要處理的事實(shí)到facts集合中。
  • 如果facts不為空,選擇一個(gè)fact進(jìn)行處理。否則停止匹配過(guò)程。
  • 選擇alpha網(wǎng)的第一個(gè)節(jié)點(diǎn)運(yùn)行(建立網(wǎng)絡(luò)的時(shí)候設(shè)定的),通過(guò)該節(jié)點(diǎn)則進(jìn)入alpha網(wǎng)的下一個(gè)節(jié)點(diǎn),直到進(jìn)入alpha memory。否則跳轉(zhuǎn)到下一條判斷路徑。
  • 將alpha memory的結(jié)果加入到beta memory中,如果不為T(mén)erminal節(jié)點(diǎn),則檢測(cè)另一個(gè)輸入集合中是否存在滿足條件的事實(shí),滿足則執(zhí)行join,進(jìn)入到下一個(gè)beta memory重復(fù)執(zhí)行3。若另一個(gè)輸入集合無(wú)滿足條件的事實(shí),返回到2。如果該節(jié)點(diǎn)為T(mén)erminal節(jié)點(diǎn),執(zhí)行ACT并添加到facts中。

3.3.3 Rete算法實(shí)例

上面介紹的這些都偏理論化,可能有一點(diǎn)不太容易理解,沒(méi)關(guān)系,接下來(lái)咱們用一個(gè)具體的例子,看看Rete算法到底是如何運(yùn)行的。咱們依然以這個(gè)選拔籃球苗子的例子來(lái)說(shuō)明。

圖片圖片

  • 首先看下對(duì)應(yīng)的網(wǎng)絡(luò)圖

圖片圖片

  • Rete匹配過(guò)程
  • 匹配過(guò)程詳解

A節(jié)點(diǎn):拿StudentFact的年級(jí)數(shù)值進(jìn)行年級(jí)匹配,如果年級(jí)符合條件,則把該StudentFact的引用記錄到A節(jié)點(diǎn)的alpha內(nèi)存區(qū)中,退出年級(jí)匹配。

B節(jié)點(diǎn):拿StudentFact的性別內(nèi)容進(jìn)行性別匹配,如果性別符合條件,則把該StudentFact的引用記錄到B節(jié)點(diǎn)的alpha內(nèi)存區(qū)中,然后找到B節(jié)點(diǎn)左引用的Beta節(jié)點(diǎn),也就是C節(jié)點(diǎn)。

C節(jié)點(diǎn):C節(jié)點(diǎn)找到自己的左引用也就是A節(jié)點(diǎn),看看A節(jié)點(diǎn)的alpha內(nèi)存區(qū)中是否存放了StudentFact的引用,如果存放,說(shuō)明年級(jí)和性別兩個(gè)條件都符合,則在C節(jié)點(diǎn)的Beta內(nèi)存區(qū)中存放StudentFact的引用,退出性別匹配。

D節(jié)點(diǎn):拿StudentFact的年齡數(shù)值進(jìn)行年齡條件匹配,如果年齡符合條件,則把該StudentFact的引用記錄到D節(jié)點(diǎn)的alpha的內(nèi)存區(qū)中,然后找到D節(jié)點(diǎn)的左引用的Beta節(jié)點(diǎn),也就是E節(jié)點(diǎn)。

E節(jié)點(diǎn):E節(jié)點(diǎn)找到自己的左引用也就是C節(jié)點(diǎn),看看C節(jié)點(diǎn)的Beta內(nèi)存區(qū)中是否存放了StudentFact的引用,如果存放,說(shuō)明年級(jí),性別,年齡三個(gè)條件符合,則在E節(jié)點(diǎn)的Beta內(nèi)存區(qū)中存放StudentFact的引用,退出年齡匹配。

F節(jié)點(diǎn):拿StudentFact的身體數(shù)值進(jìn)行身體條件匹配,如果身體條件符合,則把該StudentFact的引用記錄到D節(jié)點(diǎn)的alpha的內(nèi)存區(qū)中,然后找到F節(jié)點(diǎn)的左引用的Beta節(jié)點(diǎn),也就是G節(jié)點(diǎn)。

G節(jié)點(diǎn):G節(jié)點(diǎn)找到自己的左引用也就是E節(jié)點(diǎn),看看E節(jié)點(diǎn)的Beta內(nèi)存區(qū)中是否存放了StudentFact的引用,如果存放,說(shuō)明年級(jí),性別,年齡,身體四個(gè)條件符合,則在G節(jié)點(diǎn)的Beta內(nèi)存區(qū)中存放StudentFact的引用,退出身體匹配。

H節(jié)點(diǎn):拿StudentFact的身高數(shù)值進(jìn)行身高條件匹配,如果身高條件符合,則把該StudentFact的引用記錄到H節(jié)點(diǎn)的alpha的內(nèi)存區(qū)中,然后找到H節(jié)點(diǎn)的左引用的Beta節(jié)點(diǎn),也就是I節(jié)點(diǎn)。

I節(jié)點(diǎn):I節(jié)點(diǎn)找到自己的左引用也就是G節(jié)點(diǎn),看看G節(jié)點(diǎn)的Beta內(nèi)存區(qū)中是否存放了StudentFact的引用,如果存放了,說(shuō)明年級(jí),性別,年齡,身體,身高五個(gè)條件都符合,則在I節(jié)點(diǎn)的Beta內(nèi)存區(qū)中存放StudentFact引用。同時(shí)說(shuō)明該StudentFact對(duì)象匹配了該規(guī)則,形成一個(gè)議程,加入到?jīng)_突區(qū),執(zhí)行該條件的結(jié)果部分:該學(xué)生是一個(gè)籃球苗子。

3.3.4 Rete算法的優(yōu)點(diǎn)

  • 可共享node和memory,提高效率;
  • memory存儲(chǔ)中間結(jié)果,空間換時(shí)間,避免重復(fù)計(jì)算;
  • Rete 匹配速度與規(guī)則數(shù)目無(wú)直接關(guān)系,因?yàn)閒act只有滿足本節(jié)點(diǎn)才會(huì)繼續(xù)向下沿網(wǎng)絡(luò)傳遞。

3.3.5 Rete算法的缺點(diǎn)

規(guī)則的條件與facts的數(shù)目如果過(guò)大,對(duì)應(yīng)memory會(huì)指數(shù)級(jí)升高,極端情況下會(huì)耗盡系統(tǒng)資源。

3.3.6 Rete算法使用建議

  • 容易變化的規(guī)則盡量置后匹配,可以減少規(guī)則的變化帶來(lái)規(guī)則庫(kù)的變化。
  • 約束性較為通用或較強(qiáng)的模式盡量置前匹配,可以避免不必要的匹配。
  • 針對(duì) Rete 算法內(nèi)存開(kāi)銷(xiāo)大和facts增加刪除影響效率的問(wèn)題,技術(shù)上應(yīng)該在 AlphaMemory 和 BetaMemory 中,只存儲(chǔ)指向內(nèi)存的指針,并對(duì)指針建里索引(可用 hash 表或者非平衡二叉樹(shù))。
  • Rete 算法 JoinNode 可以擴(kuò)展為 AndJoinNode 和 OrJoinNode,兩種節(jié)點(diǎn)可以再進(jìn)行組合。

看完這個(gè)匹配的過(guò)程,相信大家對(duì)規(guī)則引擎中常用的Rete算法有了一定的了解?;氐揭?guī)則引擎,那為啥用規(guī)則引擎呢,也就是它有何優(yōu)勢(shì),以及有哪些適用的場(chǎng)景呢?

3.4 規(guī)則引擎優(yōu)勢(shì)

  1. 高靈活性:規(guī)則保存在知識(shí)庫(kù)中,規(guī)則變動(dòng)可以輕易做出修改。
  2. 容易掌控:規(guī)則比過(guò)程代碼更易于理解,因此可以有效地來(lái)彌補(bǔ)業(yè)務(wù)人員和開(kāi)發(fā)人員之間的溝通問(wèn)題。
  3. 降低復(fù)雜度:在程序中編寫(xiě)大量的判斷條件,很可能是會(huì)造成一場(chǎng)噩夢(mèng)。使用規(guī)則引擎卻能夠通過(guò)一致的表示形式,更好的處理日益復(fù)雜的業(yè)務(wù)邏輯。開(kāi)發(fā)人員也可以更關(guān)注邏輯處理,而無(wú)需過(guò)多關(guān)注邏輯判斷。
  4. 可重用性:規(guī)則集中管理,可提高業(yè)務(wù)的規(guī)則的可重用性。而且,傳統(tǒng)的代碼程序通常會(huì)添加不必要的變數(shù),很難進(jìn)行重復(fù)利用。
  5. 規(guī)則外部化:即有利于規(guī)則知識(shí)的復(fù)用,也可避免改變規(guī)則時(shí)帶來(lái)的代碼變更問(wèn)題。

3.5 規(guī)則引擎使用場(chǎng)景

一般多用于規(guī)則較多且規(guī)則調(diào)整頻繁的業(yè)務(wù)場(chǎng)景,比如:積分規(guī)則、計(jì)費(fèi)系統(tǒng)、信用風(fēng)險(xiǎn)評(píng)估、監(jiān)控告警、工作流系統(tǒng)。

3.6 規(guī)則引擎的分類

網(wǎng)上有兩種分類方式,這里我列舉出來(lái),供大家了解。

  • 基于實(shí)現(xiàn)方式
  • 基于完成度和功能配置

圖片圖片

四、商機(jī)流轉(zhuǎn)問(wèn)題解決方案

了解了上面這些業(yè)務(wù)背景以及遇到的問(wèn)題,也熟悉了規(guī)則引擎的理論知識(shí),現(xiàn)在需要制定具體的解決方案了,我們?cè)趺醋龅哪??市面有各種各樣的規(guī)則引擎,先進(jìn)行技術(shù)選型,這里列舉下當(dāng)前主流規(guī)則引擎優(yōu)缺點(diǎn)。

圖片圖片

通過(guò)各方面綜合評(píng)估,重點(diǎn)放到了Drools和easyRule兩者,且easyRule最終勝出。

4.1 Drools和easyRule對(duì)比

圖片圖片

確定了要使用easyRule就得知道easyRule如何使用的,先介紹下其相關(guān)概念和使用方法。

4.2 easyRule插件介紹

4.2.1 規(guī)則說(shuō)明

  • name:規(guī)則命名空間中的唯一規(guī)則名稱
  • description:規(guī)則的簡(jiǎn)要描述
  • priority:規(guī)則的優(yōu)先級(jí)
  • facts:觸發(fā)規(guī)則時(shí)的一組已知事實(shí)
  • conditions:在給定一些事實(shí)的情況下,為了應(yīng)用該規(guī)則,需要滿足的一組條件
  • actions:滿足條件時(shí)要執(zhí)行的一組操作(可能會(huì)添加/刪除/修改事實(shí))

4.2.2 規(guī)則定義方式

  • 通過(guò)在POJO上添加注解來(lái)聲明
  • 通過(guò)RuleBuilder API編程

4.2.3 組合規(guī)則用法

Easy Rules提供了3種CompositeRule的實(shí)現(xiàn)。

  • UnitRuleGroup:要么應(yīng)用所有規(guī)則,要么不應(yīng)用任何規(guī)則。--要么全用要么不用
  • ActivationRuleGroup:激活規(guī)則組觸發(fā)第一個(gè)適用規(guī)則并忽略組中的其他規(guī)則。--首個(gè)選用
  • ConditionalRuleGroup:條件規(guī)則組將具有最高優(yōu)先級(jí)的規(guī)則作為條件,如果具有最高優(yōu)先級(jí)的規(guī)則的計(jì)算結(jié)果為true,那么將觸發(fā)其余的規(guī)則。--優(yōu)先級(jí)最高說(shuō)了算

4.2.4 自定義優(yōu)先級(jí)

值越低優(yōu)先級(jí)越高。要覆蓋此行為,可重寫(xiě)compareTo()方法以提供自定義優(yōu)先級(jí)策略。

4.2.5 引擎執(zhí)行模式

  • skipOnFirstAppliedRule:當(dāng)一個(gè)規(guī)則成功應(yīng)用時(shí),跳過(guò)余下的規(guī)則。--一個(gè)成功,不管其他
  • skipOnFirstFailedRule:當(dāng)一個(gè)規(guī)則失敗時(shí),跳過(guò)余下的規(guī)則。--一個(gè)失敗,不管其他
  • skipOnFirstNonTriggeredRule:當(dāng)一個(gè)規(guī)則未觸發(fā)時(shí),跳過(guò)余下的規(guī)則。--一個(gè)不符合,不管其他
  • rulePriorityThreshold:當(dāng)優(yōu)先級(jí)超過(guò)指定的閾值時(shí),跳過(guò)余下的規(guī)則。--優(yōu)先級(jí)達(dá)標(biāo),不管其他

4.2.6 多種監(jiān)聽(tīng)器可供選擇

支持自定義規(guī)則監(jiān)聽(tīng)器、規(guī)則引擎監(jiān)聽(tīng)器。

4.2.7 表達(dá)式語(yǔ)言支持

支持MVEL、SPEL表達(dá)式語(yǔ)言,可通過(guò)編程方式定義規(guī)則。

4.2.8 規(guī)則中的錯(cuò)誤處理

  • 對(duì)于條件求值過(guò)程中可能發(fā)生的任何運(yùn)行時(shí)異常(丟失事實(shí)、表達(dá)式中輸入錯(cuò)誤等),引擎將記錄一個(gè)警告,并認(rèn)為條件求值為false。
  • 對(duì)于任何在執(zhí)行操作時(shí)可能發(fā)生的運(yùn)行時(shí)異常(丟失事實(shí)、表達(dá)式中輸入錯(cuò)誤等),該操作將不會(huì)執(zhí)行,引擎將記錄一個(gè)錯(cuò)誤。

4.3 easyRule使用樣例

還是用篩選籃球苗子的例子

圖片圖片

  • 定義一個(gè)學(xué)生實(shí)體類
public class Student {
    /**
     * 年級(jí)
     */
    private Integer grade;
    /**
     * 性別
     */
    private String gender;
    /**
     * 年齡
     */
    private Integer age;
    /**
     * 是否強(qiáng)壯
     */
    private Boolean isStrong;
    /**
     * 身高
     */
    private Integer height;
    /**
     * 是否一個(gè)好苗子
     */
    private Boolean isGoodSeed = true;

}
  • 定義規(guī)則(有多種方式,我列舉幾種)
//創(chuàng)建規(guī)則1-年級(jí)
Rule rule1 = new MVELRule()
        .name("grade rule")
        .description("判斷一個(gè)學(xué)生是否是一個(gè)籃球好苗子-年級(jí)")
        .priority(1)
        .when("student.getGrade() <= 3")
        .then("System.out.println(\"年級(jí)-不是好苗子\");")
        .then("student.setIsGoodSeed(false);");
//創(chuàng)建規(guī)則2-性別
Rule rule2 = new MVELRuleFactory(new YamlRuleDefinitionReader()).
        createRule(new FileReader(
                ResourceUtils.getFile("classpath:gender-rule.yml")));

規(guī)則2需要的yml文件內(nèi)容如下:

name: "gender rule"
description: "判斷一個(gè)學(xué)生是否是一個(gè)籃球好苗子-性別"
priority: 2
condition: "student.getGender().equals(\"girl\")"
actions:
  - "System.out.println(\"性別-不是好苗子\");student.setIsGoodSeed(false);"
//創(chuàng)建規(guī)則3-年齡
  Rule rule3 = new MVELRuleFactory(new JsonRuleDefinitionReader()).
          createRule(new FileReader(
                  ResourceUtils.getFile("classpath:age-rule.json")));
//創(chuàng)建規(guī)則4-是否強(qiáng)壯
Condition condition = new MVELCondition("!student.getIsStrong()");
Action action = new Action() {
    @Override
    public void execute(Facts facts) throws Exception {
        Student student1 = (Student) facts.get("student");
        student1.setIsGoodSeed(false);
        System.out.println("強(qiáng)壯-不是好苗子");
    }
};
Rule rule4 = new RuleBuilder()
        .name("strong rule")
        .description("判斷一個(gè)學(xué)生是否是一個(gè)籃球好苗子-是否強(qiáng)壯")
        .priority(4)
        .when(condition)
        .then(action).build();
@Rule(name = "height rule" ,description = "判斷一個(gè)學(xué)生是否是一個(gè)籃球好苗子-身高")
public class HeightRule {
    @Condition
    public boolean checkHeight(){ return student.getHeight() <= 170;}

    @Action
    public void action(){
        System.out.println("身高-不是好苗子");
        student.setIsGoodSeed(false);
    }
    private Student student;
    public HeightRule(Student student){
        this.student = student;
    }
}
//創(chuàng)建規(guī)則5-身高
HeightRule rule5 = new HeightRule(student);
  • 創(chuàng)建實(shí)例(fact)
//創(chuàng)建一個(gè)Student實(shí)例(Fact)
  Student student = new Student(3,"girl",9,true, 160,true);
  Facts facts = new Facts();
  facts.put("student", student);
  • 創(chuàng)建引擎,并執(zhí)行規(guī)則
//注冊(cè)規(guī)則
Rules rules = new Rules();
rules.register(rule1);
rules.register(rule2);
//rules.register(rule3);
rules.register(rule4);
rules.register(rule5);

//創(chuàng)建規(guī)則執(zhí)行引擎,并執(zhí)行規(guī)則
RulesEngine rulesEngine = new DefaultRulesEngine();
System.out.println("開(kāi)始判斷是否是一個(gè)籃球苗子:" + JSON.toJSONString(student));
rulesEngine.fire(rules, facts);
System.out.println("是否為好苗子:" + student.getIsGoodSeed());
  • 執(zhí)行結(jié)果

圖片圖片

4.4 商機(jī)流轉(zhuǎn)如何接入easyRule

熟悉了easyRule如何使用的,接下來(lái)看看我們?nèi)绾卧陧?xiàng)目中落地的,我們分了幾步:

  • 將easyRule工具包進(jìn)行二次改裝,使其執(zhí)行規(guī)則后能有返回值,封裝成jar包,將規(guī)則引擎抽取成通用能力。

初始化規(guī)則相關(guān)配置(首次初始化+定時(shí)更新);

提供對(duì)外public T fire(String ruleId, V v)通用的規(guī)則引擎api接口。

圖片圖片

這里我們將規(guī)則引擎的處理結(jié)果進(jìn)行了返回,因?yàn)闃I(yè)務(wù)上很多場(chǎng)景需要,比如不符合規(guī)則時(shí)的提醒文案。

  • 將現(xiàn)有的流轉(zhuǎn)規(guī)則進(jìn)行整理提取,將各種判斷條件拆解成單一的指標(biāo)判斷。
  • 項(xiàng)目中引入easyRule工具。

項(xiàng)目中配置規(guī)則引擎相關(guān)配置;

實(shí)例化RuleEngineTemplate類;

根據(jù)場(chǎng)景,組裝上下文context;

調(diào)用ruleEngineTemplate.fire(ruleId,context)方法。

圖片圖片

引入后,我們的商機(jī)流轉(zhuǎn)流程發(fā)生了如下變化:

圖片圖片

4.5 商機(jī)解綁流程舉例

  • 商機(jī)解綁流程

圖片圖片

  • 解綁對(duì)應(yīng)的規(guī)則配置application.yml
spring:
  easy-rule:
    priority-threshold: 100
    skip-on-first-failed-rule: false
    skip-on-first-applied-rule: true
    skip-on-first-non-triggered-rule: false
    rules:
      - rule-id: "opportunity_unbind"
        rule-file-location: "opportunity_unbind" #規(guī)則配置文件
        rule-config-type: JSON
        rule-factory-type: SPEL

具體的規(guī)則配置json

[
      {
        "name": "bind_check_cate",
        "description": "判斷是否凍結(jié)-72小時(shí)",
        "condition": "@opportunityUnbindRuleBll.checkOpportunityNeedFreeze(#context.getOpportunityId(), n,m)",
        "priority": 4,
        "actions": [
          "@clueOpporBll.unbindOpportunity(#context,T(OpportunityStatusEnum).UNBIND, T(com.clue.enums.OpportunityMinorStatusEnum).UNBIND_FROZEN)"
        ]
      },
      {
        "name": "task_bind_out",
        "description": "任務(wù)商機(jī)流回公海",
        "condition": "#context.getOpportunityStatus() == T(com.enums.OpportunityStatusEnum).TASK && #context.getOperationTypeEnum() == T(com.OpportunityOperationTypeEnum).TASK_BACK_PUBLIC",
        "priority": 5,
        "actions": [
          "@clueBll.unbindOpportunity(#context,T(com.zhuanzhuan.biz.clue.enums.OpportunityStatusEnum).UNBIND, T(com.OpportunityMinorStatusEnum).UNBIND_NORMAL)"
        ]
      },
      {
        "name": "unbind_operate",
        "description": "判斷解綁后去向,現(xiàn)階段全部回到公海",
        "condition": "true",
        "priority": 10,
        "actions": [
          "@clueOpportunityBll.unbindOpportunity(#context,T(com.OpportunityStatusEnum).UNBIND, T(com.enums.OpportunityMinorStatusEnum).UNBIND_NORMAL)"
        ]
      }
    ]
  }
]
  • 業(yè)務(wù)代碼
public Result<ParallelExecuteDTO> unbindOpportunity(UnbindOpportunityRequest request) {
  return parallelExecutor.parallelExecute(request.getOpportunityIds(), (Long opportunityId) -> {
            final Result<String> unbindResult = opportunityUnbindRuleBll.unbindOpportunity(opportunityId, request.getOperator(),
                  request.getReasonType(), request.getReasonDesc(), request.getOperationType());
            logger.info("method=unbindOpportunity, act=unbind, opportunityId={},unbindResult={}", opportunityId, unbindResult);
            return unbindResult;
            }
        );
    }

4.6 引入規(guī)則引擎前后效果對(duì)比

圖片圖片

五、總結(jié)

在easyRule引入商機(jī)流轉(zhuǎn)業(yè)務(wù)過(guò)程中,從調(diào)研到選型再到最終落地,遇到了各種大大小小的問(wèn)題,但最終的效果還是比較明顯的,對(duì)團(tuán)隊(duì)的整體效率提升非常明顯,這里有幾點(diǎn)總結(jié)與建議與大家分享。

  1. 系統(tǒng)引入規(guī)則引擎,一定要場(chǎng)景符合,不能為了引入而引入;
  2. 業(yè)務(wù)規(guī)則轉(zhuǎn)換為抽象的規(guī)則配置,可以多和業(yè)務(wù)人員交流,他們對(duì)于規(guī)則的理解可能更深刻;
  3. 選擇規(guī)則引擎方案后,需要定好規(guī)則維護(hù)規(guī)范,后續(xù)執(zhí)行按照規(guī)范維護(hù);
  4. 對(duì)于集群中沒(méi)有直接引用的代碼,不要直接清理,有可能是在規(guī)則文件里有引用。

作者介紹

楊迎,轉(zhuǎn)轉(zhuǎn)商業(yè)后端開(kāi)發(fā)工程師,目前負(fù)責(zé)商業(yè)B端相關(guān)業(yè)務(wù)系統(tǒng)開(kāi)發(fā)(商機(jī)線索、客戶運(yùn)營(yíng)、銷(xiāo)售運(yùn)營(yíng)管理、廣告發(fā)布等)。

責(zé)任編輯:武曉燕 來(lái)源: 轉(zhuǎn)轉(zhuǎn)技術(shù)
相關(guān)推薦

2020-08-23 12:02:59

商業(yè)智能商業(yè)分析數(shù)據(jù)

2009-01-18 14:42:09

CRM商業(yè)智能數(shù)據(jù)挖掘

2016-12-16 15:30:41

大數(shù)據(jù)商業(yè)智能

2013-07-18 17:23:43

大數(shù)據(jù)商業(yè)智能化

2023-09-11 06:47:39

2010-12-23 14:38:54

2010-12-07 16:09:25

2017-11-15 10:29:54

芥末堆

2016-09-28 14:39:26

大數(shù)據(jù)商業(yè)采集

2015-08-17 13:07:48

數(shù)據(jù)

2011-03-27 23:28:11

ibmdwBICognos

2017-04-28 17:47:12

智能 CRM

2013-08-29 11:24:31

大數(shù)據(jù)

2021-03-01 11:42:54

人工智能商業(yè)數(shù)據(jù)

2024-02-19 15:59:56

2022-05-23 10:10:21

物聯(lián)網(wǎng)智能商業(yè)建筑

2017-05-19 12:49:18

大數(shù)據(jù)時(shí)空算法商業(yè)決策

2021-10-25 10:46:50

人工智能AI深度學(xué)習(xí)

2021-11-03 10:53:22

人工智能商業(yè)智能軟件

2011-03-29 11:21:47

SQL Server 商業(yè)智能
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)