Imagine you're working on a social networking app and you have a
controller that is responsible for displaying a user image with a follow
and a like button. Imagine also, that - in line with the single
responsibility principle and view controller composition - the
like and follow functionality is handled somewhere else.
Our social network does have premium user accounts as well as corporate
user accounts (companies) and so there're a couple of configuration
options available for your InteractiveUserImageController
(naming was
never my strong suit). One possible option of our class could look
(partially) like this (for demonstration purposes, there're obviously a
lot of things that we can change here):
final class InteractiveUserImageController: UIView
Now, these are a lot of properties. As our app grows, we might end up adding even more properties here. Of course, we can refactor and group them by responsibility, but sometimes single responsibility still leads to quite a few properties. So how can we possibly structure this a bit better?
Swift Struct Structure
Swift's struct
types can actually be really helpful here. What we can
do is group these properties by their type by moving them into
one-time structs:
final class InteractiveUserImageController: UIView
As you can see, what we've done here is we moved the state into
seperate struct
types. Not only does this make the class cleaner, it
also makes it easier for new developers to find related options.
This is already a very nice improvement, but we can do even better!
The issue we have here is that there is an additional step involved when looking up a property.
Since we're using one-time struct types we have to define them
somewhere, (i.e. struct DisplayOptions
), but we also have to
instantiate them somewhere (i.e.
let displayOptions = DisplayOptions(...)
. This is in general ok,
but in larger classes this might still require an additional lookup to
figure out the type of displayOptions
. However, there is no way in
Swift to create anonymous struct
types like this 1:
let displayOptions = {
///
Anonymous Structs nee Tuples
Actually, there is such a type in Swift. It is our good old friend, the
tuple
. See for yourself:
var displayOptions:
This defines a new type displayOptions
that has three properties
(bigLikeButton
, alternativeBackgroundColor
, isPremium
) and can be
accessed just like our struct
from earlier:
user.displayOptions.alternativeBackgroundColor = true
Even better, the defintion does not need an additional initialization, so everything is in the same place.
Enforced Immutability
Finally, the whole tuple
is either mutable
or immutable
. You can
see that in the first line: We're defining var displayOptions
but no
var
or let
bigLikeButton
. bigLikeButton
is also a var
just
like displayOptions
. The advantage of this is that this enforces
moving static constant properties (i.e. line height, header height) into
a different (let
) group than mutable properties.
Add some data
As a nice addition, you can also use this feature when you need to initialize these properties with values:
var displayOptions =
Very similar to the earlier code, this defines a tuple of options but also initializes them with the correct values right away.
Nesting
Naturally, you can also nest these tuple options easily, which makes it even easier compared to our original struct approach:
class UserFollowComponent
I hope you found this article useful. I'm using this simple pattern quit a lot in order to give my code more structure. Sometimes only for 2-3 properties, but even then it is already beneficial.
Unlike C