Reactive Embedded Design Principles

This article attempts to capture the fundamental principles that underpin the "why" of the various design choices that I make within the reactive embedded system domain.

Although there are no absolute rules when it comes to design choices (there is a time and place for every technique,) these principles serve as a foundation for decision making against which choosing an alternative must be carefully considered and justified.

Dynamic Memory

Most embedded software people agree that dynamic memory alloction (e.g. malloc/free, new/delete) is an inappropriate technique to be used in a system that must continue to execute indefinitely. The article Memory Management In Embedded Systems discusses this more completely.

Reactive embedded systems can be very dynamic, and while traditional dynamic memory functions are convenient, they are inappropriate for most embedded work. Dynamic memory management is best done explicitly using techniques specifically designed for a particular type of application. This may appear more cumbersome, but there are common patterns and techniques, which become second-nature with practice.

Static Compile-Time Checking

Taking advantage of the ability of a toolchain to check software prevents many defects that can otherwise be difficult to find.

By using specific types and refraining from quick-and-dirty techniques (e.g. unnecessary casting) programmers/designers can employ the help of the toolchain to create highly reliable software.

Practioners should strive to express the conditions and invariants of an interface using the appropriate facilities of the language.

Sooner Than Later Run-Time Checking

There are times when system limits cannot be checked by the toolchain. When this happens, it is a good practice to expose any resource limitations during run-time initialization. In other-words, pre-allocate the resource in "main()" and produce an error at startup rather than waiting for the error to come up during run-time, which may remain hidden until an infrequently excersized set of conditions are met.

Client Owns The Memory

Separate Creational Interfaces

Loose Coupling

Interface vs Implementation

Event Driven

Active Objects, Explicit Behavior via FSM, contrast with algorithm based (e.g. compiler), and GUI applications.

Client-Server Relationships

Client-Server Active Object Notation