MVC or MVVM?

The last couple of years there has been a lot of discussion in the community about one of the most pressing issues when it comes to writing maintainable applications.

And that pressing issue is no other than the size of view controllers. View controllers tend to become a kitchen sink, a mix of responsibilities, that handle networking, deal with navigation or validate user data.

MVC, or at least the flavour of MVC recommended by Apple’s documentation has been partially blamed for it. And MVVM has been suggested as a better practice, designed to avoid finding yourself with a huge view controller that does too many things.

But here is the thing: I don’t think MVVM is intrinsically better than MVC. Nor the other way around. I have the feeling that sometimes MVVM is sold as some kind of silver bullet that, in combination with a more functional style, is going to, magically, make our lives easier.

I love the idea of separating presentation and presentation logic, which is something MVVM advocates for. But, I don’t think that, by itself, is enough. I think it is necessary to do much more than just embracing a different pattern, no matter how good that pattern looks on paper.

I believe this book (highly recommended, non-affiliated link) is the first one where I read about the idea of micro-architectures. Basically, the idea is: when facing a problem, don’t try to think too big, try to build a solution that solves the problem in a clean, extensible and testable way.

I think that micro-architectures pay off at a local scope. But the way micro-architectures really shine is by accumulation. When you start solving small, limited in scope, contained problems by architecting the crap out of them, everything else starts falling into place, and you start noticing how an application-wide architecture starts emerging.

How? A local, isolated, solution usually leads to a better solution at a wider scope, which usually shows the way to a better solution to an even wider scope.

For example, if you remove from a view controller the responsibility of creating and navigating to another view controller by adding a class to the system that takes care of doing that, you might find that if you inject that class into every other view controller you might generalise it to deal with all the navigation logic in your app. So, now, you need to find a way to inject that NavigationManager into all your view controllers, so it might make sense to have another class that takes care only of creating view controllers. It would be great if you could pass your NavigationManager to this new UIManager, so you might need something that creates both and injects one into another. That could be an ApplicationBootstrapper that you create in the App Delegate. See the pattern? Decisions at a local level propagate up, so you can build an application-wide architecture from the bottom up.

The point I am trying to make is: applying the SOLID principles everywhere, all the time, is going, by accumulation, to produce well architected, maintainable and testable applications.

Embracing MVC, MVVM, or whatever goes into fashion next, by itself, is not going to be enough. I think it is better to embrace whatever pattern you understand better, or think is good for you and your application, or you can reason about better, and keep always a vigilant and critical eye on every decision you make. Trust your instincts, and as soon as you notice a bad smell, micro-architect the crap out of whatever you are building.

Why to avoid tracking state in View Controllers

(And a hint on how to avoid it).

State is a biatch. It makes difficult to maintain code because it makes harder to reason about code.

But, if there is one place where tracking state is particularly bad, that would be, in my humble opinion, a view controller.

UIViewController is the centre of the iOS universe. Tooling, documentation, make easier to turn view controllers into huge, tangled entities with multiple responsibilities.

So in this post, I would like to focus on one specific thing that should not be responsibility of a view controller: tracking state.

State has many disguises

I have always found very difficult to define state in just one sentence. State can be many things. Is this view controller waiting for a process to complete? Is this view controller displaying a spinner? Is this view controller displaying data in edit mode? Is this view controller displaying an error message?

All those examples, and many more, are different manifestations of the same issue: a view controller is tracking state. And that’s a problem.

What’s wrong with a view controller tracking state?

A view controller, at least according to its name, should do just one thing: control a view. That, in my opinion, implies populating the controls within a view (in proper iOS-speak, that would be setting values in the view’s outlets), and passing user interaction commands to somebody else (in proper iOS speak, that would be receiving actions, and propagating them to whatever entity is in a position to deal with them).

The problem is that, as soon as we are not very strict in terms of what a view controller should or should not do, that same view controller ends up doing a little bit (or a whole lot) of everything, from networking to creating other view controllers and managing parts of the app’s navigation flow.

Navigation is something in particular that I believe should never be part of a view controller responsibility. But that requires a completely different post. In any case I recommend reading these two approaches to the problem.

But let’s pretend, just for today, that triggering navigation commands can be part of what a view controller should do.

An example

For the shake of keeping this post as short as possible, let’s consider the following example. We are working on an image editing app. We want to present a list of images to our users, in the form of a table view. When the user taps one of the table view’s rows, we transition to a photo editor.

Let’s assume, again for the shake of keeping the post short, that the view controller presenting that list of images implements UITableViewDelegate. (hint: most likely it should not implement it, but that’s a matter for an upcoming post).

So, when the user taps a row, this is what would happen.

Fair enough. We just built the simplest thing that could possibly work. Self high-five! (but again, a view controller should not trigger navigation)

Requirements change

If there is one thing we can be certain about in our craft/profession is that requirements will change.

Continuing with our example, our app has been a success, and users are demanding new features left and right. One of the most demanded features is being able to transfer images to other users. So, we want to display a list of images (again, in a table view), but now we want to launch the native sharing sheet when the user taps one picture.

We obviously want to reuse as much as possible of the implementation of the photo list that we already have, so a possible solution could be providing the view controller with some information about what it was launched for, so it can decide how to behave when the user selects an image.

So, just to recap, we want to make our view controller aware of the reason why it was launched, so it can behave according to that reason. In other words, we want to execute different actions, according to the view controller state, as a response to the same user interaction.

The simplest solution

The simplest thing that could possibly work might be something like the following:

We are letting know the view controller of its reason to be presented when we create it, and then, make it execute a different command according to that very same reason.

So, we can launch our image list like this:

There be dragons

This solution seems perfectly valid, but there be dragons.

First, we are breaking the Open Closed Principle. This principle says, more or less, that “modules should be open for extension but close for modification”. How are we breaking it?

Well, imagine that a new requirement comes in: now we need to display also a list of images, but this time, when the user selects one, we want to delete it. That would imply adding a new case to the enumeration, and a new branch to the if in the didSelect method. So, in order to extend the module (add new functionality) we need to modify the module (add new code).

Secondly, we have a more subtle issue here. We want our view controller to do different things according to its state. We want different behaviours according to different states. The problem with that, is that it is very difficult to contain that. Once you correlate your class behaviour to its state, that correlation breeds and spreads everywhere. Sometimes slowly, some times faster, but it spreads.

That correlation manifests itself in the form of if-else clauses, in particular in the form of complex if-else clauses, where you need to check the value of instance variables (properties) in order to know what your code should do.

In a nutshell, by coupling behaviour to state, you introduce complexity. Complexity in your code, complexity in the logic that your code models. And complexity is the source of most bugs: when something is complex it is more difficult to reason about it, and it is easier to oversee subtleties, to miss logical paths, to make mistakes.

So, if state is the source of most complexity, and complexity is the source of most bugs, then removing state sounds like a great idea. But, how can you remove state?

Isolate the source of your problems. Then remove it.

So far, we have stated how, in the context of view controllers, state and behaviour are a source of problems. So we could start by isolating them, and after that, removing them from the view controller.

What if we could write our didSelect method like this?

That would avoid all the issues previously discussed. The didSelect method wouldn’t need to know anything about context or internal state. It couldn’t be simpler, just two lines!

Notice also how we don’t need to track state any more. We can get rid of the property of type Destination, and of the actual Destination enumeration.

But, what is exactly ImageSelection and how would it solve the problem?

It’s all about trust

We try to develop software by modelling abstractions, usually in a way that those abstractions model behaviours.

The way I understand OOD, wearing the software architect hat is kind of being the god of your own world, a world where you create entities with specific behaviours (objects), and declare some rules about how those entities can collaborate with each other (interfaces). That implies that, if object (entity) A knows that object (entity) B provides a given collaboration rule (interface), then object A should trust object B to fulfil his duties without actually knowing what those duties are.

In our example, the view controller will tell ImageSelection to do whatever ImageSelection considers necessary to fulfil its duties.

But, remember, we need ImageSelection to have different behaviours, according to the context where the view controller is created.

So, we have a collaboration rule (the ImageSelection api), and we need different implementations of that collaboration rule. And that is called…

Polymorphism

In iOS speak, that means that ImageSelection is a protocol. And that we can have different implementations of that protocol providing different behaviours that still comply with the protocol contract (the aforementioned collaboration rules).

Let’s begin with the protocol:

Let’s say that one implementation of the ImageSelection protocol corresponds to the behaviour necessary to transition to a photo editor. It could look like this.

We could have another implementation of the ImageSelection protocol contains the logic necessary to launch the sharing sheet.

Now all we need is a way to provide an specific implementation of the ImageSelection protocol to our view controller. So, say hello to another of the SOLID principles.

Dependency inversion (and dependency injection)

The Dependency Inversion Principle says more or less “you should rely on abstractions, not concretion”. Well, if you look at the current status of the didSelect method, that is actually what is happening. That methods collaborates with an abstraction (protocol) not a concretion (instance of a class). So, we are good.

But how do we provide that abstraction to the view controller? Through dependency injection. In this case, passing the concrete implementation of the ImageSelection protocol to the view controller in its initialiser.

When we need to present the image list for users to edit a photo, we just need to provide the proper implementation of the ImageSelection protocol.

And the same when we need to present the image list to share a photo.

Final words

Let’s take look at the example we have been discussing again, trying to focus on the big picture. This is what we did:

  • Isolate whatever parts of the view controller are related to state.
  • Remove all traces of state from the view controller.
  • Abstract whatever different behaviours we might have behind an interface, and provide specific implementation of that interface for each of those behaviours.
  • Inject the behaviour, according to the context where the view controller is created.
  • Trust the collaboration contract.

That way, we achieved:

  • A cleaner view controller:
    • It doesn’t do anything it shouldn’t, according to what a view controller should be, like keeping track of state or contain logic related to state.
    • It contains simpler code, easier to understand and easier to reason about.
    • It is open for extension and closed for modification. If there is a need to display the same view controller with a different behaviour associated to it, it is just a matter of providing the view controller with a reference to a third implementation of the ImageSelection interface.
    • Testability is improved. The behaviour of the view controller when an image is selected can be mocked.
  • A set of classes, each modelling one single behaviour. Each of those classes, will be:
    • Highly cohesive (it does just one thing)
    • Loosely coupled from the rest of the system.
    • Highly testable. Each one of those classes needs to fulfil just one expectation
    • Reusable. Each implementation of the ImageSelection protocol encapsulates a behaviour, not a thing. Behaviours are easier to reuse than things. A specific example: the Photo Editor view controller might want to allow users to share the edited photo by launching the sharing sheet.
  • Cleaner, more declarative code. (I wrote three other posts about declarative vs imperative code)
  • We open the possibility of declaring a default implementation of the ImageSelection protocol in an extension, and override that default implementation only if and when necessary. POO FTW!

There are other approaches, of course. The first one that comes to mind mind would be relying on extension, instead of composition. But that would be a matter for another post. One problem at a time.

No-one actually knows what they are doing

Earlier this morning, I found myself trying to help a colleague remove some duplicated code.

There it was. The big acronym: DRY. Don’t Repeat Yourself. The mantra that every aspiring Software Craftsman repeats ad nauseam.

Duplicated code has somehow become, by far, the biggest possible issue in any code base for some kind of developers (not the colleague in this example). And that, to me, is an issue.

What did you say? Did you say DRY is bad?

I did not say that yet. But I will say it now: DRY is bad when it leads to adopting poor solutions to problems, when it leads to bad architected solutions.

A certain degree of duplication is not bad. It actually helps discover abstractions, it helps simplify the design, or at least it helps discover where it is actually necessary to have a point of extension. And this is not the first time I write about this.

In particular, a certain degree of duplication might help you avoid this:

1313789

Because, yes, excessive inheritance, or relying on inheritance to solve every single problem is bad. Very bad.

There is nothing like a “one true set of best practices”. There is always more than one solution to a single problem. To the question “what is the best way to do X?” the answer should always be “it depends”.

We have a set of tools to reach for (extension, composition, design patterns, abstraction, interfaces, abstract classes…). There is no right tool for a given problem, but depending on the situation, the same problem might be solved using a different tool or a combination of tools.

Nobody knows what they are doing

Nobody has all the answers, we are all in the process of learning to use our toolset and its applications. There are some things you (like me, and like everyone else) will only learn through experience, if you keep your eyes and mind open.

The Payroll Machine.

Or, as some would say, the story of how some complexity might be necessary sometimes. Or, yet another edition of Looking at the Wrong Abstraction.

The difficult solution

Imagine you need to develop an application that calculates a company’s payroll. Let’s assume that we have three different roles within the company (Developer, Systems Architect, Development Manager, and since this is a modern cool and hip company that does scrum, a Product Owner), and that different roles have different salaries.

The simplest approach

Well, you could argue that it does not actually matter too much, when calculating the payroll, if an employee is a Developer or a Systems Architect. So, one sensible approach might be to model all employees as instances of a class like this:

Now, calculating the payroll is just a matter of doing something like this:

Real life sucks. Or requirements change

I bet you have been there a thousand times. Your app is all app and running, processing data full steam ahead, doing what is expected to do, and doing it well, when suddenly… requirements change.

In this case, the CTO demands a new feature: he should be able to assign multipliers to specific employees, so he can modify their salaries temporarily.

The flexible solution. Or, the mega-awesome although apparently slightly over-engineered solution, that after some consideration, happens to be just awesome and not over-engineered at all

First, I’ll show you all the codez. The I’ll discuss all the codez.

Now, there are different kinds of Employees. To me, that means that each of those “kinds” has to be modelled by a different class. Why? Because they represent different behaviours. As you know, a PO does not do the same things a Developer does.

However, it is true that I am only interested in part of the behaviour of those different kinds of Employees. That is already abstracted by the interface!

Is there repetition? Yes, apparently, but I wouldn’t call it repetition, I would call it specialisation. If there is something else to be taken into account when calculating a salary (for example, manage,went might have part of their salaries payable in shares dividends and whatnot), the specific class that models a PO can implement that specific behaviour.

Also, this solution improves encapsulation. The responsibility of calculating each employee’s salary is well encapsulated, and is completely opaque to the calculatePayroll method.

Summary

Often times, a flexible solution requires more code than a simple one. Well, that’s life, I guess: if you want something done properly, you will need to put some serious work into it. It does not matter if it is installing a new fridge in your kitchen, or writing a new method in your code.

But the key here, again, is that being able to identify the right abstractions makes a huge difference in the scalability, modularity and cleanness of your code.

Sometimes nothing is something. Or the null object pattern with a touch of the decorator pattern

Or why if clauses should die in a fire.

This post has been lingering, locked up in my drafts folder (which is not an actual folder, but all the cool kids say that, so bear with me on this) for some time.

Yesterday, I stumbled upon this talk by Sandi Metz, because, yes, sometimes I search Youtube looking for recordings of talks about OOD. I am a big fun on Sandi’s talks, and this one did not disappoint me, as usual. And it also gave me the push needed to publish this post

If clauses breed, and sometimes, nothing is something

I am not a big fan of if clauses. I know they are necessary, but I try to avoid them as much as possible, specially when they are type checks.

Type checks are bad

Period. There is always someone that will tell you that type checks might be necessary sometimes, but truth is they are one of the biggest and stinkiest code smells.

“What is a type check?” you might ask. Fair enough; this is a type check:

This is the quintessential example of why type checks are wrong, and you will find a thousand slightly different variations of it on the interwebs.

What’s wrong with that? Simple

Type checks are a sign of bad design

The previous code sample is the perfect example of how a type check is a symptom of a bad abstraction. A Fish and a Spider are both animals, so they both should implement an interface declaring a move() method. Clients of Fishes and Spiders would only be aware of that abstraction and call the move() method. Period.

There is a particularly bad type of the check

And that is the one that does not look like one. It is usually in disguise, pretending to be a null check.

Here is an elaborate example. Consider a Car class:

And a CarWarehouse class:

Now, clients of the CarWarehouse want to checkout cars by name:

The forEach method will crash, because it is trying to call getName on something that is null.

Fine, you might think, I will just filter the stream to remove the objects that are null:

But that’s just bad.

Type checks breed

Once you need to start filtering your results, once a client of a class A needs to start performing a type check on the values returned to it by that class, you are going to need to repeat those checks every single time you want to use that class A.

Why? Because you expect the values returned by A to be of at least two different types: null and whatever it should actually be returning.

So, how what can I avoid those type checks?

Making your classes meet the expectations they set. Simple as that.

Which, of course, happens to be not that simple. But seriously, if clients of your class are expecting a collection of entities that respond to a particular message (note the Smalltalk-speak), make sure that all the entities your class returns respond to that message. Again, simple as that.

In the previous example, what do I want exactly? I want all the objects returned by CarWarehouse to respond to getName. Then all I have to do is return a collection of objects that respond to getName. And if there is no object to return, then I will return something else that still responds to that message.

The Decorator pattern. Sort of.

Here come the big guns! Design patterns to the rescue! Not too long ago, I ranted about how design patterns are abused.

In this particular case, I m going to adapt one of the patterns in the catalog, the Decorator Pattern, to wrap my Car objects:

Notice how SafeCar extends Car. That allows me to do the following:

Which, as you can see, is basically creating a null object, sort of. Again, I am taking the liberty of adapting the pattern to my needs.

And now, clients of my CarWarehouse can conduct their business merrily:

Summary

What matters are not the tools you have, but how you use them. Over-abstraction is bad. Over-engineering is bad. Knowing the tools in your belt, knowing how to adapt them and how to let them work together to solve your needs is what matters.

Oh, and sometimes, you need something to help you deal with nothing.

Dependency Injection will make you look cool

I love this quote:

“Dependency Injection” is a 25-dollar term for a 5-cent concept.

I love it so much that I posted it separately.

What on earth is Dependency Injection?

Every time I have to explain what is Dependency Injection, I can’t avoid picturing myself as one of those cheap comedy characters, torn between two little instances of myself siting on my shoulders, one wearing all white, the other one wearing all red.

The one in white is whispering to my ear “provide some background, start the Dependency Inversion Principle”. The one in red,though, will be jumping up and down, shouting “tell him about passing everything your class might need in the constructor”.

Yeah, I have a rich complex inner life.

The Dependency Inversion Principle

Let’s do the right thing, and start from scratch.

A. High-level modules should not depend on low-level modules. Both should depend on abstractions.

B. Abstractions should not depend on details. Details should depend on abstractions.

There you have it, the Dependency Inversion Principle in all its glory. Obviously, if you throw that to anyone’s face, you should expect at least some eye-rolling, if not some head banging (them banging your head against the nearest wall).

In a nutshell, what the principle states is that both high and low level components should depend on the same abstraction. More about that later…

Riiiiiight, but what is Dependency Injection?

Basically, it is a pattern. Not one of the patterns in the GoF, but a pattern nonetheless. A pattern employed to facilitate that both high level and low level components depend on the same abstraction, aka the Dependency Inversion Principle.

Riiiiiiight, would you mind providing an example, smartass?

First, no problem. Second, mind you colourful language, please.

But you have a point. Here is an example of a very simple multi-layer app. There is a service layer that performs operations against an specific service (a service might be an actual remote service, or just a file on disk, let’s assume for the shake or the argument that, in this case, it attacks a remote service), and a business layer on top of it that provides a domain-specific API.

Quite straightforward, right? Indeed. The problem here is, what happens if we need to change the way the service layer works? What if we want to grab the configuration from a file on disk, instead of a remote service, or even worse, decide what to do at runtime?

Yeah, we are in a bad situation. Why? Because there is a hard dependency here. The ConfigurationManager depends directly on the ConfigurationService. Those two classes are tightly coupled, the manager can not work without the service.

Sweet. You are good at describing code smells. What about a solution, please?

Sure, no problem. Dependency Injection to the rescue! No, wait! Dependency Inversion Principle to the rescue!

First, I will try to find an abstraction both the manager and the service can depend upon.

Second, I will make my service implement the ConfigurationService protocol.

Now here comes the part where we all facepalm in sync, because suddenly, the concept “Dependency Injection” makes sense. The Dependency (in this example, remember, it was the ConfigurationService) will be injected into the ConfigurationManager as a parameter in the constructor. But wait, there is more! The ConfigurationManager will not hold a reference to an specific dependency, but to an abstraction (the Configuration interface).

This last bit is important, so I am going to repeat it. The ConfigurationManager depends on an abstraction now. It is not aware of which actual service it is using, and it actually does not give a damn about it.

Summary

Dependency Injection decreases coupling, and improves the flexibility and modularity of all designs. And it is a neat term that will make you look cool if you use in front of your colleagues.

As usual, you can grab the source code on GitHub

The Open-Closed Principle

Today we are going to go through one of the five tools that every Object Oriented Designer, or just anyone not wanting his code to become a loaded gun pointing at her head, should have in her toolset: the Open/Closed Principle.

The Open/Closed Principle is one of the most mentioned, but yet most misunderstood, of the five SOLID principles. I am sure you are fed up with reading the definition all around the interwebs, but here it is anyway:

Software entities (classes, modules, functions, etc.) should be open for extension, but closed for modification.

Say what!?

Open for extension, but closed for modification. Neat. But, what does that mean? Let’s rephrase the Principle a little bit:

We should be able to modify the behaviour of a piece of code without changing the actual code that implements it.

In other words, we should have magic powers, or superpowers, or be able to bend the space-time continuum.

Having superpowers would be neat. Can I have some?

Sure, it would be neat. But it is definitely out of the scope of this post.

Let me rephrase. How can my code be open for extension but closed for modification?

Let’s go through a real life example. Real life, like in “code extracted from an actual codebase my team has to maintain”. Let’s pretend that the fact that I personally wrote the offending piece of code does not matter.

The problem

I mostly work with OVPs (that’s Online Video Platforms). I build those pesky apps that some TV providers deliver to their subscribers, and allow said subscribers to watch TV on their devices.

So, I needed to display a Program Guide. An Electronic Program Guide, actually.

An Electronic Program Guide is a list of what is going to be broadcasted during a particular range of dates/times. Let’s pretend this is what I need to display:

Screen Shot 2015-04-03 at 8.29.42 pm

Bear with me on this one, please.

As you can see, the list needs to display Movies, TV Shows, and Live events. When the user taps a particular Program, the app needs to transition to a “details” view, which is, obviously, different (different content and different layout, and even different business logic) according to the type of Program the user selected.

For historical reasons, and some practical reasons, the model object that was provided with in order to build that listing looks similar to this:

Yes, you can argue than all my troubles will end if I looked at the right abstraction, and if I did not need to rely on that “type” property. And I would agree with you: remember, there are historical reasons behind this. Anyway, all this “look at the right abstraction” thing is probably matter of another post.

But, on the other hand, relaying on the right abstraction does not change the fact that I need to navigate to different views according to the type of content I need to display.

The simplest possible solution.

I am a big fan of keeping things simple. When you keep things simple, code smells, bad designs, and bad solutions just popup in front of you when you look at the code, jumping out of the monitor, waving their arms, screaming “refactor me, refactor me!”

So, the simplest implementation that would get the job done would be:

Riiiiiiiight, a switch.

Switch is bad

No matter what they tell you, no matter what you see, switch clauses are usually a code smell. And in this particular case, ermahgawd, it is just bad. I wrote that code, and I still want to punch myself in the face overtime I see it. But why?

Well, this will not escalate well. First, and most obvious, Program is poorly designed, it is the wrong abstraction, and to workaround that bad design, it exposes a type to help identify what it actually represents. That is clearly meant to change.

But, the worst is about to come. What if I need to deal with a new type of program? I would need to update that switch. There is no way to extend this code that does not imply editing the navigateToDetails function.

This code is not open for extension and closed for modification.

Again, the simplest possible solution clearly exposes two code smells: first, Program is the wrong abstraction, or at least it is poorly designed, and second, the initial design is not easy to extend.

The better solution, open for extension and closed for modification

Let’s assume that Program is not going to change now. It will, but not at this precise moment.

If you look at the first implementation of the navigateToDetails function, you will see how all the business logic that deals with navigation is in there. That function checks the program type, and launches the command needed to navigate to the desired destination. What I want, is find a way to delay those decisions as much as possible. That way, I can deal with the problem in a generic way here.

The first step to fix my problem (remember, I want to be able to navigate to different views according to the type of Program the user selects) starts with declaring a protocol that abstracts the details of how I want to perform that navigation.

Then, I will have different implementations of that protocol. Each of those concrete implementations will deal with the details of how to navigate to the desired destination, and more importantly, they will provide a way to decide if that particular implementation is supposed to handle a Program or not.

That last part is the key of the whole refactoring. Notice how I can inject (or in less fancy words, pass as a parameter) a list of all the available implementations of the Router. My navigateToDetails function will loop those, passing them the Program. If it finds any implementation that can deal with the Program passed as parameter, it will ask the implementation found to proceed and navigate to… where? That’s the thing! The navigateToDetails function does not know where, because it doesn’t need to know.

 

Delay all decisions!

I recall reading, some time ago, that good Object Oriented Design consisted in finding ways to delay decisions. I only agree with that up to a point (I guess I have been a victim of over-engineered systems more than once), but I think it makes a good rule of thumb. If a particular part of your system knows too much about others, maybe it is time to rethink it.

But I digress. The whole point of this post was implementing a solution to a problem in a way that allows easy maintenance, and simplifies scalability.

Summary.

Object Oriented Design is all about trade-offs. Simple code usually gets the job done, but sometimes simplicity in the code brings along poor maintainability. Sometimes, ten lines of code get the work done, but sometimes you need to substitute those ten lines by a hundred lines, as long as those hundred lines provide a solid, clean and maintainable solution.

And, did I mention that unit testing the second solution is way easier?

Code samples.

You can get a couple of Swift playgrounds containing the source code to this post on Github