Stream Oriented Programming (SOP, SP) is an emerging paradigm evolved from principles of Reactive, Declarative, Functional and Dataflow programming that models applications as a composition of reactive streams and side effects as a set of declarative connections to the external world.
Streams can be defined using various primitives, whether imperative or functional. These include Observables, Signals, Callbags, Callforwards, objects and even plain functions. Among these, Observables are the most mature and feature-rich, currently on their way to becoming a web standard.
The Power of Composition: data flow vs control flow
Reactive streams are inherently composable. They can be grouped into higher-level abstractions that remain consistent in interface and behaviour: data in, data out.
Connecting streams is a trivial, mostly declarative operation, as they all expose a common interface for both pushing and pulling data.
This allows developers to construct complex applications from smaller, reusable units while ensuring consistency and eliminating redundancy.
When every stream speaks the same language, as opposed to objects in OOP each having their own, unique interface, the creation of large applications becomes easier to build, test, and maintain. The focus shifts from how to instantiate, extend and connect objects to transform data from one type to another and stitch it together.
Defining a Stream
A reactive stream is not a magical construct but rather a well-structured design pattern. A stream:
- Accepts data or events as input
- Optionally processes that data
- Optionally emits new data as output
This processing can be synchronous or asynchronous, and streams can be composed to aggregate or transform data from other streams. Examples include RxJS’s Subject and BehaviorSubject.
Practical Use Cases
Streams already underpin many real-world systems:
- Big Data pipelines have long employed similar principles for scalability and throughput.
- Cloud-native development often applies stream-oriented thinking at the architectural level.
- User interfaces are a natural fit: everything from button clicks and navigation flows to sequences of modal dialogs can be represented as streams. A mouseover is a stream, a dialog box is a stream, and an entire application can be modelled as a stream.
Despite these natural fits, most mainstream UI frameworks are still primarily imperative in design. SP introduces a novel approach, particularly in web development, by offering a consistent reactive model across the entire stack.
How Streams Simplify Code
In traditional architectures, much effort is spent writing glue code to move data between components:
// glue code
target1.data = source1.data
target2.setData(source2.data)
source3.on('data', data => target.doSomethingWith(data))
With streams, this complexity disappears. You connect streams declaratively, ensuring that type compatibility alone dictates whether the connection is valid. By eliminating these imperative steps, a major source of application bugs is removed.
Working with Streams
The workflow begins by defining streams and then binding them declaratively within templates. The framework handles the wiring automatically:
const Component = () => {
const stream1 = SomeStream();
const stream2 = SomeStream();
const stream3 = SomeStream();
return rml`
<button onclick="${stream1}">click me</button>
<div>${stream2}</div>
<div class="${stream2}" onmousemove="${stream3}">
${stream3}
</div>
`;
}
This illustrates the essence of SP: streams are defined first and then composed declaratively in a way that maps directly to user interactions and application logic, often wrapped in a reusable, composable component.
A pioneer of SP in practice is Rimmel.js, the first UI library designed all around streams to create modern, async, responsive web applications.
For live demonstrations, see this Stackblitz collection or explore additional examples. These resources showcase SP principles in action across a wide variety of scenarios.
Future Directions and Challenges
While SP shows remarkable promise, several key challenges and opportunities remain:
- Standardisation: Observables are moving toward becoming a web standard, but their current design isn't streams-first.
- Tooling and ecosystem support: The success of SP depends on strong ecosystem adoption. Developer tools, UI libraries, components, utilities.
- Learning curve: Many developers are familiar with imperative programming. Shifting to a fully declarative, stream-based mindset requires new patterns of thinking and training.
- Community-driven innovation: SP is shaped by both theory and experimentation. The community’s role in identifying best practices, anti-patterns and optimal architectures will determine its trajectory.
As these challenges are addressed, SP has the potential to reshape modern software development by providing a consistent, composable, and future-proof programming model.




Top comments (0)