Looking at the wrong abstraction

Warning! The post title might be a little bit misleading. Or not. Read on, and decide.

In the coming paragraphs I am going to look at a few different issues like Swift-Objective-C interoperability, Swift extensions, and the one that actually provides the post title: how relying upon the right abstractions improves code quality and therefore maintainability.

The problem

The difficult solution

I hate (not) to make this about me, but I spend most of my time dealing with native clients that consume content from online video platforms (aka OVPs). In other words, I spent an awful lot to time building lists of Movies, TV Shows and whatnots.

For this particular difficult solution, I need to display a list like this:

The list contains two different kinds of “stuff”: movies and tv shows. To make things a little bit more (opening air quotes) interesting (closing air quotes), both Movies and TVShows are objects modelled as good old Objective-C classes, and I am not allowed to modify the source code of any of those two classes.

Ugly, yes, but Marines don’t do, Marines make do, and so on and so forth.

Now, seriously, this is more evidence supporting a concept I am trying to get across in almost every post. Start with something simple, something that gets the job done. Then look at it carefully, with a critical eye, and you will see all the code smells and bad design decisions jump off the screen, right towards you.

What’s wrong with that? Why is that ugly?

Here is the culprit: isKindOfClass. If you write Java for a living, it would be instanceof. In Swift, it would be the is operator.

YMMV, but I am going to say it as clear as I can: checking for a type at runtime is a code smell. A nasty, stinky code smell.

I know, in theory, there is a reason why isKindOfClass, instanceof and similar are part of the frameworks. In practice, I still have to find myself in a situation where relying on checking the actual type of an object does not stink, and I still have never found myself in a situation where checking the type at runtime was the best possible solution.

How can this be solved in an elegant way?

Well, as usual, taking a step back, and looking at the big picture. What is it that I am trying to achieve? Displaying Movies and TV Shows in the same listing, right?

Yes, and no. What I actually want to do is list a collection of strings. I should not care about what is actually producing those strings, about what it actually is, I should only care about how it behaves.

That is the key concept here: your abstractions would not focus on what things are, but on how things behave.

So, back to my example. If I shift from Movies and TVShows, to something-that-holds-the-data-needed-to-be-presented-in-the-listing, my listing would only have to use one entity, one abstraction.

Step 1. Declare a protocol.

I assume naming might be off. The goal is providing a method that returns the content that we want to display in the cells, already formatted properly as a single string.

Swift

1

2

3

4

protocolListItemPresenter

{

varcellContent: String{get}

}

Step 2. Declare a couple of extensions to Movie and TVShow

Extensions can be used to enforce protocol compliance. This is what The Book has to say about that:

Extensions add new functionality to an existing class, structure, or enumeration type. This includes the ability to extend types for which you do not have access to the original source code (known as retroactive modeling).

That is just what we did. Without touching Movie and TVShow, we enforced them to implement a protocol. Even better, notice how Movie and TVShow are written in Objective-C, while the extension is Swift. Neat!

Step 3. Implement the listing data source in Swift.

This is necessary. Only Swift code can use the new features in Swift (like Generics or Extensions). So this one is kind of a no brainer. But Swift is fun, so I call that a win-win!