Author: Little Fu Ge



Warm spring breeze blowing head on, peach blossom more open


Small Fu Ge | bugstack. Cn precipitation, share, grow, and focus on the original project cases, to share knowledge in the most easy to learn programming way, let oneself and others to learn something. Projects completed so far are; Netty4.x practical case, implementing JVM with Java, full-link monitoring based on JavaAgent, handwritten RPC framework, architectural design case, source analysis, etc. You use the sword 🗡, I use the knife 🔪, good code is very burning, hope you don’t stingy move!

One, foreword


Have you ever seen code like this? How about something like that? Well, congratulations on being treated gently by the world!

If else, it’s not really a bad keyword, it’s just somebody broke it. Especially after receiving the product demand as follows;

The date of demand The degree of emergency Programmer (VOICE)
Monday morning Ape brother, the boss said to do some marketing pull quantity, give boys and girls to send different coupons, promote consumption. It’s urgent. I need it after work Okay, it’s not that hard. Add a judgment and go online
Tuesday afternoon Dude, we’ve been great since we got online. Let us according to the young, middle-aged, adult, different age plus judgment, accurate stimulation of consumption. It’s super urgent. I need it tomorrow It’s not hard. Just add it
Wednesday evening Hey, little brother! To sleep! The boss said that our activity was very successful, can we subdivide the single, married and children into different judgments? This is more incentive for users to spend. Thief emergency, online asap. Be aware ofifelseMore and more
Thursday. Early morning A: wow! You guys are so good. You got there so fast. Hee hee! I have a small request, we need to adjust the age group, because now the students of the Student Affairs Office are early, it is easier for those who have a date to buy something. Change the value! Hard work! Boss, waiting! A lot of values to change, oops! So muchifelsethe
Friday. Midnight Say hello! Baba, broken, how to send the wrong coupon, a customer complained, a lot of girls to complain. Look at that. The boss, he… (a sweat), ah, the value of the wrong position! After all, a person carried all

Have you ever come across such a scenario, so is the product for you to go to the ditch, or you take the project to the ditch. You might think, I can’t help it if it’s so urgent. In fact, not only do you have no way, it is to win the market, so that everyone is in a hurry. Only reasonable evaluation, paving, setting up, will continue to meet the business needs, product form changes. Otherwise the road is getting harder and harder!

Second, the scene

Scenarios like the one mentioned above are often encountered in our actual development. Especially in some; Marketing, risk control, crowd, etc., all kinds of user information decision tree relationship, will appear such business logic. And for some larger scenarios, you definitely won’t hardcode if else directly because it’s too difficult to maintain. Unless, of course, you just write it once and use it once.

Next, we will transform the above scenario into a tree structure diagram, which in turn reflects the overall picture of this requirement, as follows;

  • From the figure above, we can see that the decision flow of the product is a tree after the requirements are put together for a week. Each of these different factors can lead to different results.
  • And if the whole content of the product is handed to you from a little bit to a whole package, you’re going to have a different r&d design. Of course, there are also the same, because there are some very far-sighted programmers, they step on the pit all the year round! And this same high design, is stepping on the experience of stepping out of the pit.
  • So, in addition toif elseWhat other solutions can you think of in your own tech stack? Next, we’ll write out two implementations for comparison.

If, else encoding

@Test
public void test_ifelse(a) {
    Result result = null;
    if ("Male".equals(policy.getSex())) {
        if (policy.getAge() < 18) {
            if (policy.getUserSingle()) {
                result = Result.buildResult("A"."A red");
            } else {
                result = Result.buildResult("B"."Red" B"); }}else if (policy.getAge() >= 18 && policy.getAge() <= 30) {
            if (policy.getUserMarry()) {
                result = Result.buildResult("C"."Red C");
            } else {
                result = Result.buildResult("D".Red "D"); }}else if (policy.getAge() > 30) {
            if (policy.getUserParenting()) {
                result = Result.buildResult("E"."E" red);
            } else {
                result = Result.buildResult("F".Red "F"); }}}else if ("Female".equals(policy.getSex())) {
        if (policy.getAge() < 18) {
            if (policy.getUserSingle()) {
                result = Result.buildResult("A".A "yellow");
            } else {
                result = Result.buildResult("B"."Yellow" B"); }}else if (policy.getAge() >= 18 && policy.getAge() <= 30) {
            if (policy.getUserMarry()) {
                result = Result.buildResult("C"."Yellow C");
            } else {
                result = Result.buildResult("D"."Yellow D"); }}else if (policy.getAge() > 30) {
            if (policy.getUserParenting()) {
                result = Result.buildResult("E".Yellow "E");
            } else {
                result = Result.buildResult("F"."Yellow F");
            }
        }
    }
    System.out.println("Decision result (IfElse) :" + result);
}
Copy the code
  • That goes without saying, as long as it doesif elseWrite out or no problem, but write wrong is not necessarily good, after all, a layer of a layer. That’s a small amount!

Rule engine Drools

The simple way to think about a rules engine is to separate out the parts of your business logic that are changing the behavior rules and processes. To a separate rules engine for processing. In the end, you just need to provide the configuration and input parameters by convention to achieve the result of the rule execution.

Drools (JBoss Rules) is an open source business Rules engine that is easy to access enterprise policies, easy to adjust, and easy to manage. It is fast and efficient and complies with industry standards. It allows business analysts or reviewers to easily view business rules to verify that the coded rules enforce the required business rules.

He slapped her and asked why. Ok, let’s do the above code with Drools and explain it later.

1. Configure the environment

  1. jdk1.8.0
  2. idea + maven3.x
  3. Drools 7.32.0. The Final
  4. Case source code download,Bugstack wormhole stackReply:The source code for
  5. Visual flow chart solution; flowdiagram.itstack.org

2. Engineering structure

itstack-demo-drools-02└ ─ ─ the SRC ├ ─ ─ the main │ ├ ─ ─ Java │ │ └ ─ ─ org. Itstack. The demo │ │ ├ ─ ─ model │ │ │ └ ─ ─ the Policy. The Java │ │ └ ─ ─ Result. Java │ ├ ─ ─ Resources │ │ ├ ─ ─ meta-inf │ │ │ └ ─ ─ kmodule. XML │ │ └ ─ ─ rules │ │ └ ─ ─ tree. DRL │ └ ─ ─ webapp │ └ ─ ─ index. The HTML └ ─ ─ the test └─ Java sci-imp ─ org.sci-imp. Sci-impCopy the code
  • The code in the case can be obtained by following the public account: BugStack wormhole stack, reply keyword **< get source code >**
  • So that’s what we’re talking aboutDroolsThe basic engineering of the rule engine, the way the rule engine is used is not complicated, as long as it is set up in accordance with the convention.

3. Code explanation

Policy.java & defines decision attributes, which are also Fact objects

public class Policy {

    private String sex;            / / gender; Male and female
    private Integer age;           / / age
    private Boolean userSingle;    / / single; Yes/no
    private Boolean userMarry;     / / to get married; Yes/no
    private Boolean userParenting; / / parenting; Yes/no. get/set }Copy the code

Result.java & defines the Result output

public class Result {

    private String code;
    private String info;
    
}    
Copy the code

Meta-inf /kmodule.xml & configuration file

<?xml version="1.0" encoding="utf-8" ? >
<kmodule xmlns="http://www.drools.org/xsd/kmodule">

    <kbase name="rules">
        <ksession name="all-rules"/>
    </kbase>

</kmodule>
Copy the code
  • You can have multiple kModuleskbase, corresponding todrlRule file of
  • kbase name="rules"Name The name must be unique
  • There can be one or more Ksessions under kBase. The name attribute of ksession must be set and unique
  • The default attribute of kbase indicates whether the current KieBase is default. If it is default, the KieBase can be found without the name, but each module can have at most one default KieBase

Rules /tree.drl & rules file

package rules; import org.itstack.demo.model.Policy import org.itstack.demo.Result; global org.itstack.demo.Result res; Rule "red A" when Policy(sex ==" male ", age < 18, userSingle) then res.setresult ("A"," red A"); End rule "red B" when Policy(sex ==" male ", age < 18,! UserSingle) then res.setresult ("B"," red B"); End rule "red C" when Policy(sex ==" male ", age >= 18, age <= 30, userMarry) then res.setresult ("C"," red C"); End rule "red" when Policy(sex == "male ", age >= 18, age <= 30,! UserMarry) then res.setresult ("D"," red D"); End rule "red E" when Policy(sex ==" male ", age > 30, userParenting) then res.setresult ("E"," red E"); End rule "red" when Policy(sex == "male ", age > 30,! UserParenting) then res.setresult ("F"," red F"); End rule "A" when Policy(sex == "female ", age < 18, userSingle) then res.setresult ("A"," YELLOW A"); End rule "yellow B" when Policy(sex ==" female ", age < 18,! UserSingle) then res.setresult ("B"," yellow B"); End rule "yellow C" when Policy(sex ==" female ", age >= 18, age <= 30, userMarry) then res.setresult ("C"," yellow C"); End rule "D" when Policy(sex ==" female ", age >= 18, age <= 30,! UserMarry) then res.setresult ("D"," D"); End rule "yellow E" when Policy(sex ==" female ", age > 30, userParenting) then res.setresult ("E"," yellow E"); End rule "yellow F" when Policy(sex ==" female ", age > 30,! UserParenting) then res.setresult ("F"," yellow F"); endCopy the code
  • Rule name, when then end a set of combinations, under what conditions output what results
  • Sex == "female ", age > 30,! userParenting“, separated by a comma is the condition of and, equivalent to your and. Not exactly, because in subsequent processing, the comma processing logic is optimized in Drools.
  • Then processes the result and returns the result information. This result uses the one we setglobalGlobal import. End end keyword.
  • Maybe you don’t think it’s very yoursif else? But don’t feel that way, because this is just the tip of the iceberg. And we previously screenshot a tree structure, and this attribute structure can be generated automaticallyDRLRule file.

4. Perform the test

The startup process for Drools is set up in apitest.java & unit tests

public class ApiTest {

    private KieContainer kieContainer;
    private Policy policy;

    @Before
    public void init(a) {
        / / build KieServices
        KieServices kieServices = KieServices.Factory.get();
        kieContainer = kieServices.getKieClasspathContainer();

        policy = new Policy();
        policy.setSex("Male");
        policy.setAge(16);
        policy.setUserSingle(false);
        policy.setUserMarry(false);
        policy.setUserParenting(false);
        System.out.println("Decision request:" + JSON.toJSONString(policy));
    }

    @Test
    public void test_drools(a) {
        KieSession kieSession = kieContainer.newKieSession("all-rules");
        kieSession.insert(policy);
        Result result = new Result();
        kieSession.setGlobal("res", result);
        int count = kieSession.fireAllRules();

        System.out.println("The Fire rule (s) :" + count);
        System.out.println("Drools:"+ result); kieSession.dispose(); }}Copy the code

The init () initialization

  1. In the initialization method, buildKieServices.Factory.get();, this process is relatively resource – consuming and will not be built frequently in actual business use.
  2. fromKieServicesTo deriveKieContainerContainer for all kieBases of the given KieModule.
  3. Set FACT objects, which are just conditional values for your decision object.

Test_drools () executes the rule

  1. Gets the session named all-rules in the configuration in kmodule.xml, which is stateful by default.
  2. Setting decision ObjectskieSession.insert(policy);
  3. Setting global ObjectskieSession.setGlobal("res", result);Is used to finally output the result
  4. Start executing ruleskieSession.fireAllRules()
  5. Finally output results, finally release resourceskieSession.dispose()

The test results

Decision request: {"age":16."sex":"Male"."userMarry":false."userParenting":false."userSingle":false}
Fire rule(s): 1 Decision result(Drools)B: B | redCopy the code
  • You can try to modify the input parameter information during testing to verify different results.

5. Understanding of Rete algorithm

Drools is an open source rules engine written in the Java language that evaluates written rules using the Rete algorithm. Drools allows business logic to be expressed declaratively. Rules can be written in native languages other than XML, making them easy to learn and understand. Also, you can embed Java code directly into rules files, which makes learning Drools even more appealing.

Good! So you know, Drools is all about implementing the Rete algorithm. Let’s take a look at Rete.

In order to solve the problem of low efficiency of production-type reasoning engine, Forgy proposed Rete algorithm in 1979 as an efficient pattern matching algorithm for production-type system. The original purpose of Rete algorithm is to reduce the rule storage by using the common parts of each domain between rules, while saving the temporary results of the matching process to speed up the matching. In order to achieve this effect, the algorithm splits the rules, in which each condition unit is connected to a data discrimination network as a basic unit (node), and then the facts are filtered and propagated through the network. Finally, all the conditions are activated with fact-matching rules.

Since the Rete algorithm was proposed in 1979, it has undergone various improvements and expansions. In addition to the optimization of self-rule network structure, there are also many researches on some function extensions such as fuzzy reasoning, event reasoning and parallelization.

1. Structural optimization

  1. Processing of mixed logic characters

    Operators are logical operators that inject and, OR, not, etc.

  2. Reordering of rule precursors

    Rule antecedent order refers to the order of each constraint in the rule body. It determines the execution order of conditional link operations, affects the size of intermediate results, and is a key factor to determine the efficiency of rule matching.

  3. Index method

    The index method is to establish the index of the current node to the successor of nodes in the Rete network. In fact assertion, the index can be used to quickly find the corresponding successor nodes without searching one by one.

2. Function expansion

  1. Rete was originally used to handle only first-order Boolean logic, but many Rete extensions are now used to handle other logic.

  2. Event processing retes with time information express current state through facts, but many applications include some time in the event stream that plays a key role in the parallel execution of events. Therefore, Rete algorithm is needed to process these information.

3. Inference of special data

  1. Flawed data and uncertain inference

    • Is not correct
    • Don’t precision
    • inconsistencies
  2. Fast-changing data and machine learning

    In addition to data defects, Rete algorithm also needs to solve problems for the data with drastic changes.

4. The parallelization

Since the Rete algorithm was put forward, performance improvement has been the focus of research. After the advent of multi-core and multi-processor, it has become a common efficiency improvement method to distribute the inference process to different machines for parallel processing

Six, summarized

  • Great products, great r&d, never just a microphone or a tool machine. But a craftsman with a soul, need to have a plan, decision-making, vision.
  • Drools are not only used in this way, but also in a variety of ways. This chapter is mainly the beginning and will be further improved. About the engineering code can follow the public number (BugStack wormhole stack) to obtain.
  • Only if your stack is comprehensive enough can you have a solution in N when you encounter a problem. But learning must be their own thing, whether busy or idle, to let their recharge. Entertainment is not impossible, but to control themselves properly.If you don't control yourself, someone else will