Yesterday, I came out strongly against the use of Middleware in Redux claiming that I felt it was Redux taking on too much responsibility. But, after I wrote that post, I got to thinking about the $http service in AngularJS. The $http service allows us to define interceptors which wrap around the AJAX request in the promise-chain that executes the HTTP workflow. Well, you don't have to squint all that hard to interpret the $http interceptors and the promise chain as a sort of "middleware" for the AJAX request. So, why does that approach seem "OK" to me while the Redux middleware makes me so uncomfortable?
| || || |
| || |
| || || |
First of all, there's no doubt in my mind that some of the pushback I feel towards Redux middleware comes from my own fear and insecurities about new technology and, especially, the trouble that I've personally had in learning Redux. To not admit that would be foolish and naive. But, even when I try embrace that fact, the two different workflows still feel like they have a fundamental difference. Maybe if I could outline some of the differences, it would help get at the root of the disconnect.
The AngularJS $http service will always be asynchronous. No matter what you do in the $http interceptors, the result always comes back in an asynchronous promise. In Redux, you can use middleware to fundamentally change the flow of control, converting it from synchronous process to an asynchronous process.
With an AJAX request workflow, there is an inherent need to transform data. The AngularJS $http service uses the interceptors internally to convert configuration data into an AJAX payload and then to convert an AJAX response into a result. With the Redux action, there is no inherent need to trasform incoming data - that is the job of the reducers (to translate action data into state change).
While not a critical difference, implementing an AngularJS $http interceptor is more straightforward - it's just another .then() in a single promise chain. Implementing Redux middleware, on the other hand, is a whole dance of decorators and factories inside of factories. I am sure that the increased implementation complexity and layers of abstraction make if feel more different than it actually is (going back to pushback ala insecurities).
So, mechanically speaking, AngularJS $http interceptors and Redux middleware are different. But, really, they're not that different. As such, I don't think that my pushback stems from the mechanical differences.
I think that my pushback somehow comes from the use-cases. But, even that is hard to define. I feel like the AngularJS $http interceptors are used as "hooks" into the AJAX life-cycle. But, you could also say that the Redux middleware provides "hooks" into the state mutation life-cycle. Which it does.
I think my issue is when those "hooks" get too heavily co-opted as a platform for business logic orchestration. Meaning, when they become less of a "convenience" and more of a "critical" part of the application workflow. For example, using the Redux middleware as a means to initiate API request feels like an overreach of middleware responsibilities for a library.
NOTE: I am being explicit on this last point about it being for a "library." If you're using something like Express, whose whole "reason for being" is about coordinating application control flow, the expectation is different.
Unfortunately, I can't seem to articulate it any better than that. I think that, as an idea, Redux middleware is good; and, that my pushback yesterday was perhaps more fueled by fear than I would like to admit. But, I do think that Redux middleware can be used in inappropriate ways. And, for me, that can be generally interpreted as when the middleware is becoming overly critical in the core functionality of an application. I think a good litmus test would be to remove the middleware and see what happens. When you do that, how much stuff in your application breaks? If just a few small things break, you're probably on the right track. But, if the application fundamentally stops working, you're very likely abusing middleware responsibilities (in my opinion).