Smart Trains 1

ST 8 Dual Roles of Hierarchy in Software Architecture

In the previous post we looked at the state hierarchy of the Train state machine which automatically drives a model train between two stations. It receives an ARRIVING event from the hall-effect sensor and sends a MOTOR_RUN_REQ to set the speed of the motor.

This event abstraction makes the Train state machine easy to understand. We don’t need to care about how a hall-effect sensor picks up the magnetic signal, or how to use PWM to control the direction and speed of a motor. We call this a separation of concern or decoupling, which is the rationale for a component-based architecture.

We partition the system into components based on roles and responsibilities. We organize them into a hierarchy, with the topmost component modeling the most abstract behaviors and those at the bottom modeling the most detailed behaviors. Every component is a hierarchical state machine (HSM), and they communicate with each other through events (or dedicated channels managed by events).

This architectural pattern is called the Hierarchical Control Pattern [1]. Hierarchy plays double roles here. The overall system is partitioned into a hierarchy of components, with each component acting as a hierarchical state machine internally.

When we see this model train running in the garden, we don’t just see variables, loops or if-else blocks, but rather concurrent communicating hierarchical state machines each faithfully performing its own duties.

[1] H. Gomaa, Real-Time Software Design for Embedded Systems. Cambridge University Press, 2016.