Skip to content

Category: OOD

Protocols as boundaries between the known and the unknown

In the previous post, we discussed how protocols 1 are the foundation of polymorphism, and how using protocols we can define a contract, an expectation, that can be implemented in many different ways.

Today we are also to explore how we can use protocols as a way to use code that does not exist yet, as a boundary between what we know (our code) and what we don’t know (other people’s code).

In an ideal world (maybe not ideal for everyone, but that would be a different discussion) we don’t develop our software in isolation. We have team mates, or we use modules or frameworks developed by other teams within the same company.

Some time ago, I was with a time developing a set of Video On Demand applications. We had to implement a new feature: add support for recommendations based on user’s content consumption habits. The recommendations engine was not developed yet, in fact there was no team assigned to build it at that time.

We knew were our side of the solution started and ended. We knew we were going to need to tell the recommendations engine that a user had watched a particular item, and we were going to need to get a list of recommended items from the engine.

We started by defining our own interface for that recommendations engine. We looked at the problem from ur side of it, and wrote the interface we wished the recommendations engine had.

Did we know how the actual interface of the actual recommendations engine would look? Not at all. Did we care? We did not.

But we could start working on our side of the solution using fake data.

Having a clear boundary, clear separation between our side and their side, allowed us to build our side completely decoupled from the recommendations engine.

Having a clear boundary also gave us the confidence that we would be able to adapt to whatever the actual interface of the recommendations engine would look. And why I mean by adapt is literally write an adapter between our interface and the actually interface of the engine, if necessary (see the Adapter Pattern)

Also, having a clear boundary allowed us to unit test our solution from day one, giving us the confidence we needed to move forward fast.

It’s not rocket science. But it is worth remembering that protocols are not just those things that you use for table views data sources and delegates, but that they are probably the most powerful tool in our reach.

  1. I have never been a fan of how the Cocoa frameworks use the word protocol instead of interface. ↩︎
Leave a Comment

Fun with protocols

Back in the old days, people used to communicate with each other by shouting.

But soon, people found that shouting was not practical. The receiver of a message could just be too far away, or sleeping, so humanity invented written messages. And so snail mail was born.

Fast forward a few hundred years, to the early ages of the internet. Someone, somewhere, invented email, so now people could communicate like this.

Soon, people realized that even though email was great, there were other forms of communication. What’s even more remarkable, people were happy sending emails, but they soon realized that what they really wanted was to be able to do something slightly different. Instead of sending emails, they just wanted to send messages.

Some of those messages would be emails, some of them would be snail mail, some others might even be some unknown technological marvel soon to be discovered. But what all people knew is that they did not wan to be constrained by being able to send emails and only emails.

And here is when people realized that the way they had been approaching communications was slightly unadaptable.

One of the few software engineers on the face on earth at that time, decided to do something about it. She started thinking about what people wanted, and why they could not have it, and soon realized that the actual problem was that there was a hardcoded dependency between a Person, and the way that person was able to communicate.

Our hero also realized that the reason why that was a problem was that what people really wanted was freedom of choice, and flexibility, and being able to send messages by multiple different mechanisms, not only email.

And that made her think: “maybe what people expect are not things, but behaviours”. Indeed, People seemed to have a clear expectation: “we should be able to send a message”, but different people wanted that expectation to be fulfilled differently.

Our hero thought “what people want to rely upon is an abstraction, not something specific.”1

So our hero started building her solution around an abstraction: a protocol defining a behaviour.

That allowed our hero to model a couple of specific implementations of that behaviour 2. For example, an email, an SMS, an iMessage (aka Apple Message, to avoid lowercasing a class, apparently all our hero firmly believes in coding standards)

So now, a Person could be taught to blindly rely on the abstraction our hero modelled, trusting it to know how to fulfill her expectations.3

That way, Cesar can send emails while Jodelle can send emails, or a hipster can send a Messenger Pigeon.

Our hero was satisfied with her implementation of the solution, specially because she realized that this design allowed her to provide as many means of sending messages as she wanted, without having to change the way a Person sends a message.4

Also, our hero soon realized that she could only test that messages are actually sent, by providing a very specific type of Sendable that did not actually send any message.5

And that’s the power of protocols. A protocol defines a contract, declares a behaviour, but does not define the way that contract of behaviour is implemented. A protocol is abstraction, and the details, the nitty gritty of how those contracts or behaviours are implemented are left to concrete implementations of the protocol.

Relying on abstractions instead of concretions, in general, makes designs more decoupled, open for extension and closed for modification, and highly testable.

1 Comment

Swift’s defaults params, for fun and profit

Note: This post has been seating in my drafts folder for months. It is about a topic that has been discussed over and over in this blog, but I still feel like it can add some kind of value. So here you have it.

Dependency Injection and the SOLID principles have become, one way or another, an important part of almost ever post in this blog. And today’s post is no exception.

In my experience, one of the biggest challenges when it comes to unit testing view controllers is, well, unit testing view controllers.

UIKit tends to make all of us lean towards the “one screen = one view controller” paradigm, which tends to make each and every one of those view controllers sort of a dark hole that swallows everything related to the screen it corresponds to.

 

Yes, as soon as a view controller starts doing more than just the thing it should do (controlling a view), and starts doing networking, navigation, model state validation, local persistency and whatever elese you throw at it, things begin to get complicated.

Code becomes tangled, SOLID principles are violated, stuff gets impossible to test, and kittens die.

Oh, no, my view controllers are doing too much!

Well, there is a solution for that: making view controllers do less. Which can be achieved with the help of our old friend, the Single Responsibility Principle. Tell us more about yourself, old friend!

Every module or class should have responsibility over a single part of the functionality provided by the software

Or, the way I understand it:

Every module or class should do just one thing

Or, in the dystopian words of George Orwell:

One thing good, more things bad!

Cool, but wasn’t this post about default parameters?

Indeed it was. And it still is.

The thing about default parameters is that we can use them to help us factor our code in a cleaner and more modular way.

Let’s say that we have a view controller that needs to present a list of Items, fetched from our backend.

We want our view controller to do just one thing, so we will extract the networking to a separate class. Actually, what we do is separate to a different module whatever is related with providing the view controller with the data it needs to display. (See? Single Responsibility Principle FTW!)

So, we could write our view controller like this:

This solution is doing the Single Responsibility Thingy properly, but the dependency between List and DefaultDataLoader is hardcoded.

That is an issue, because it is safe to assume that DefaultDataLoader is somehow going to fetch data from the network. Which means that if I want to unit test List, I needs my tests to fetch data from the network, which is in between not optimal and plainly bad.

But why is networking in the tests bad? First, because there is no way to feed the unit tests with custom data, with data that we expect the view controller to handle in an specific way, for example.

Also, because unit tests should only have one reason to fail (again, the Single Responsibilty Principle, this thing is every-frikin’-where!), and doing networking introduces an extra factor for failure. Now a test ight fail because the production code is failing or because the rails server is down, or because the database is down, or because the office dog stepped over the router’s plug and disconnected it.

Oh, is that the bit about Dependency Injection?

Indeed, it is. Actually, it is more about Dependency Inversion, which happens to be the “D” in SOLID.

Depend upon abstractions, do not depend upon concretions.

Or quoting Napoleon and friends again:

Abstractions good, concretions bad!

In our previous example, List depends on a concretion: a specific instance of DefaultDataLoader. That deendency is hardcoded, and it can not be changed after compilation.

Let’s make List depend on an abstraction. One of the tools we have to model abstractions in Swift, line in many other languages, is protocols (interfaces).

So, let’s begin by defining a DataLoader protocol, by just extracting the public API of the DefaultDataLoader class:

Now, we can inject that dependency into the List class:

 

Dependency Injection is a 20 dollar word for a 20 cent concept. I wish I had come up with that quote, but I didn’t.

But the point is that DI is as simple as that. If class A needs to use class B, pass to class A a reference to class B.

Why do we type it as an interface though? Well, because we want to rely on abstractions, not concretions, remember? And also, because…

Finally! Here comes the ta-dah!

Indeed it comes. The way List looks now, we would need to do somethign like this when initializing it:

Or if you have a thing for one liners:

 

Which is fine, but can become annoying if we only need to provide one concrete implementation of DataLoader. And also because, and we are splitting hairs here, that code could look cleaner and read simpler.

And, finally, this is where we get to discuss default values in parameters.

Let’s rewrite the List initializer like this:

Now, to create an instance of List:

 

It literally, doesn’t get any simpler than that.

But the best is jet to come.

BYOM (Bring Your Own Mock)

Remember what we discussed about unit tests? Yes, unit tests should not hit the network, and we shoud be able to mock data fetched from the network.

Well, the thing is we can unit test List mocking data like this:

This is Good, with a capital G, because we can provide List with whatever data set we need in order to tests its behaviour, without hitting the wire.

 

1 Comment

Program to an interface, not an implementation

Something happened today that made me go back to a long long time ago, in a continent far far away, when my mentor at the time said to me “program to an interface, not to an implementation”, and I found myself googling (actually, yahooing, it was that long long ago) what that could possibly mean.

It took me years to have a basic grasp of what he meant. And, as I mentioned, today I read some code that made recall that moment.

Let’s say that we are working on an app that needs to save some data locally. Let’s keep things simple and let’s say we need to save a username locally, to pre-populate a login form.

The simplest thing that could possibly work would be something like this:

But now, once we are saving and retrieving the user name, it would not be completely unexpected if we were asked to display that username someplace else. Let’s say, for example, why not, that in a splash screen

I guess by now you already see the problem.

We are duplicating code. And duplicating code is not good.

But, even if we were not duplicating code, there is another issue here, way more subtle in my opinion.

And the issue is that the code is Snippet 1 is highly procedural, and it is a clear example of programming to an implementation, and not to an interface.

Programming to an implementation

The code in sample 1 is highly imperative and extremely specific. It lacks any abstraction.

We are aware, and we express that clearly in the code, that the username is going to be stored in the user defaults. Not only that, we make the LoginScreen class aware of that fact, and what is worse, we make it also aware of how saving stuff to user defaults work, in painful detail.

This code was easy to write, but the fact that we are exposing the details of how the username is saved is going to be a guaranteed source of pain.

What would happen if we needed to save, for example, the user’s phone number as well? Or his score (if this was a game)? Or an authentication token? And what if we also need to display any of that data in more that one place? We would scatter our source code with extremely specific references to the way we read/write that data.

Programming to an interface

The way I see it, programming to an interface is avoiding implementation details to be known by anyone that should not be aware of said details. And the way to achieve that, is by making my code as declarative as possible.

So, what do we have here? We have data that can be used to identify a User, and we need behaviour to make that data persist between app sessions.

Model objects

So, the first thing to do is identify the Model. In this example, the model is not a username or a telephone number, or a token, it is the abstraction that groups all of those together: a User.

So, let’s declare a User:

Abstract behaviours

Now, what do we need to do with that User? Persist it. Do we need to know how to persist it? No, we don’t. Do we need to know if we save it to UserDefaults, to a remote server, or to the Keychain? No, we don’t.

And this is the whole point of this post: more often than not, we don’t need to know how something is done, we just need to know that something is going to get done. In this case, we don’t need to know how the user’s data is going to be saved, all we need is to know that someone is going to take care of having that data available for us when we need it.

That way, we shift from writing step by step descriptions of what to do, to write high-level expectations of how things should collaborate with each other. We shift from imperative, to declarative code.

So, what’s the behaviour here? If we describe what we need in the most possible abstract way, we need User data to be available.

Abstract stuff, in Swift, like in any other OO language, is the domain of interfaces. In Swift, though, we call the Protocols.

And protocols need an implementation:

Now, the original code would look like this:

Which is better, if you only look at the save() and read() methods.

In fact, you might be wondering if we are actually in a better position now. We have written a protocol, to abstract things, but after all, in LoginScreen we create a concrete class to implement it. And you would be right, if it wasn’t for the coming step.

If we pass LoginScreen the actual implementation of the DataStore protocol that we want it to use, LoginScreen wouldn’t actually know who or how is saving and fetching data. That is called “inverting the dependency”. And I have written about it a couple times before.

Now we are getting somewhere. We have one abstraction (DataStore) and we have a class (LoginScreen) that is provided with a concrete, and unknown to it, implementation of that abstraction. We have shifted from something extremely specific and imperative (LoginScreen saving and reading to user defaults) to something abstract and declarative (LoginScreen asks DataStore to save or fetch data, not caring about how it does it).

And, to me, that is what “program to an interface, not an implementation” means.

Leave a Comment

Replacing Type Code with Polymorphism

Note: In this post I use the terms class, struct and entity to refer to the same thing. Please bear with me!

Replacing type code with polymorphism is one of those refactoring that are, literally, in the book. However, opportunities to refactor to polymorphism can often times be difficult to identify.

Let’s say that we are working on a SaaS system. The system has different account tiers, with different denomination, different prices, and different capabilities.

To be a little bit more specific, let’s assume just to simplify this post, that our service tracks workouts. There are three account tiers: Free, Plus and Premium, according to the following:

Free account:
– Price: free (duh!)
– Can track: runs, hikes and walks
– Number of workouts: 20 per month

Plus account:
– Price: 2 USD a month
– Can track: Everything supported by the Free Tier plus biking, swimming
– Number of workouts: 50 per month

Premium account:
– Price: 10 USD a month
– Can track: Everything supported by the Plus Tier plus yoga, pilates and roller derby.
– Number of workouts: unlimited.

So, a first attempt at implementing this model might look like this:

Now let’s imagine that we want to present the number of workouts that can be still tracked in the current month in one of our views. Given the previous model, we could do something like this:

I guess you immediately recognise an issue here: the logic in the workoutsAvailable function should be part of the Account object.

There are multiple reasons for that. First, well, that logic is part of the Account abstraction. Second, if we need to present the number of available workouts in two different places in the UI, we would have to duplicate that logic.

So, let’s do the right thing and move that code to the Account entity

It is obvious that the way clients of the Account entity can present the number of available workouts is simpler now. That is important for many different reasons, but to men the most important is readability. Reading and understanding the code in the Current.workousAvailable function takes a second, because there is no complicated logic to understand in there. And as a bonus, when there is no complicated logic to read and understand, it is more difficult to make mistakes.

But now, we also need to present the monthly price in the UI. given our previous experience with the number of available workouts, we might go directly to add that logic to the Account struct

(As a side note, the price should not be typed as a string, but as another struct called Currency, with two properties: the value and the unit it is measured in. But that’s beyond the scope of this post)

Now, notice how the Account struct is basically has the same logic duplicated in two calculated properties. Now, if we add the supported workout types to the mix, we would have three different properties implementing more or less the same logic.

We are turning our Account abstraction into something that can do three different things, depending on a type parameter.

We have code that affects the behaviour of a class, according to an internal enumeration. That is a good indicator that, maybe, the Account struct should be broken down into different classes, each and every one of them modelling only one of those behaviours.

So here is where the refactoring in the post title comes to help.

What do we really need our accounts to provide? Price, number of workouts and a boolean that tells us if that account can track a particular workout type.

Let’s model that as a protocol:

Now, and this also might be a matter for another post, there is something in that protocol that I find a little bit annoying: the lack of symmetry. So I am going to refactor it to:

Now, I shall provide a different implementation of this protocol for each account tier:

Now, each struct models a simple behaviour. There is more code, true, but the code is dumber, simpler. Each logical unit (struct) model a single behaviour. That makes the code easier to read, easier to understand, and therefore more robust and easier to maintain.

Leave a Comment

My take on iOS app architecture

TL;DR;

iOS apps have a single entry point. That single entry point can create and hold a reference to whatever we need to be global, and then inject it everywhere.

Object Oriented Design, or Architecture if you will, is a daunting topic. I believe there is never a right or wrong way to architect a software project, because the number of tradeoffs to consider is huge, so what works for a project might not be the optimal solution for the next one.

That being said, I do believe there are a basic set of practices that help build highly cohesive and decoupled code: single responsibility principle, modularity, a set of domain model objects, and dependency injection.

To illustrate my point, let’s discuss at a very simple app, that reads and writes data from and to a backend. I guess that, conceptually, covers almost 100% of the apps that are developed these days. Let’s say it is a todo list.

Domain model objects

The first step would be looking at the domain (the problem we are trying to solve) and come up with a set of abstractions that model the entities that are part of it.

In our example, we want to display todo’s, create todo’s, present a list of todo’s, and maybe share todo’s… I guess by now we all can see a model object emerging: Todo

Data manipulation.

We need to send Todos to a backend. And we need to read Todos from a backend as well. That probably implies dealing with network requests, and also with a good deal of JSON (or protocol buffers).

We don’t want to scatter those responsibilities across the codebase, even if it is just because network operations have to be done in a background thread, to avoid blocking the UI, so it makes sense to deal with all that async calls in just one place.

But, we have a difficult solution here: that one thing dealing with networking will have to be used from multiple places

A common solution to this problem is making the Thing That Handles Networking a singleton. (Note: Since I wrote the first draft of this post, three weeks ago, Soroush Khanlou wrote this excellent post about refactoring out those singletons. Go read it now!)

Singletons, per se, are neither good nor bad. Sometimes, something is a singleton and it makes sense to model it as such.

But, in my experience, it is better to move away from them, for one reason in particular: a singleton is a global variable, and as such it is a dependency that is very hard to get rid of.

Dependency Inversion

But what if we invert that dependency? And we have a huge advantage here: the iOS app architecture.

An iOS app has a single entry point (the AppDelegate, an implementation of the AppDelegate protocol).

That ensures that instances variables of the AppDelegate are going to be unique as well. Well, not completely, but let’s say that we can guarantee that an instance of a regular class is created once and only once.

You might say, and you would be right, that there is nothing preventing a developer from creating as many instances of that class as she wants. I believe the solution to that is, as Uncle Bob said, well, just create one.

Back to Data Manipulation

Another look at the domain will tell us that we want to:
– obtain a list of Todos
– obtain a Todo
– create a new Todo
– edit an existing Todo
– delete a Todo

This nothing more than a list of high level operations. We don’t really care, or need to care, at this stage about how those operations are actually implemented, so we can just declare them as a protocol.

Notice how this protocol abstracts two different responsibilities: reading and writing. This is a hint that, eventually, we might need to split the protocol in two (again, this post provides a great discussion of why it might be a good idea to do so).

However, I am not going to do it right now, in part because it is one of the points I want to make: modularity, good separation of concerns, empowers us to further break things down whenever we things it is the right moment to do so.

Now all we have to do is provide an implementation of that protocol to our UI. And the easiest way to do that is, again, relying on the fact that we have a single entry point (the App Delegate), and applying the Dependency Inversion principle. Or, if you will, inject all the things!

So a typical AppDelegate looks like this:

I am not very fond of storyboards, so I usually have a class whose responsibility is bootstrapping the UI, creating the root view controller, the navigation logic (if necessary) and preparing both for collaboration.

I create that bootstrapping logic in the App Delegate, and I would also create an instance of my service, and inject it into the bootstrapping logic:

And then my data service can be injected into any view controller:

Is this approach future-proof?

Nothing is completely future-proof, but I think this approach is flexible enough, and to me, it remains open enough for modification and extension.

  • There is good separation of concerns. There is one thing that deals with data (fetching and saving), there is one thing that creates UI, and there might or might not be one thing that handles navigation.
  • There is good modularity. Any of those things in the previous bullet point can be refactored and split into smaller pieces, if necessary. There is a clearly defined interface in between them, so if, say, I noticed that the implementation of my TodoService is starting to mic business logic and pure data transport, I can break it down in two.
  • There is good testability. Since I am injecting the TodoService into each view controller that needs to collaborate with it, I can inject a mock in my tests.

I have found that by pursuing a dependency graph in the form of a tree, where the root node is the App Delegate, I have more room for adapting to changing requirements, and I can factor and test my code better.

Leave a Comment

A journey of thousand miles…

This week I spent some time adding a media gallery to the product I’m working on. You know, one of those things that mimic the native Photos user experience, where you can swipe to left and right to navigate to the next item, zoom in and out a photo… The usual suspects.

So, in order to move fast we decided to rely a third party library for it, instead of writing it from scratch.

We already had a well defined model object to represent a media item (photo or video). But the third party library that we chose requires its own model object, which makes total sense.

Also, it is possible we might end up switching to a different library in the nearly future, so it makes sense to have a clear boundary between our code and the third party library. I call it a boundary, some people call it a wrapper, some other people would call it an abstraction layer, but the point is that we don’t want to scatter references to this third party library across our codebase, we want those references to be isolated, encapsulated in just one class.

To the point

First, let’s assume our model object, the one in our codebase, looks like this:

The model object required by the third party library looks like this:

We could discuss if having a property to mark a MediaItem as an image or a video is an indication that MediaItem is the wrong abstraction, but that’s beyond the scope of this post (hint: I think it is the wrong abstraction, that any kind of type property in any class or structs suggests that there we are trying to model two different things with just on type)

Let’s say that boundary is a class Called MediaBrowser, that, first of all, transforms our model objects to instances of the model objects required by the third party library:

Now, that code might look quite straight forward, but in plain english, it will read like this:

For each instance of MediaItem, create an instance of GalleryItem, having in mind that, when creating an instance of GalleryItem, first, we need to check if MediaItem is a photo or a video. If it is a video, we need to pass to GalleryItem’s initialiser the value of the videoURL property in MediaItem, mark it as Video. However, it MediaItem is of type Image, we need to provide its imageURL to GalleryItem’s initialiser, as well as mark GalleryItem as Image.

It’s not rocket science. But describing what galleryData() code does requires a paragraph. And every single time you read this function, you need to translate it into that paragraph in order to understand what it is doing.

That happens because the code is quite imperative . There are a lot of specific, unnecessary details in there. Unnecessary because we don’t need to be that specific to describe what we expect the galleryData() function to do.

This is what we expect: we want to map each instance of MediaItem to a brand new instance of GalleryItem. Simple as that. However, the code, again, is telling a different, more complex, story, with plenty of details that we don’t need to be made aware of every time we read it.

The declarative solution

One of the things I like most about Swift is that it provides multiple ways to model abstractions, and multiple tools that can be used to write more declarative code.

For example, we can declare initialisers in extensions. So, we could do something like this, to extend the GalleryItem object (remember, this object is part of a third party library, and therefore out of our control):

And now, this would be our galleryData() function:

This function, now, clearly express my expectation: I want to create a new GalleryItem for each MediaItem. Period. I don’t care about how that happens, I don’t care about the details, I just trust GalleryItem to do the right thing and create an instance of itself correctly.

We have turned the previous, imperative code into declarative code.

Now, in plain English the galleryData() function reads:

For each instance of MediaItem, create an instance of GalleryItem.

Rinse and repeat

In the scope of this post, there is not a huge difference in terms of lines of code, or in terms of code complexity between both solutions. This, per se, is not going to turn complex code into simple code, buggy code into robust code.

But now, imagine applying the spirit of this approach, using the tools Swift provides to write declarative code, every single time there is an opportunity to do so. That would make a significant difference. Because a journey of a thousand miles begins with a single step.

Leave a Comment

Polymorphism and protocol extensions

Allow me to start using a big word: cyclomatic complexity

Cyclo-what? Illustrate that with an example!

Let me illustrate a typical example of cyclomatic complexity. Imagine you have some entities similar to these:

Now, imagine we need to render a table view containing Images, Movies, and TextMessages. Notice how each one of those entities provides a description of itself (the data that will need to be rendered) of a completely different type. In plain English, the table cells will need to display a UIImage if the object to render is of type Image, a NSURL if the object to render is of type Movie, and a String if the object to render is of type TextMessage.

So, the obvious implementation, the one that first comes to my mind, the one I have seen in a thousand different projects in the good old Objective-C days (yes, that was sarcasm), would be declaring a method typing the parameter as id, and then cast and check the type of whatever is passed. Translated to Swift, it would look like this:

Well, that was bad in the good old Objective-C days (sarcasm again), but now, in the bright Swift present, code like that is just unacceptable.

What wait, why is that bad?

Here is where the cyclo-thingy kicks in.

That method is very apparently very simple, but in reality is very complex. Or, to be more accurate, it has the potential to become very complex, very fast.

First, as soon as we start to create different logical branches, we are starting to add different behaviours to somethign that, in fact, is just one single behaviour (in this case, rendering data in a cell). Since we are not dealing with a single behaviour anymore, it is very likely that the behavious in each one of those logical branches will start diverging more and more as time goes by.

But that is not the only reason. As soon as we start creating different logical branches, and each branch starts behaving differenly, the code starts to become more difficult to understand, which makes it more difficult to maintain.

Also, when the code is more difficult to understand, specially because it does multiple, very different things, it is easier to make mistakes. Never understimate the importance of this. This, in my experience, is the first source of bugs in every single codebase I have ever touched.

It took me years to figure it out, but once I got it, I decided to make this my only non-negotiable rule when it comes to writing code:

The Single Resposibility Principle applies to every single task in the daily practice of a software engineer, from organizing code in files, to structs, classes, methods, functions, or any other construct.

Again, let me be clear about this: to me this rule is non-negotiable. Sowftare engineering is all about trade-offs except when it comes to the Single Responsibility Principle.

One file should contain only one abstraction (a struct, a class, an enumeration, a protocol, you name it), one method should only do one thing (either render a movie, or render an image, but never, ever, render a movie or an image), one class should do just one thing, one module should deal with only one high-level concern, and so on.

Now that we got that out of the way, let’s look again at the implementation of the Cell class, because there is another violation of the SOLID principles: the Cell class is not open for extension and closed for modification. If we want to render another type (say, Audio), and since Cell is already rendering three different tyes it wouldn’t be that surprising if we had to add yet another one, we would need to edit the source code of the Cell class. And we’d need to edit it to add yet more logical branches, more complexity.

In other words, we would need to edit to make even more brittle. Not good.

So, where do protocol extensions fit into all of this?

Well, protocol extensions make composing behaviours very easy.

Now, it could be argued that the solution I am going to discuss is not the only possible solution. And that would be true. And we have already discussed an alternative solution to a problem very similar to this, by relying on plain-old polymorphism. So, one thing we could do here would be having a bunch of Cells, all of them implementing a protocol, or all of them subclasses of a base Cell class. However, I believe there is a neater way to implement this.

So, let’s start again with the same entities:

Now, let’s declare a protocol, and declare the render method in it:

The next step would be declaring a Cell class:

Notice how this class is actually empty, does not provide any behaviour at the moment. Nowm let’s start composing behaviours in extensions and protocol extensions. The first extension would make the Cell class implement the Populable protocol, and provide a “default behaviour” for it:

To be honest, having to provide a “default behaviour” is the only part of this solution I don’t like. As you can see, I typed the parameter as Cell, assuming a cell won’t have to render itself, and that way, I am providing a defaul tbehaviour that I do not expect to be necessary. And, again, that makes me feel uncomfortable.

Anyway, now I can start providing the rendering behaviour that I expect from the Cell, in separate extensions, one for each type of data I want to render:

Notice how Swift’s type inferrence makes the final code clean of any extra type information: it just works:

Now, here is the actual beauty of this solution. If I want to render a new type, all I have to do is add an extension to the Populable protocol with the logc necessary to deal with that specific type:

And, as added bonus, Xcode, with the help of the Swift compiler, will provide me extra documentation, in the form of code hints, about what types can be rendered by an instance of Cell:

codeHint-supported-types

Recap!

In object-oriented programming, polymorphism (from the Greek meaning “having multiple forms”) is the characteristic of being able to assign a different meaning or usage to something in different contexts – specifically, to allow an entity such as a variable, a function, or an object to have more than one form.

By relying in strict typing, the single responsibility principle, favouring composition over inheritance, and using protocol extensions in our advantage, we can implement very robust solutions to complex problems, with code compliant with the Single Responsibility Principle, and therefore simple to read, understand, and maintain. And, as an added benefit, easy to test.

7 Comments

Modularity in layman’s terms

Imagine that every Sunday you have the opportunity to design your week schedule.

Now, imagine that you are only allowed to design your schedule by combining pre-built blocks, and that you are given blocks like those in set A.

Screen Shot 2016-04-19 at 12.08.21 PM

And now imagine you can choose from blocks like those in set B

Screen Shot 2016-04-19 at 12.08.29 PM

Which set of blocks will allow you to build a more flexible schedule? Would the schedule built with blocks from set A be more or less difficult to adapt to change that the schedule built with blocks from set B?

That’s modularity. And that’s why the single responsibility principle matters. And that’s why methods should not be long. And that’s why classes should not be long. And that’s why view controllers that control views, do networking, and contain logic to deal with navigation are bad.

Leave a Comment

Five code smells in the making

If you have read Refactoring, and if you have not you should definitely stop reading this blog and grab a copy immediately, you should be familiar with the term code smell.

A code smell is something in the code, apparently not very important, but that is a symptom of an underlying significant problem.

Some code smells have been catalogued, but there are some others, way more subtle, that are more difficult to spot. Following is a list of some of those proto-smells, that I have catalogued in my own practice. In my experience, every time that I notice any of these, I end up needing to rethink/refactor significant parts of my code.

Please take all of them with a grain of salt, more as generic pseudo-guidelines than as strict rules. What might indicate a bad design at one given moment and in one given situation, might just be strictly necessary, and even good, in another.

Too many imports

This one is from the (good) old days, when we didn’t have Swift, and we had to import a class dependencies manually. Like animals.

If a class implementation starts with a long list of imports, there is something wrong somewhere.

Either that class has too many responsibilities and therefore is doing too much, breaking the Single Responsibility Principle, or it truly needs a lot of context, which might indicate that it is not the right abstraction or it is not collaborating with the right abstractions. In any case, this is usually a prelude to a big refactor.

This one is particularly evident in the case of an AppDelegate; if it to import needs too many classes, it is probably a good idea to introduce some abstraction.

Private enumerations or instance variables of type enumeration

If the previous smell was only applicable to Objective-C code, this one is mostly applicable to Swift.

Private enumerations usually hide either state or lack of abstraction.

I discussed a similar issue in this post, focusing on state, but the case where this smell is a symptom of lack of abstraction was beautifully described in Refactoring: replace conditional with polymorphism. This other post makes a great example.

Complicated logic.

Nested if-clauses in particular make code difficult to understand, and therefore difficult to reason about.

Complex if-clauses are a symptom of lack of abstraction

Here, When I say lack of abstraction, I mean “lack of the most basic abstraction. For example, this code:

is impossible to understand to:

  1. Anyone other than the original author.
  2. The original author, one month after writing the code.

Every time I see code like that, I start to refactor complexity out by decomposing the different parts of the conditional into separate methods. Sometimes that will be enough, some other times, that would show me that there is an abstraction I can extract even further.

Properties referencing gesture recognisers.

I haven’t found any situation yet where holding a reference to a gesture recogniser in a view controller is not a symptom of a major issue.

Holding references to gesture recognisers indicates improper management of behaviour in the UI

A gesture recogniser should be provided a selector, and then should be attached to a view. Period. If I need to hold a reference to it, that might indicate either temporal coupling (I am building the UI in sequence, and I need that sequence to be executed in a particular order) or it might indicate that I am dealing with state in the UI. None of those scenarios are particularly good.

Properties in view controllers referencing transient views.

This happens almost exclusively in view controllers.

Properties pointing to transient views in a view controller indicate that the view controller has different states.

If I need to reference a view that might or might not be on screen, that most likely means that my view controller is dealign with state. And we have already discussed why that might not be a good idea.

These are five proto-smells that help me become aware of when I start drifting towards one of those tangled messes I tend to put myself into. I always keep a vigilant eye on them to avoid not being able to see the forest for the trees.

Leave a Comment