6

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.

lennon310
  • 3,212
Justin
  • 71

2 Answers2

3

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.

Christophe
  • 77,139
  • 1
    Thank you for the recommendation on the rule engine -- I found noolsjs which has provided to be a great method of doing this in JS. – Justin Feb 05 '21 at 03:25
  • @Justin thank you very much for this feedback. It will help other readers working with JS to benefit from your practical experience. – Christophe Feb 05 '21 at 07:14
0

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

Ewan
  • 75,506
  • 1
    According to OP, it may be any combination of properties; therefore it seems to be unfeasible to preset them on overloaded constructors. – Emerson Cardoso Feb 01 '21 at 16:00