Structs are very useful datatype in swift when it come to storing data models required by our apps. Having mutable data models often leads to unwanted app states, due to inconsistent model values present across app, introduced as a side effect of mutation. This makes our code unsafe and our apps prone to a lot of bugs. Thus, we generally prefer to have our data models immutable to ensure safety from above scenarios, but you cannot always escape mutability, as our apps are open to various user interactions which often cause data model changes. So if we can’t escape it, then we should very well learn to handle struct mutations properly. So without further ado, let dive straight into it 🌊 .
Consider an banking/trading app which deals with mutating you account balance based on your transactions/trade deals. This makes for a perfect scenario where your
Account struct would be exposed to mutations.
The idea behind functional programming is to treat every computation as an evaluation for mathematical functions, and avoid mutable state. The idea is to write functions should have a clear input and a clear output with no global side effects like mutating objects. Consider the following code snippet for incrementing Account Balance, which adheres to this approach:
deposit function here instead of mutating the original
balance, returns a new value each time it is called. Thus, this allows us to have
let,without having to deal with side-effects that would occur if the
balance was made a
var . We can happily have our struct properties as constants instead of variables, and avoid the side effects. 😃
Mutating Function approach
Structs in swift are value types unlike classes which are reference types, and by default you cannot mutate the properties of a struct using instance method. You will end up with compilation errors like this 😭.
Swift won’t let you write methods that change properties unless you specifically request it. Hence, if you need to modify the properties of structs within a particular method, you can opt in to mutating behavior for that method. This type of method mutates the struct properties and then writes all the changes back to the original struct.
So, let’s make use of the power of mutating function to implement our deposit function. For this we just need to mark
mutatingin the above snippet. Since, the function is mutating it does an in-place modification of our struct, and hence we don’t need to return a new value, which was the case with the functional variant.
And on top that, if we had created two different accounts, then called
deposit on one of the account, it wouldn't change cause changes in the other account. Hence this type of function doesn’t introduce any global side effect, and mutation is restricted to the specific instance invoking this function 🤩.
But to implement the mutating behavior we had to also make the
balance property a
var , and this open another pathway to set the value directly instead of setting it via the mutating function. You don’t wanna leave too many openings exposed for mutating, right 😇? This can be tackled very easily by making the setter for the property private, and the compiler will take care of the rest for you by flashing errors.
Hence, we close the other opening to mutation to full proof our solution using a mutating function with private setter 🎉
Mutation is sort of a necessary evil in mobile app development cycle. It can wreck havoc in our apps, burdening us with unwanted bugs, if left unchecked or not tackled properly, leaving the end users with a substandard UX. There is no such thing as the best approach to tackle struct mutation, and you can opt for either of the variants. Generally speaking, it’s best to decide based on readability and choose the version that makes your code the clearest at the call site, but yeah it doesn’t harm to have multiple solutions in your arsenal and decide the usage on a case by case basis. Empowered with the right weapons now, let this evil scare you no more on your conquest of making great apps with seamless user experience 🥇.
Until next Adieu …