So far, we have been programming using the paradigm called object-oriented programming, where everything in a program is represented as an object that can be manipulated and passed around to other objects. This is the most popular way to create apps because it is a very intuitive way to think about software and it goes well with the way Apple has designed their frameworks. However, there are some drawbacks to this technique. The biggest one is that the state of data can be very hard to track and reason about. If we have a thousand different objects floating around in our app, all with different information, it can be hard to track down where the bugs occurred and it can be hard to understand how the whole system fits together. Another paradigm of programming that can help with this problem is called functional programming.
Before we jump into writing code, let's discuss the ideas and motivations behind functional programming.
Functional programming makes it significantly easier to think of each component in isolation. This includes things such as types, functions, and methods. If we can wrap our minds around everything that is input into these code components and everything that should be returned from them, we could analyze the code easily to ensure that there are no bugs and it performs well. Every type is created with a certain number of parameters and each method and function in a program has a certain number of parameters and return values. Normally, we think about these as the only inputs and outputs, but the reality is that often there are more. We refer to these extra inputs and outputs as state.
This is a great example of a
stateless function. No matter what else is happening in the entire universe of the program, this method will always return the same value, if it is given the same input. An input of 2
will always return 4
.
Now, let's look at a method with state:
Side effects are an even worse type of extra input or output. They are the unexpected changes to state, seemingly unrelated to the code being run. If we simply rename our preceding method to something a little less clear, its effect on the instance becomes unexpected:
Besides predictability, the other effect that functional programming has on our code is that it becomes more declarative. This means that the code shows us how we expect information to flow through our application. This is in contrast to what we have been doing with object-oriented programming, which we call imperative code. This is the difference between writing a code that loops through an array to add only certain elements to a new array and running a filter on the array. The former would look similar to this:
Running a filter on the array would look similar to this:
So far, with our imperative code, most of it just defines what our data should look like and how it can be manipulated. Even with high quality abstractions, understanding a section of code can often involve jumping between lots of methods, tracing the execution. In declarative code, logic can be more centralized and often more easily read, based on well-named methods.