❔ How to design this code ?
Hi folks, I am having some troubles coming up with a design for the following problem.
I have a Product object that have a several properties (e.g. category (a string), dangerous (a boolean), type (enum), length(int), height(int), weight(int) etc.)
There is a set of rule that allows to set the value of some properties based on conditions on other properties. For example : Set the
Type
property to "Big" when Length
>2 and Weight
>15. Another example : "Set the Dangerous
to true
when Category
== fireworks
.
Those rule must not be harcoded in the code, because our users want to have the possibility to add such rules on their own.
Does anyone have an idea on how to do this ? Some of my pain point are :
- How to model a rule in a nosql database ?
- How to apply it seamlessly on the Product objects etc.16 Replies
Another precision that I need to make here :
Sometimes, I can have rules that are conflictual. For example:
* if
Category
== t-shirts and CustomerId
==2 then set the property LocationInWarehouse
to D
* if Category
== t-shirts and then set the property LocationInWarehouse
to C
Thus, each rule must have a Priority to resolve such kind of conflicts. The Rule with highest priority is applied.The main problem I see with how you have phrased your scenario is this...
If the categorization/validation "rules" of a product are dynamic, then what happens when the categorization/validation rules are changed after there are already products in the system and they are considered invalid after the rule change?
---
In other words... you sound like you should have normal fields and properties, and then you should have other properties that are determined. For example, don't store "Dangerous" as a field in the database/storage. just have a method to determine if a product is "Dangerous" and call the method each time you need to check
"normal properties" versus "computed property"
No actually, there is two options:
The user is asked whether he likes to apply the new rule on existing products in the database or not.
and most likely we need to apply them on existing products to change the value of
Dangerous
based on the new rulewell then you sound like you have your answers:
- apply the rule when a new product is added
- when a rule is changed ask the user if they want to apply to existing products
as for modeling the rules in the database, they need to be composed of the primitive data types just like any other model. It will be tricky as you are figuring out, because figuring out how to model logic is hard. right now you may only need threshold logic (if xx is greater than yy) and thus you may only add that kind of model, but in the future you may need more complex logic like (if xx < yy and zz != aa)
modeling logic in a database is hard
yeah, that's the issue I am trying to wrap my head around. As you said conditions that be somehow complex
I used to work on a tax processing software and we had a bunch of rules that were modeled in a database and we ran the rules on all a company's financials to determine how much tax they owed
the rules were dynamic, but it was a very complex system. not trivial
yeah, that kind of complexity scares me. If it was my project I would not do such dynamic rules but the product owner is not ok :/
I think, on the long run, this may result in a completely unusable system due to high complexity
very possibly. just try to design it to be as flexible as possible. it will be impossible for you to predict the future. you have no idea what kind of rules will be requested
maybe define some fundamental rules such as "ThreshholdRules" and have a different table for each type of rule. "ThresholdRules" might have an
- id
- name
- description
- property of a product that is being thresholded
- value of the product's property that is being thresholded
- whether the threshold is an upper or lower bound
and then you could have other rule types like "EqualsRule" that just means a property must be equal to a given value.
- id
- name
- description
- property of a product
- value of the product's property
might be terrible advice... but just trying to help
but if each type of rule is in it's own table... theoretically you could add rule types in future by adding new tables
yes, that's the strong point of such a design I think, adding a new rule would not result in changing the model of existing rules of other type... in nosql terms that would result in different collections
but the problem is that there is a risk of having too many tables/collections at the end
x<y and z != w is a kind of rule
and x ==y and z ==w is another kind
yeah... that is why in general people try to keep "logic" out of the database
ignoring stored procedures and such
anyways... good luck 🙂
thanks a lot 🙂
I have a terrible idea but maybe it is somehow intresting :
Store each rule as following
{
dangerous : true
conditionsOfApplications : "x < y and z != w and j == k"
}
So the conditions are just stored as a string. Then in the program we parse that string and transform it into logic. Something similar to how a compiler works
I can only agree with ZP, keep this logic in some kind of "EntityRuleEnforcer" that is run upon all objects either after creation or modification.
yeah but how to store things like "x < y and z != w and j == k" that are dynamically set by the user
without having to modify the code after every new rule
My initial thought was to have each "rule" be a
Func<Entity, bool>
and Action<Entity>
if the func returns true for a given object, the action is applied
The problem there being that its hard to have "user created" funcsyup, that "user-created" aspect is what makes it very hard
Was this issue resolved? If so, run
/close
- otherwise I will mark this as stale and this post will be archived until there is new activity.