Empty subscribes

Photo by Jack Anstey on Unsplash

Empty subscribes

A code smell that could ruin your codebase

I've seen a lot of frontend code recently and what bugs me are empty subscribes. If your framework is using Observables instead of Promises, subscribing is important. Yet, having empty subscribes is a code smell and should be avoided at all cost.

Smelly code

// Using RxJs in my example :-)
someObservable.pipe(tap(value => this.doSomething(value))).subscribe();

This, in my opinion, is an example of poor code. The reason is that the call of the subscribe function is necessary. That is exactly the difference between Observables and Promises: your code is not executed until a subscriber is present. Without subscribers, no value goes through the value stream. This is crucial to how Observables work. Sadly enough, not everybody understands this. Some of us are just thrown in the codebase without introduction to any of the frameworks that the frameworks we use are built with.

To be blunt, if I didn't know how Observables worked and saw an empty subscribe function, I would delete it. Not because I want to break the code, but because there's no callback given. And so there's no callback to be executed, right? That's what my brain would think if I understood only part of it.

While that might sound dumb, it's ignorant to think everybody understand everything. Also, I haven't witnessed any software project where time was invested in fully understanding the frameworks used once someone joins the project. Of course, you get some time to know your codebase. But do you get to know every aspect? Let me know in the comments, because that sounds like a dream project to me.

If you are not convinced by my argument, here's an interesting exercise. Go to your codebase and find an empty subscribe. Delete it and push your changes. Let's see how long it takes for your team members to find the location of this bug without looking at previous commits. My guess is it will take them quite some time.

The solution

// using RxJs in my example again :-)
someObservable.subscribe(value => this.doSomething(value));

In my solution for the empty subscribe function, I just moved the code that was in the tap function to the subscribe function. There's a callback, so there's no way someone can remove this by accident. When dealing with empty subscribes, there is always something that can be moved to the subscribe function.

Conclusion

We looked at a code smell concerning Observables and empty subscribes. When no callback is given to the subscribe function, the Observable will work as planned but this might not be clear to everyone on the team. There is always something that can be put inside the subscribe callback. It's best to put it there to avoid misunderstandings and potential future bugs.