No More Disposable Observer as Callbacks Please
This blog post was inspired by an article that DoorDash Engineering posted describing the transition from Callbacks-Style API calls to Rx-Style API calls. In this article, I highlight some of their points as they relate to some of ClassPass’s legacy Android code base.
The ClassPass code base currently follows a pattern where the Presenter component creates and passes a DisposableObserver
to the Interactor layer, which in turn passes the callback to the repository layer. (Presenter from MVP Architecture).
DisposableObserver
Example:
Let’s not do this any more.
- Callback Hell — The pattern above uses
DisposableObserver
as a callback and reinforces the Callback Hell problem. - Readability — Keeping relevant logic together makes code more readable. The pattern above spreads relevant logic over different layers and components.
- Testing — Unit testing the Presenter requires instantiating multiple layers to simulate the test logic. This is not ideal for unit tests.
Example:
- Rx offers better — RxJava/RxKotlin has grown in popularity in direct response to challenges around organizing asynchronous logic. Operators such as
flatMap
serve as an alternative to callbacks.
The Better: Observable Chaining
Rather than using the DisposableObserver
as a callback, we should return the result as an Observable
.
Before:
interactor.fetchData(input: Data, callback: DisposableObserver<>)
After:
interactor.fetchData(input: Data) : Observable<>
Refactoring the Interactor
Using the proposal pattern we refactor ReviewInteractorImpl
.
ReviewInteractorImpl
Before:
ReviewInteractorImpl
After:
Refactor the Presenter
The Presenter layer refactor will reintroduce 2 components removed from the Interactor layer.
subscribeOn
andobserveOn
— the logic the ensures IO doesn’t happen on main thread.subscribeWith
— The binding between callback logic and API response
Also, we refactor the Inner class ClassReviewListObserver
into the Observable
chain.
ReviewPresenterImpl
Before:
ReviewPresenterImpl
After:
Refactor Tests
Finally, removing the callback no longer requires the unit test to instantiate the Repository.
In summary, replacing DisposableObserver
with Observable Chains gets us a couple things.
- Readability —
ReviewPresenterImpl
chains together all the logic describing the behavior offetchVenueReviewList
. - Cleaner Tests — The unit test does not reference the Repository anywhere and only mocks the Interactor.
- No Callbacks — No Callback Hell 🎉
- Rx Operators like
flatMap
anddoOnError
The example illustrates how we can refactor logic in the Presenter layer and how ReactiveX deals with async behavior without callbacks. With only one call to the api layer,fetchVenueReviewList
is pretty straightforward. For more complex scenarios like chaining api calls, ReactiveX offers many more operators.
Let’s leverage ReactiveX’s true potential and kick DisposableObserver
aside. 🎊
You’re reading the ClassPass Engineering Blog, a publication written by the engineers at ClassPass where we’re sharing how we work and our discoveries along the way. You can also find us on Twitter at @ClassPassEng.
If you like what you’re reading, you can learn more on our careers website.