-
Notifications
You must be signed in to change notification settings - Fork 482
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Condition Sharing #339
Condition Sharing #339
Conversation
fix the link to the boolean expressions that broke after not was introduced.
This will allow you to npm install examples and actually run them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A very simple solution for adding additional composability options to the rules engine. I'm a fan.
The lack of result caching is a bit of a bummer but that's something that could be iterated upon in future updates.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Such a simple solution to something that will be super useful!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Underlying implementation looks good.
Per comments let's think hard about the naming and api we're exposing.
README.md
Outdated
@@ -29,6 +29,7 @@ A rules engine expressed in JSON | |||
|
|||
* Rules expressed in simple, easy to read JSON | |||
* Full support for ```ALL``` and ```ANY``` boolean operators, including recursive nesting | |||
* Rule composition / inheritance with the use of shared conditions |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see this as an advanced feature that grows in importance as users begin using the library more extensively; seems like a highly specific thing to mention up front in the readme. Recommend deleting this line
docs/engine.md
Outdated
Adds a shared condition to the engine. Rules may include references to this shared condition. | ||
|
||
```javascript | ||
engine.addSharedCondition('validLogin', { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not simply addCondition()
? Adding new terminology into the mix suggests to the user they need to understand the difference between a shared condition vs a non-shared condition; wondering if we can maintain the single concept of a condition and simply offer this as an upgrade and additional way to use conditions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was doing some googling to try to see what this was called in other rules engines and there doesn't seem to be a good name for these in wide use. So I'm ok with condition
as the name I actually like that in a future state this could be used to add new Condition
subclass constructors which would let make it even more extensible.
docs/engine.md
Outdated
condtions: { | ||
all: [ | ||
{ | ||
uses: 'validLogin' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wondering if condition:
would be more ergonomic, as it clarifies to the user the type of the identifier they need to place in the value, and mentally ties it back to engine.addSharedCondition()
. It'd also be consistent with other existing properties such as fact: <id>
, operator: <id>
. thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah the more time I spend with it the less I like uses
. I'm fine with either condition
or ref
as I think there a more natural term. The one thing with condition
is that it means a rule could be { conditions: { condition: <id> } }
how do we feel about that?
@@ -10,6 +10,6 @@ | |||
"author": "Cache Hamm <[email protected]>", | |||
"license": "ISC", | |||
"dependencies": { | |||
"json-rules-engine": "6.0.0-alpha-3" | |||
"json-rules-engine": "../" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
I think you'll see to add a line to the toJSON helper in order to ensure the |
Add Support for Conditions which are added to the engine and then referenced in various rules. Condition references can be used as top-level conditions in a rule and can be used recursively.
2e4ec69
to
674c2b5
Compare
@CacheControl all comments addressed, looking for a final sign-off before I merge this and put together a point release. |
Add documentation covering the use and advantages of condition sharing. Specifically on the ability to re-use the same condition across multiple rules.
674c2b5
to
371243e
Compare
This introduces the concept of Condition sharing which allows regular conditions that are given a well-known name and to be added to the engine. Rules can reference the condition by including a
condition
property on a condition.example based on #296
This addresses #336, #296, and #263
A few things related to this:
Why do we need this at-all
The ability to capture common conditions and compose rules is useful as a first-class function of this rules engine. As rules reach increased levels of complexity common patterns emerge that should be re-used rather than repeated. One option to do this is to add a "pre-processing" step outside the rules engine that would build up rules from component parts. However this means that someone inspecting the rules as they're run would need to understand the behavior of this pre-processing. Additionally having this be supported by the rules engine allows for more universal editing tools to adopt this as something that can be edited.
Condition references vs. rule-chaining
The primary difference here is that the composition can be communicated using JSON because conditions are fully expressible as JSON. This prevents the javascript code from needing to know about specific rules to setup specific event handlers. This allows us to cleanly separate javascript code that configures the rules engine from the rules themselves. Additionally there is no need to specify rule priority when using conditions as the condition references will be resolved at runtime.
Why condition references and not something with facts
I had originally suggested using a "conditional fact" or other construct to capture the idea of re-used logic. This was nice because it matched concepts that already existed in the rules engine. However it fails the equivalency test. Extracting re-used conditions into a fact would cause the rule results to be different. I liked that the use of Conditions and the approach of de-referencing the condition references at runtime would keep the same structure to the rule results even after refactoring.
Concern with duplicated work.
Condition references are dereferenced and evaluated within each rule they're part of. That means that if a condition is used in 10 rules it will be evaluated 10 times. I'm not concerned about this as the majority of the work will be captured by the Fact value caching in the almanac. The work that is left to be done ought to be very quick. While the possibility of result caching does exist as a future improvement adding it here seemed unnecessarily complex.