A few basic concepts I want to jump into before going into ReactiveCocoa for iOS development.
State
State is one of those terms that is thrown around a lot when discussing modern application development. And it may not be something we have traditionally talked much about about, at least not referring to it as "state". Application state is bascially stored memory for the application, which can be in the form of variables, properties, etc. The web in nature is inherintly stateless. Meaning every request made to a server, begins with no state (with the exception of perhaps session related information, etc). There are no arrays or data structures persisted. Each call may fetch data from a database and essentially starts from scratch. This is true with the traditional web. Innovation in web development has had a lot to do with how to add state to web applications. So state really applies more to native application development. Think of it this way. An app on your machine, like Google Chrome, is constantly running, either in the foreground or background, but running nonetheless. It is in charge of managing how much memory is uses. Getting rid of information it no longer needs and persisting (saving) data that it will need to reference later. For example, tabs in Chrome are a form of state. If you open a tab with GMail in it, and then primarily use other tabs for browsing throughout the day, your GMail tabs still exists and doesn't disappear. Google Chrome knows that it should not trim that information from memory because you may at some point want to click on that tab and resume using GMail. This is an oversimplified version of "state".
State as we will be referring to it, will be at a much more micro level, and has more to do with storing variables and properties in your code vs. running values through a "stream" of functions that manipulate the data being passed along. Global variables are the opposite of stateless design. One large advantage of removing state is simple testability. If you have methods or functions that are stateless, and only know about what has been passed to them, they are much easier to test. There are no outside factors that have to be handled, set up, or torn down. It is solely dependent on what you tell it in your test.
Stateless design also relates to language paradigms like mutable and immutable variables. Mutable means changable. Immutable means the variable is only ever assigned once, and never changes. In stateless design we begin using Immutable values much, much more. Which also eases testing, and reduces the risk of other outside factors giving the app unexpected results. Languages like PHP are more or less always mutable. Languages like Swift have introduces more convenient ways to work with Immutable data. If you are changing or manipulating data that is immutable, you are creating a new variable, rather than change the existing one. This brings us to Functional Programming.
Functional Programming
Functional programming is how we more or less implement stateless application design. This is because we can "chain" functions together and a value or set of values are passed along the chain being manipulated along the way, and eventually returned to what is usually an immutable variable. This variable can be immutable because all the manipulation that needs to be done is compartmentalized into a series of functions. Functions that take in a value and return a value. A chain of functions is basically saying do this, then do this, then do this, and so on and so forth till we have the data we want.
Functional programming is generally considered more difficult to learn. I think this is because working with mutable data allows someone to set a variable, then use standard programming constructs to change this value over time. It also allows you to see the logic that is happening to your variable sequentially, often in the same block of code. I suppose this is often called procedural code. There isn't anything wrong with procedural code, it's just a different way manipulating data. And you can combine both of these design patterns easily with a program. PHP is a good example of this. PHP if by in large procedural, but there are some functional aspects of it. Like mapping, or filtering an array. You might use functional code to set up an array, but then procedurally evaluate and change this array afterwards.
Loops (or lack there of) are often talked about when describing Functional Programming. Probably due to the fact that it is such a common structure in code that functional programming approaches differently. So in a loop, you are checking a series of values, either changing them or using them to construct something else. An example will help explain this...
$arr = array(1,2,3);
$total = 0;
foreach ($arr as $number) {
$total = $total + $number;
}
print $total;
There are a bunch of ways to approach this functionally in PHP. You can use array_reduce() to return the total.
$arr = array(1,2,3);
$total = array_reduce($arr, "add", 0);
print $total;
function add($a, $b) {
return $a + $b;
}
This is a bad example though, because PHP isn't really set up for functional programming. Ideally we would chain array_reduce to our array variable rather than call a function that passes the array as a parameter.
Swift is better at this...
let arr = [1,2,3]
let total: Int = arr.reduce(0, add)
print(total)
func add($a: Int, $b Int) -> Int {
return $a + $b
}
This is more functional. We are calling reduce as a method of the array itself, telling it to start with 0, and run the add function for each value in the array. Pass in two values... one that in this case is the running total, and the second the next element in the array.
But Swift is set up to handle these kinds of things much "cleaner". It's kind of a pain to define a whole function just to add values (I think this is one barrier to developers when switching to functional programming). Swift (as well as many other languages) introduces closures. So defining a function seperately isn't really necessary, it can be done on the fly. Like this...
let arr = [1,2,3]
let total: Int = arr.reduce(0) { $a, $b in
return $a + $b
}
print(total)
Or, even simply...
let arr = [1,2,3]
let total: Int = arr.reduce(0) { $0 + $1 }
print(total)
This is such a common pattern in Swift that they make things easier on developers developing functionally by assuming some things. No need for a return statement in the ad hoc function. It just assumes that the evaluation is the return value. No defining parameters to the function, just use $0, $1, etc for the values being passed in. I displayed the second way after showing more explicitly what was going on to make things more understandable to someone used to programming procedurally.
One last concept to mention is High Order functions, because you will see this term quite a bit in the functional world. High Order functions are simply functions that can take other functions as parameters. This is an important part of chaining things functionally.
This brings us one step closer to understanding Reactive Cocoa. The next post will be exploring the "Reactive" part.
Need a fresh perspective on a tough project?
Let’s talk about how RDG can help.