debugging

Embracing Redux – or What’s Wrong with Object-Oriented Programming?

Before you ask, I don’t think anything’s wrong with object-oriented programming. But recently I’ve attended an interesting talk at the JAX conference. By the look of it, the speaker, Manuel Mauky, wasn’t happy with object-oriented programming. Instead, he propagated functional programming and Redux.

While I don’t agree with him, I considered his reasoning compelling. I’ll try to summarize it as best as I can.

By definition, object-oriented programming means to combine data with algorithms. To me, this always seemed to be natural. After all, data is meaningless until you know what to do with it. From this point of view, objects join two concepts that belong naturally together.

Manuel tackles things from a different angle. He doesn’t believe that data and behavior belong together. He’s pretty much convinced that the application state should be separate from the functions defining the behavior of the application. We’ll see that this approach has many advantages.

Time

In Manuel’s world, time plays a crucial role. In fact, almost everything programmers deal with boils down to the question what happens to their program in the course of time. How are the data changed by the actions of the programmer or by external events? Putting it into the terms of Redux: how does the application state change over time?

Redux is a framework focusing on the application state and on how the application state changes. So the two central concepts of Redux are

  • the central store containing the application state
  • and several transformations describing how the application state changes when certain events are triggered.

That, in turn, explains why functional programming is so popular among Redux programmers. The rules describing the transformation of the application state are functions. Plus, Redux considers the application state a different domain than the state transformations, which describe the application’s behavior. That’s the natural field of a functional programming language. It’s a lot harder to implement a program separating state from behavior with an object-oriented language. Of course, it’s possible, but it feels counter-intuitive.

Time-traveling debugger

My last adventure into Redux wasn’t a pleasant experience. But there was one feature that almost bought me: the time traveling debugger. As mentioned before, the central idea of Redux is to define an application state. Other than I suggested before, the state doesn’t change over time. It’s immutable. The functions transforming the state create new immutable variations of the old state.

At every point of time, there’s exactly one application state. If we were to store these states, we could traverse the history of our program backward. That’s a tremendously useful feature. How often do you see an error without being able to reproduce it? If you’re running your program with a time-traveling debugger, that’s never going to happen. You can go back in time, reconstructing the steps that led to the error along the way. A couple of years ago I evaluated Chronon. We didn’t use it because we were low on budget, but the first results were encouraging.

Redux takes the idea of a time-travelling debugger one step further. You’re not really interested in arbitrary changes. You’re interested in changes triggered by events, such as the user clicking a button. Storing these events and the corresponding application states is easy. So it’s not astonishing that time traveling debuggers are not only available in the Redux universe, they are even available for free.

Long transactions

Long transactions are another domain showing the power of Redux. Sometimes it’s useful to start a series of changes without having to store each change immediately to the database. If you allow the user to do so, that’s a long transaction. The classic examples are programs like Word or Excel. You can do an arbitrary number of changes, but it won’t be committed to the file system until you hit the “save” button.

Redux makes it easy to implement such a long transaction. Basically, all you have to do is to store the events and to replay them when the transaction is committed. Or to replay the state transformations and to save them to the database. If you want to rollback the long transaction, you simply go back to the original application state.

Serializable application state

I don’t exactly remember why this is an advantage, but Manuel emphasized several times that the application state is serializable. I guess that comes in handy every once in a while.

Knowing where to locate an error (or an application behavior in general)

At this point things get interesting. According to Manuel Mauky, one of the biggest advantages of Redux is that you always know where to locate an error. My own experience was a bit different. I always know where to find the cause of an error in an object-oriented program, but I had my fair share of difficulties finding the same error in a Redux application.

I guess it’s just a matter of practice and convention. I prefer the object-oriented paradigm, so it’s little wonder I get along with it more easily. If someone’s grown up with another tradition, my approach probably seems weird to them. Both paradigms work. It’s mostly a matter of taste which one you choose.

When to use or not to use Redux

I’ll try to give a recommendation nonetheless. Redux has a couple of disadvantages. Among other things, it requires you to write a lot of classes. The object-oriented approach tends to be less verbose.

So Redux pays if you’ve got complex applications with a lot of user interactions. In particular, it pays if you’ve got several windows, each being able to trigger events influence each other window. Facebook is a classical example of such an application. The more UI events you’ve got to deal with, the more I recommend Redux.

However, the typical bread-and-butter application is a lot more straightforward. So the object-oriented model is more appropriate. You can write your program in a much more compact and concise way.

Wrapping it up

It depends on what you want to optimize. The time-travelling debugger is a persuasive argument to adopt Redux. On the other hand, object-oriented programming amounts to writing less code. At the end of the day, it’s a matter of personal taste. Which is more important to you: putting data and behavior together because they don’t make any sense otherwise, or do you concentrate on time and changes over time? Neither approach is wrong, so ask your team which model they feel more comfortable with. You can implement most applications using both paradigms. Currently, Redux is popular because Facebook and others propagate it, but I’d rather you’d ignore such short-term considerations and think in the long term.

One thought on “Embracing Redux – or What’s Wrong with Object-Oriented Programming?

  1. Hi Stephan,
    thanks for your summary and review of my talk. Good to hear that you found it helpful even if you don’t agree with all statements.

    Indeed, in my opinion functional programming is superior to object-oriented programming in many cases, especially in the frontend.
    However, of cause functional programming has it’s disadvantages too and there are still many open questions when using redux that I still have no good answer for (yet).
    And in the end – as you’ve wrote – you have to decide which aspects are most important for you.

    For classic CRUD heavy applications maybe the overhead of redux doesn’t pay of. The more “interactive” your application is the more likely it is that redux is beneficial. But there are other aspects too, for example the know-how of the developers in your team. This is something that we have learned from our projects: The learning curve is quite high for developers that aren’t used to functional programming concepts.

    Even though I think that functional programming is the better approach I’m still open to counter arguments and I’m happy to rethink by opinion. And I’m also eager to hear counter arguments like yours so thanks for this blog post.

    Here is another article that I found interesting and that taught me the idea of the separate responsibilities of data and behaviour that are mixed up in OOP: https://code-cartoons.com/a-cartoon-intro-to-redux-3afb775501a6

    There are multiple use-cases for a serializable state (in general, maybe not all of them apply to browser apps):
    – You can persist the state and reload it the next time your app is started. For this you don’t need to change anything in your actual application logic but only add and configure a library that takes care for this, for example redux-persist (https://github.com/rt2zz/redux-persist). In OOP this is harder because your application state is distributed over many objects at runtime. I’m sure there are also libraries or frameworks to implement this with OOP but I doubt that they are as simple and natural as the redux variant.
    – You can calculate and even cache the state on the server-side and send it together with a pre-rendered page to the client. This technique can improve your side loading speed and has some SEO advantages. You can read more on this in the redux docs here: http://redux.js.org/docs/recipes/ServerRendering.html#server-rendering
    – We have an application those application state has to be synchronized over the network. Multiple clients have to see the same UI. Actually we haven’t implemented this application with redux because this was some years ago but the serializable state of redux could help when implementing such applications. Maybe it’s not a good idea to send over the whole application state on every change but you can send it over from time to time as a checking mechanism.
    – the last argument is the developer tool: Visualizing the current state and persisting it is only possible because the state is serializable.

    Greetings, Manuel

Leave a Reply

Your email address will not be published.