Truck Icon

Get Free Shipping with a Purchase of $25+

Truck Icon

Add complete, 24/7 vet care

Telehealth Cart

Fuzzy Membership

$79 Yearly

Subtotal$0
Savings calculated at checkout
  1. fuzzy tech

SOLID in iOS - Single Responsibility Principle?

Posted by Austin Betzer on August 29, 2022

Technology
the-signs-that-your-dog-is-choking-and-what-to-do-featured-image

Why should an iOS developer care

I have often noticed myself ignoring basic yet essential computer science concepts throughout my career. I hear and have said far too often that iOS development does not have the same complexity as other types of engineering.I was wrong, and if you share this opinion I would encourage you to reconsider. You should not strive to over-engineer your app, but you should do your best to apply these basic guidelines in their most simple form. You will notice a considerable difference in the codebase you're working in.

What is SOLID

SOLID is an acronym that stands for:

  • S: Single responsibility principle

  • O: Open–closed principle

  • L: Liskov substitution principle

  • I: Interface segregation principle

  • D: Dependency inversion principle

We will just be covering the Single responsibility principle in this article.

The S in SOLID

The S represents the Single Responsibility Principle. It was introduced by Robert C. Martin(aka. Uncle Bob). It means exactly what it says. Every object, module, and function you create should only have one responsibility. Do keep in mind these are guidelines, not rules.

Okay, but why…

  • The more responsibility something has, the more complex it becomes to maintain by you and your team.

  • It becomes less reusable. This is due to high coupling and often leads to rigid code. It also becomes easier to introduce more bugs due to an increase in side effects that scale with the increase in responsibilities.

  • It makes the implementation explicit and understood by everyone

Take a look at the example below,

Screen Shot 2022-08-31 at 4.21.54 PM

If we recall the SRP principle, every class should have a single responsibility. So, let's review each responsibility the type has currently.

  1. Calculating birthday

  2. Persisting the User's information

  3. Logging save events

Let's look at how we could potentially simplify the User's struct. I've come up with the following.

solid in ios 2

Here I've created a protocol called AgeCalulator. This may seem like a small change, but you have to remember that Swift encourages composition(pieces you can put together). So, if we were to make another object called Animal, we could reuse our AgeCalulator somewhere else.

Next, I've extracted our networking dependency from our User object altogether. By creating a UserController, I've moved the responsibility from our User object to our controller object.

Last, I've removed the responsibility of our analytics event tracking. You may have noticed it's been removed entirely. It isn't the User or user controller's job to track events. You may be asking who should be responsible for it, which is exactly the question you should be asking. I'll elaborate more in another article.

A more practical example

Now I know the above example is a very simple example. So let’s take a look at a more complex example, something that you may have even done yourself in the past.

For some context, let's consider that we are building the following feature in our app:

Use Case

We want our users to be able to track events on a day-to-day basis. To start we want our users to be able to log their exercises, meals, and weight.

Requirements

  • When tracking Weight we need to be able to track a number

  • When tracking a meal we need to be able to track the Name, Amount, and the Unit of Measurement

  • When tracking an exercise we want to be able to track the duration of the exercise as well as the type of exercise.

  • We need to track every event on our backend

Below I've created our data models

solid in ios 3

Below is a not-so-uncommon example of how someone might right this class.

solid in ios 4

If we recall the SRP principle, every class should have a single responsibility. So, let's review each responsibility the TrackerViewController currently has.

  1. Setting up the UI

  2. Saving an event

  3. Handling networking errors

  4. Managing state based on the type of tracker

  5. Navigation to the success screen

It is not super uncommon for a view controller to ultimately end up housing a multitude of implementation details, and can often lead to view controller classes with 100s if not 1000s of lines of code.

Here is an example of how we could potentially break up the logic into something a little more manageable.

Here are a few protocols I made to make the implementation a little better.

solid in ios 5

Next, I break apart TrackerViewController into their own respective classes and then opt to subclass it.

solid in ios 6

Okay, what I've done is incredibly simple.

  1. I made a few protocols to allow us to have a reusable postTrackableEvents method

  2. I created an APIClient, giving the responsibility of networking to our APIClient instead of our TrackerViewController

  3. I subclassed TrackerViewController and created three new trackers view controllers. MealTrackerViewController, WeightTrackerViewController, and ExerciseViewController.

This simple change makes every view controller have a single responsibility, abstracting all knowledge of the different types of trackers there are, removing redundant networking requests, and removing having a bloated file full of UI components.

P.S. I could have created a ViewModel but we will save that for a different article.

The more you can remove responsibilities from your class, the easier it becomes to read and maintain.

Hopefully, you found this useful and that you are able to take your code to the next level by remembering the Single Responsibility Principle.


To view, copy, and customize code on your own view this post on Engineering.Fuzzy.com on Hashnode.

Shop our best sellers

Join our mailing list and receive 10% off your first purchase