I started my career doing C/C++ programming for Embedded systems and then transitioned to do Java/J2EE for a very long time. For the last year or two, I have been exposed to the world of functional programming through Scala, and for the last couple of months I have been doing actively development in the front end stack using Node.js on the server side and Redux/React on the client side. It has been a great experience and would like to share the connections I can see between the concept of “referential transparency” in functional programming world to Redux/React.
[Source Used for reference: Functional programming in Scala book]
Functional programming (FP) is based on a simple premise that we construct our programs using only pure functions – functions that have no side effects. What are side effects? A function has a side effect if it does something other than simply return a result. For eg:
- Modifying a variable
- Throwing an exception or halting with error
- Making IO operations
Functional programming provides many techniques to do the above set of operations as well without side effects. I have written about a couple of patterns here:
The key idea is that majority of logic that deals with side effects lives at the edges of the application, while the core remains pure. Why do we need to have “pure functions” in the first place? Well, the answer turns out to be simple: Pure functions are easier to reason about. A function f with input type A and output type B, function of type A => B, is a computation that relates every value a of type A to exactly one value b of type B such that b is determined solely by the value of a.
We can formalize this idea of pure functions using the concept of “referential transparency”(RT). This is a property of expressions in general and not just functions. For eg., if we have an expression 2 + 3 in different parts of the program; This expression has no side effect and evaluation of this expression results in the same value 5 every time. In fact, if we saw 2+3 in a program we could simply replace it with the value 5 and it would not change a thing about the meaning of the program. The above case is true for eg., if we have a function called add(int, int): int which takes 2 integers and returns an integer as a result. If we saw for example, add(2, 3) in different parts of the program we could again simply replace it with the value 5 and the meaning of the program stays the same.
Referential Transparency examples String class and its methods in Java are examples of referential transparency, as they do not have any side effect. String s1 = "Hello" int length = s1.length() // always going to be 5 Non Referential Transparency examples StringBuilder class and its methods in Java are examples of non referential transparency as they have side effect. StringBuilder s1 = new StringBuilder("Hello"); s1.append(" , World"); // side effecting operation
Pure functions as mentioned earlier are easier to reason about and also has an additional important property that they are inherently thread safe and are very easy to parallelize. In the above example, StringBuilder is not thread safe as it has side effecting operations.
In the case of UI, state comes from 2 sources:
- State produced by making a backend service call, which is an IO operation which is solved by Thunk Middleware. Thunk Middleware makes side effects living at the edges of the program within redux, where as the reducer function within the core can remain pure.
- UI state like checkbox selected, button clicked etc.,
Because of reducers being a pure function and thus referentially transparent, the UI application state has become so easy to reason about.
React Redux , which provides react bindings for redux, provides a function called connect(mapStateToProps, mapDispatchToProps) which acts as a bridge connecting the redux state to the react component props and also dispatching actions from react component to trigger the next state calculation using reducer function thus making sure the React Component UI stays up-to-date when its relevant state changes.
The mental model of how React, Redux, React-Redux fits in can be shown as below:
As we can see, how a core philosophy of “referential transparency” in the world of functional programming is being applied to client side programming using React/Redux which makes UI code very easy to reason about.