Scripting language-based rules engine
preface
In daily development, developers often face a scenario where the logic of business requirements is complex and constantly changing.
The usual way to do this is to stack code based on if else, which is boring and untechnical.
Maintaining such code can also be exhausting and confusing.
We wondered if we could provide a solution to separate dynamic business rules from the main process.
Users can write their own business rules, and the system will translate business rules into code execution, freeing developers from the if else.
case
Let’s assume the business scenario
Scenario 1: Financial risk control
Scenario 2: Deal promotion
Combining the above scenarios, we define the characteristics of the business model:
- There are fixed input parameters and output formats
- The intermediate rules section requires configuration and flexibility as possible
Demand model
Regular data model
We did a data model abstraction for the business scenario
We form rule solutions into variables + conditions + results so that we can convert business rules to implementation code.
The system model
We simply divide the system into two modules: rule executor and rule management.
-
Rule executor
Is responsible for selecting the rule objects that need to be executed (including the order in which the rules are executed) to parse the execution and return the final result.
-
Rule management
Open to development and business, responsible for structured parsing and interchange of business rules and implementation code.
implementation
We divided the system into the following levels to achieve:
Execution of dynamic code scripts requires a scripting language executor.
The conversion of business rules to code scripts requires the structuring of business rule data.
In addition, the ability to delegate to the system the ability for business parties to define their own algorithms in the system is also necessary.
Scripting language executor
In the JVM environment, scripting languages can be Groovy, Scala, JRuby, etc. This scheme adopts another way, using ali’s open source tool QLExpress to achieve.
We have a few feature comparisons between Groovy and QLExpress
Execution engine | Perform type | Expression language | performance | features |
---|---|---|---|---|
Groovy | A compiled | support | high | Java syntax compatibility |
QLExpress | interpreted | support | high | Strong expansibility |
According to our findings, what we need is an engine that supports an expression language, is lightweight, flexible, and extensible.
So we chose QLExpress.
In addition to the features mentioned above, QLExpress also
- Methods that can be bound to Java classes or objects and executed in scripts
- You can customize the extension operators
- Support for collection class parameters
- Seamless integration with Spring
These features are necessary for us to implement the rules engine
QLExpress implementation:
ExpressRunner runner = new ExpressRunner(); DefaultContext<String, Object> context = new DefaultContext<String, Object>(); context.put("a", 1); context.put("b", 2); context.put("c", 3); String express = "a + b * c"; Object r = runner. Execute (Express, context, null, true, false); System.out.println(r);Copy the code
You only need to:
- Provide context parameters (which are generally invariant)
- Processing rule result returned
In this way, we have separated business processes from business rules, and developers have turned over a lot of business logic to the rules engine system through service calls.
Data structure
According to the data model that defines the rules, we split the rules into variables, conditions and results.
Simple conditions, which can consist of variables and logical operators; A rule’s condition can also be composed of multiple simple conditions. Rule results can also be represented by variables.
The source of variables can be context parameters provided by the service or a set of defined algorithms that can be customized by the service user.
Let’s use an example to illustrate these concepts.
A business that has a trading order expects the user to meet the conditions at the same time after placing an order
- The user is located in City A
- The user has not purchased the current item
- Place orders in the evening
We would like to offer a 20% discount for current orders.
We simply define the input parameters of placing orders as user ID and commodity ID. To construct the rule condition, we also need to define some intermediate variables.
- Variable 1 = Gets user location based on user ID
- Variable 2 = Get user purchase records based on user ID and item ID
- Variable 3 = Determine the current time is evening
With three variables as conditions, we can redefine: variable 4 = 20% as the final return.
Therefore, this rule can be equivalent to:
If variable 1 equals A city and variable 2 equals 0 and variable 3 equals true
4 return variables
Thus, we have transformed a concrete business rule into a logical relational record and management of several variables.
The structure of data is realized.
Defining binding methods
In the requirement scenario of business rules, the implementation process of coding usually uses context parameters or temporary variables generated after the calculation of parameters as the components of rules to participate in the business logic operation of rules.
Therefore, the business needs to be able to pre-register custom methods with the script executor, and the script executor can call methods to get business results when executing the relevant code.
We register our business methods into the QLExpress executor by binding QLExpress to Java class or object Method features.
public void functionABC(Long a,Integer b,String c){
System.out.println("functionABC");
}
ExpressRunner runner = new ExpressRunner();
runner.addFunctionOfServiceMethod("abc", singleton,"functionABC",new Class[]{Long.class,Integer.class,String.class},null);
String exp = "abc(a,b,c)";
IExpressContext<String, Object> context = new DefaultContext<String, Object>();
context.put("a",1L);
context.put("b",2);
context.put("c","3");
runner.execute(exp, context, null, false, false);
}
Copy the code
The underlying logic for QLExpress to perform binding Java class object methods is the same as for calls in Java programs, so we can also bind remote methods.
We know that Dubbo can * invoke remote services as if they were local methods, * so we can leave the decision of what methods to bind to the business, increasing the openness of the solution.
conclusion
This article provides a lightweight solution to the rule class requirements.
The rule requirement data is structured parsed and then converted into a scripting language to implement the business rule requirements by executing the scripting language.
This scheme can meet the needs of flexible change of business rules by providing a certain degree of expansion ability while meeting the needs of stable process of business subjects. At present, it has been applied in the merchant transaction and expense reimbursement control business of zhengcai Cloud.
Looking to the future
In the context of huge differences in the needs of businesses, how to meet the flexible customization of businesses and at the same time expand capabilities into universal services to save development costs needs to be improved gradually in the following iterations.
At present, the rule logic only supports a single path, and the implementation of multiple paths or even path nesting rules can be considered later.
In the process of executing the rule script, how to optimize the intermediate variables is also the direction that can be optimized.
In the future, we will continue to build the system from both technical and business aspects to make it easier to use and more efficient.
Recommended reading
Chapter 2 of the JVM series – Class files to virtual Machines
Dapr Combat (part 1)
Dapr Combat part ii
DS version control core principles revealed
DS 2.0 era API operation posture
, recruiting
Zhengcaiyun Technology team (Zero) is a passionate, creative and executive team based in picturesque Hangzhou. The team has more than 300 r&d partners, including “old” soldiers from Alibaba, Huawei and NetEase, as well as newcomers from Zhejiang University, University of Science and Technology of China, Hangzhou Electric And other universities. Team in the day-to-day business development, but also in cloud native, chain blocks, artificial intelligence, low code platform system, middleware, data, material, engineering platform, the performance experience, visualization technology areas such as exploration and practice, to promote and fell to the ground a series of internal technical products, continue to explore new frontiers of technology. In addition, the team is involved in community building, Currently, There are Google Flutter, SciKit-Learn, Apache Dubbo, Apache Rocketmq, Apache Pulsar, CNCF Dapr, Apache DolphinScheduler, and Alibaba Seata and many other contributors to the excellent open source community. If you want to change something that’s been bothering you, want to start bothering you. If you want to change, you’ve been told you need more ideas, but you don’t have a solution. If you want change, you have the power to make it happen, but you don’t need it. If you want to change what you want to accomplish, you need a team to support you, but you don’t have the position to lead people. If you want to change the original savvy is good, but there is always a layer of fuzzy window…… If you believe in the power of believing, believing that ordinary people can achieve extraordinary things, believing that you can meet a better version of yourself. If you want to be a part of the process of growing a technology team with deep business understanding, sound technology systems, technology value creation, and impact spillover as your business takes off, I think we should talk. Any time, waiting for you to write something and send it to [email protected]
Wechat official account
The article is published synchronously, the public number of political cloud technology team, welcome to pay attention to