Software Engineering Asked by mettleap on December 10, 2021
Background:
I have a JSON object (named JSONConditionObject) which looks like the following,
{
"condition1":"value1",
"condition2":"value2,value3 ..."
//more fields below very likely to be added/changed
//also the nature of values for a condition (String/List) might change as well
//For eg, it can be another json itself
}
I want to read this JSON object -> validate the conditions and if all conditions are true, perform some task.
My Approach:
The best I could think of is the Decorator pattern to make the code extensible/flexible. Each field will be a decorator around a base object (base object will have logic to perform the final task if all conditions are true),
public abstract class ConditionDecorator extends Condition{
private Condition condition; // Condition is the top level abstract class signifying a json condition
@Override
public void apply(Task task) {
if(this.shouldApply(task)){
condition.apply(task);
}
}
}
Then each condition in the JSONConditionObject will have its own class like so,
public class Condition1Context extends ConditionDecorator {
private Condition condition;
private String condition1;
public Condition1Context(Condition condition, JSONConditionObject jsonConditionObject){
super(condition);
this.condition = condition;
this.condition1 = jsonConditionObject.getCondition1();
}
@Override
protected boolean shouldApply(Task task) {
//will have logic for validating condition
...
}
}
Finally, I read the JSONConditionObject and return a variable of type Condition which can be used to validate the conditions one after another. If a new condition is added in the future, I will just have to create a new class for it (like Condition1Context above) and decorate the final Condition object with it.
My Question:
This approach is a bit verbose and leads to generation of a lot of classes in my project (one single class for each condition). Would there be another way which is a bit more elegant and would require lesser code?
When the conditions are not that complex you could use the specification pattern to map your conditions to classes, so having a class per primitive condition which you can combine with logical operations (Specification pattern). Maybe have a look at Java predicates/bipredicates. For generating your specification hierarchy from the JSON, you could write a simple interpreter.
Answered by brckner on December 10, 2021
Validating a dynamic list of conditions to perform some action is a typical use case for a rule engine.
A simple and effective approach is then to use the interpreter pattern for the conditions:
TerminalExpression
which can have several input parametersNonTerminalExpression
context
.This separation between context and condition-expression is very useful when the rules are loaded and then executed several times elsewhere, with different execution context each time.
In your case, the JSON will be the initial source for the evaluation context (i.e. values associated with the condition), and at the same time the main source for building the expression (i.e. which conditions to use) dynamically.
Since the rules itself already use values, you could simplify the design by keeping with the rules an initial context for the parameter values (configuration context), and an execution context when the conditions are applied to objects being validated.
A rule would be a pair: an Expression
that evaluates a JSON condition and a an Action
that is fired if the condition is true. Decoupling the actions from the condition evaluation is key to avoid a combinatorial explosion.
Alternatively, if you have only one dynamic rule and not a list of (potentially interacting) rules, you could very well use a base rule and decorators, but for varying the action, not the conditions.
Answered by Christophe on December 10, 2021
The approach you describe, which basically is a dynamic configuration (JSON) which leads to a hard class structure, seems to generate a lot of ugly code.
You'd have to have some kind of registry to hold the various condition objects, and then create them via reflection (or even worse: through another layer of indirection) and finally somehow tack them together. (... and to lots of error handling on the way, as usual when you take the reflection route.)
As an alternative, I suggest you look into a ready-made business-rules framework. For java, drools (https://www.drools.org/) is well established, relatively easy to set up, and probably suited to your task.
Answered by mtj on December 10, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP