This is a two part series on the functional programming basics you should know before learning React and Redux. Click here for part 2.
The first article in the series simplifies the concepts of functional programming and by the end of the article, the entry barrier to learning React and Redux will hopefully seem a little smaller.
Similar to way you can choose to write a formal or informal style email, you can write different styles of code. There are a few different styles (aka paradigms) including; structured programming, object oriented programming and functional programming.
Believe it or not, these patterns have essentially been unchanged since Alan Turing wrote the first line of code on an electronic computer. Since then, mathematician Alfonso Church built on the work of Turing and introduced the Lambda Calculus in 1936, which then provided the backbone for John McCarthy’s LISP language in 1958, the first functional programming language.
This is reassuring, because despite the constant wave of new languages, frameworks and tools you see on a daily basis, functional programming concepts have persisted.
You may have noticed senior engineers seem to pick up new languages with ease. That’s because they have understood these core, unchanging concepts and can spot the underlying patterns of functional programming.
So what’s so great about functional programming and why did the React team choose it? Well, if you were to write an application that followed all of the functional principles your code would be,
- Easier to debug
You may not be as concerned about these benefits for a small personal application such as a to-do app but if you were working on large scale applications for a multi-million pound company, they are critical.
Before introducing the concepts, its worth noting that there is no such thing as the perfect application or developer. Software engineering is as much an art as it is a science. Functional programming does not provide all the answers in a nice neat FAQ. You need to work hard to understand the concepts and use your best judgement on how and where they can be applied.
Secondly, the term ‘state’ is used in the below text. State refers to all the parts that change in an application. More simply, it’s your apps data. For example, in an online library application, the state could contain book titles, authors, if the user is a member, if the user has filled out a form on the website, etc. Knowing these two things we can begin to answer, what are the concepts of functional programming?
- Avoid changing state (aka avoid mutations, aka immutability). This sounds strange at first because obviously things need to change in our app… The trick is, you need to be making copies of the state and editing the copy, rather than editing the original state. As an example, if you had an array of team members and wanted to add someone new, instead of editing the current array you should copy it and edit that. This may also be written as ‘you should transform your state’.
- Avoid functions that change the ‘outside world’ (aka avoid side effects ). Again, this sounds strange but it’s similar to the above in that your functions should only copy and edit the input, rather than editing the original input. Some times side effects are required, for example, logging to console, writing to the screen, triggering an external process, writing to a file, etc, but where ever possible you should not be ‘editing’ the outside world, you should be ‘adding’ to it. Anytime you do need side effects, you should separate and isolate the actions from the rest of your application as much as possible.
- The state in your application should never be ‘shared’ (aka avoid sharing state). For state to not be ‘shared’, it means that every time you need to ‘change it’ you should duplicate it and edit the duplicate, thus state is never ‘shared’ as such.
- Writing functions that are predictable, only do one thing and do not change the ‘environment’ around it (aka write pure functions ). They have no ‘side effects’ and given the same input, they always return the same output.
- You should write code that displays ‘what’ should happen rather than ‘how’ it should happen (aka write declarative code). An example of this would be choosing to use the map function, instead of a for loop, because the map function is a more concise version of a loop.
From the above, we can see that we are trying to avoid mutations, side effects and sharing state by writing pure functions. We are also being thoughtful with our function composition and writing declaratively. State management libraries such as redux provide a framework to achieve this in your applications, but before learning those you should know how to write it without their use.
To summarise we can understand the concepts as follows,
- Avoid mutations
- Avoid side effects
- Avoid sharing state
- Use pure functions
- Be thoughtful about function composition.
- Write declarative code