3 ms·
Because it sets what is stored in `state` it does not have to be. It could be inside the if, but there two major reasons why it should not: 1) Testability. Wit
by jononor 10y ago
Because it sets what is stored in `state` it does not have to be. It could be inside the if, but there two major reasons why it should not:
1) Testability.
With it separated, we can write automated tests for our state calculation logic that are hardware independent, like 'normal' code. We just need to create `currentState` data, pass it into our `calculate()` function, and verify the new `state` returned. This can run both on our host-system, and on-target. We can even build simulations if we want, http://www.jonnor.com/2017/03/host-based-simulation-for-embedded-systems/ http://www.jonnor.com/2017/03/host-based-simulation-for-embe... (shameless plug).
2) Deterministic execution time.
Many embedded systems have soft or hard real-time constraints, action must always be performed within X microseconds. The more branches we have the harder it is to reason about whether we can keep this guarantee. By eliminating branches we are executing our 'worst case' always, giving it much more testing.
- jononor 10y agoThis assumes that the call to updatePin is idempotent (calling multiple times with same inputs does not do anything). An update of a I/O pin usually is, but other hardware (or APIs...) might not be. In this case the realization of the state should still be in a separate function for testability. But it can take both `newState, currentState` as arguments, and then do: if (newState.thingon != currentState.thingon) { nonIdempotentUpdate(newState.thingon); } If the device is latency critical, then the functions should be tested in all its permutations. You can use generative techniques like fuzzing to generate the `state` inputs.
- greenleafjacob 10y agocomponentDidUpdate for embedded systems?