Solving Complexity With Simplicity
Apple announced Swift last year, during the annual WWDC. It was an unexpected but very exciting news. Since then, my personal feelings about Swift were wavering, from “GOSH, IT ROCKS!” down to “GEE, THIS SUCKS!”. One thing intrigued me and still does: the functional side.
Back in 2010, I was involved in iOS development and Java development (fifty-fifty), I was so bored about the second one, that I started to search for an alternative. During a conversation with an ex-colleague, I discovered Scala and I then ended up giving it a try. At that time, I never really programmed in a Functional style (or with a Functional Language), but the first feeling was great, even if the syntax of the language was so difficult to understand and master, that my first thought was to let it go and try Groovy. Furtunately, I didn’t give up and Scala has become one of my favourite languages and this gives me the possibility to reuse most of the concepts I learned with the new entry: Swift.
Simplicity as way to solve Complexity
In functional programming, there are a lot of interesting concepts, but when I am asked why I like the functional approach is because complexity can be solved with simplicity. It sounds very kitchy as answer, but the truth is that mastering functional programming concepts, makes a software more robust, easy to scale and more maintainable.
In Scala (and any other FP language) is possible to learn how to create simple code and how to combine (chain) functions, handling errors and results in a very elegant way. What most I like of functional style, is how side effects can be managed.
The world of Side Effects under control
The first thing to know is what is a Side Effect and why, in software development, this easy concept can be difficult to handle and to deal with. What exactely is a side effect?
In computer science, a function or expression is said to have a side effect if, in addition to returning a value, it also modifies some state or has an observable interaction with calling functions or the outside world.
Basically, everything involving a disk write, database connetion, I/O, or just an
NSLog, are operations with side effects.
To make it easier, a basic example of a code snippet with side effect is:
We have side effects here because we are incrementing a static variable that can be accessed (and modified!) by the outside world. We can, for example, have a method that resets the counter:
The above method can cause a lot of troubles if we are doing things concurrently, can you imagine and exactely predict a scenario with one thread incrementing the counter and another one resetting it? Difficult.
Purity can help
In functional programming, the above code is usually avoided. State-dependant code (if not correctly wrapped and handled) is considered as a bad practice, how can improve the above example avoiding side effects?
To transform the first method into what is considered as pure function, we have to pass the counter argument and return a new value incremented by one, no state-dependent results, no side effects.
The second method is definitely useless, but shows how pure functions are usually implemented. Why I don’t pass the counter to be reset in the method? Because I love immutability.
Immutability for the win
In Objective-C, immutability is not a best practice concept and in all libraries and projects I worked with/on, I nevers saw a deep usage of immutability. Can you imagine to write a whole app without using
Instead, immutability, is a concept very important in FP and in Swift has been heightened with the verb to declare constants:
From Apple documentation:
The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once.
In concurrency, all important collections in Objective-C are not thread-safe and they have to be managed carefully in concurrent processes. In Swift, with a careful implementation, immutability can avoid side effects, making the code more stable and less error-prone.
Unfortunately, there are still some strange behaviors about
let and collections like Arrays, but knowing them can prevent us to fall into the trap.
In the next posts we are going to see how Swift can be used to write better, maintenable and scalable code explaining basic concepts of functional programming with easy examples.