I am developing an application that needs to programmatically determine the complete state of a DC motor, given a limited number of details about the state. For example:
{
voltage: Measurement(12, "V"),
rpm: Measurement(5000, "rpm"),
currentDraw: undefined,
torque: undefined
}
This object would be passed to a function that calculates the values of currentDraw
and torque
according to the defined properties of the object. However, it is not always voltage
and rpm
provided - it may be any combination of properties, and the ones listed above are not the only ones available (simplified for the question).
I would like to avoid this logic:
constructor(state) {
if (state.voltage) {
if (state.rpm) {
state.torque = ... ;
state.currentDraw = ... ;
} else if (state.torque) { ... }
...
}
...
}
As it's not clean and difficult to read. Plus with a large number of possible variables, the function would get very large very quickly.
Has anyone solved a similar problem before? All advice welcome.
2 Answers 2
If you have a very large number of variables and hence a growing list of formulas to calculate missings. If moreover, there are identified dependencies in these formulas, the execution logic of your completion algorithm could become quite complex.
One way to solve it would be to use a rule engine. In your case it could be a very simple one:
- It would use a set of rules, i.e. formulas that you can apply.
- Each rule has some conditions, i.e. the variables that are needed to apply it (and perhaps also the missing variable that it determines).
- You'd iteratively go through the set, to find the next one that you could apply.
- Once flagged you can eliminate it from the subsequent iterations
- You can also eliminate from the iteration the formulas for variables that you already have.
This is flexible: it's very easy to add new rules for new variables. It's straightforward to implement, since known variable do not change.
A variant of this approach would be to build a dependency graph derived from the set of rules (nodes=variables and formulas). The graph may allow you to find for each missing variable the formulas (rules) to be used by traversing the graph , and navigating back to the known variables. Order the set of formulas found int the path reversely based on the number of missing dependencies (some more thoughts may ne needed here). This is slightly more complex to implement, but would probably optimize execution. SO if you have a large dataset to be completed, it could be worth giving it a try.
-
1
-
@Justin thank you very much for this feedback. It will help other readers working with JS to benefit from your practical experience.Christophe– Christophe2021年02月05日 07:14:01 +00:00Commented Feb 5, 2021 at 7:14
You are avoiding the simplest solution of them all, push the decision back a layer make the calling code or ultimately the user choose by having different methods for each valid combination of properties
class DcMotor
{
DcMotor(float voltage, float rpm) {...}
DcMotor(float currrentDraw, float torque) {...}
...etc
}
If you cant pre-decide in anyway then the conditional statements are unavoidable as you only have a limited number of hardcoded equations which determine the missing properties.
Using a rule engine simply moves your conditionals from your programming language to the rule engine rule language
-
1According to OP, it may be any combination of properties; therefore it seems to be unfeasible to preset them on overloaded constructors.Emerson Cardoso– Emerson Cardoso2021年02月01日 16:00:47 +00:00Commented Feb 1, 2021 at 16:00
if not X, then calculate X from the properties that must be known and those reconstructed earlier
? That would keep the condition nesting low.