I stumbled on an interesting case study that explained how Tektronix explored three different software architectures and found that dataflow best met their needs.
Tektronix is the name-brand manufacturer of electronic measurement test equipment. Among other things, they design and manufacture oscilloscopes which are small, TV like devices that display waveforms. While they use to literally use tinny CRTs and analog components, oscilloscopes are now complex digital devices that use embedded software to control their operation.
The company found that software development for oscilloscopes was getting out of hand. There was very little reuse of existing code in new equipment designs. Every new scope required their software developers to start from scratch.
In an effort to reduce development costs, Tektronix explored three different architectures as the basis for their new software development: object oriented, layered and dataflow.
Initially an OO hierarchy was designed. But it quickly became apparent that it was not going to work. There were questions as to what class particular functionality belonged. Cross cutting concerns have always been difficult to represent with the strict type hierarchy that OOP requires.
Next a layered model was designed. There were layers for hardware, digitization, visualization and the user interface. But this architecture did not take into account that the oscilloscope user needs to be able to configure parameters in all of the layers to adjust the waveform view. How should the the user interface layer change parameters in a lower layer?
Finally, they built a dataflow model. It perfectly matched the problem domain where a signal is incrementally transformed until it is displayed. Parameters from the user interface could directly feed into any node. Yet this too had problems. The pure dataflow model was too slow for their needs due to each node copying the waveform data. Their solution was to create different types of node ports. Some eliminated copying the waveform while other allowed the node to ignore unneeded data if it was running behind.
This summary is from "An Introduction to Software Architecture" by David Garlan and Mary Shaw.