If you’re doing any Object-Oriented programming, chances are your code is bloated. If you’re working on an enterprise application, even more bloated.
One recurring, boring, time-consuming and error-prone pattern that occurs across the whole codebase and that’s so hard to remove that most OOP programmers just get on with to get their paycheck is the Adapter Pattern, otherwise known as just “glue code”.
Large numbers of object instances laying in your codebase, each with a different API and some methods named after some squeezed-together English words to give a hint at what they do.
Both functions down here perform the same operation of adding data. What’s different is semantics, signature, style, tiny details:
-
setData(items: Item[])
insertItem(item: Item)
Modern AI companies selling point is the culmination of this problem at the largest possible extent, summarised as:
All apps are just CRUD wrappers.
Do you write Object-Oriented code? Chances are you’re no exception, and just writing yet another boring CRUD wrapper yourself.
Not very exciting as a career prospect, is it?
object1.setData(someData);
object1.on('data', data => {
object2.addData(data);
});
object3.init(otherData);
for(object2.items) {
object3.insertData(object2.getItem())
};
setInterval(() => {
if(object2.hasNewData()) {
for(object3.items) {
object4.add(object3.getItem())
}
}
}, 100);
This is no tiny problem, actually.
If we represent code as a graph where vertices are the objects and edges are the glue code connecting them, if there are n
objects, the maximum number of pieces of glue code are, in a worst-case scenario:
Now, let’s talk about the error-prone aspect, in case you didn’t get the scale of this problem.
Unless you are an infallible programmer, you have a probability py
of making one mistake and introducing a bug in a piece of glue code. If you are a good one, your py
value may be lower than the average developer’s pa
probability. We’re in the age of AI and LLMS, but they make mistakes, as well, so they still sit somewhere in this probability scale and have a pl
probability of introducing at least one bug.
With AI getting better and better, it’s reasonable to expect pl
to fall towards 0, without necessarily reaching it exactly. As you get more experienced, your py
value should drop, too. The mass of software developers is constantly filled with junior developers, so our pl
value might just stay where it is.
0 < pl < py < pa < 1
Given the number of glue-code pieces in your OOP application grows quadratically with the number of objects you deal with, as we’ve just seen above, the probability of having a bug, px ( n(n-1)/2 )
, where px
is any of the above py
, pa
, pl
probabilities, is also quadratic, in other words, unacceptably high.
Solving the Glue-Code Problem
Fast forward to the 2020s. We had new programming paradigms such as functional programming, functional-reactive and stream-oriented programming.
The last one in particular claims to solve the glue-code problem by saying all objects should be replaced by streams and speak the same “glue-language”.
No one particular glue language is mandated, so we can resort to some established ones, such as the protocol used by the Observable/Observable interfaces.
// Pushing data
next(data)
// Getting data (either of the two)
subscribe(data)
subscribe({next, error, complete})
What this means in practice
The implication of the above is a reformulation of programs in terms of streams. Each stream is either readable, writeable, or both, but they all observe the same protocol.
By observing the same protocol we can get rid of most if not all custom glue code and a large bug surface from our code.
Can Reactive Streams just replace Objects?
Yes, with no exception.
All Streams are objects with a common interface, so whatever an object can do, a Stream can, as well.
Connecting streams becomes a single operation that can be abstracted away by UI libraries, frameworks or platforms:
> > > > > > > > > > > > > > > > >
source.subscribe(destination)
> > > > > > > > > > > > > > > > >
Formulating problems in SOP
Any problem can be formulated in a Stream Oriented way. Streams are an evolved version of functions that take input events instead of regular parameters and emit data instead of returning values. For the rest, any algorithm can be “embedded” in a stream, if you think of it as a wrapper.
Rimmel.js is the first UI library designed with Stream-Oriented programming in mind. If you like what you’ve seen here you may want to leave a Github ⭐ Star
so we can continue evolving it for you!
Learn More