The Single Responsibility Principle in Swift

Sometimes I have a feeling that not everybody cares about where to put a piece of code which we’re writing. Sometimes, the “does it work?” question is sufficient requirement to mark a task as done. Especially, when it comes to adding new code into existing project.



Recently, we had a task to write a module which allows a user to update his data in his profile. We end up with UIViewController, which is responsible for the UI and gathering data from text fields, UserUpdater which creates a request based on ViewController data and the HTTPClient which knows how to send the request to the API.

After covering case when a user edits all his information it was a time to check if the app works well when a user changes only one field. Unfortunately, the API didn’t work as we assumed. When the API gets a JSON without some field, it assigns the null value. As a result, when we don’t send the username, the API overrides existing value with an empty string which is not an expected behavior. The solution was simple. When the app detects that some field is not changed, it should send an existing value. Easy, we’ll just put if inside ViewController while gathering data from text fields:

func updateUser() {
    let username = usernameTextField.text ?? user.username
    let description = descriptionTextView.text ?? user.description
    let changes = UserChanges(username: username, description: description)
    userUpdater.update(with: changes) { result in 
        ...
  }
}

Such solution works, but it smells with bad design. It violates the Single Responsibility Principle.


The Single Responsibility Principle – The theory

Single Responsibility Principle was introduced by Robert C. Martin (aka. Uncle Bob) and it expresses as follows:

A class should have only one reason to change.

To understand Single Responsibility Principle (SRP) do one exercise. Write down people who have the power to change something inside your app. It could be:

  • The Designer
  • The API Guy
  • The Database Guy
  • The Domain Specialist (like a lawyer or an accountant)

Of course, peoples tends to wear multiple hats. Especially in smaller companies, everything can be handled by one person. Here is all about roles not about physical persons. Think about above list like a list of actors or roles.

Finally, when you know what actors can change your app, it is the time to define what the “one reason to change” means which the Single Responsibility Principle is talking about. It means you should design your app that every class can be changed only by one actor. If the Designer could have a request to change something inside a class, then the API Guy cannot be the person who can ever have a request to change it.

So, what with our if?

I said, the above solution violated Single Responsibility Principle. How can I improve it? First, think about actors who are able to change the app in the future. The Designer can always change how the screen looks like. He can switch the order of labels, change the distance between them or add some fancy animations. On the other hand, the API Guy can fix how the API works. Someday, handling missing JSONs field won’t be a problem anymore.

Now, you have to assign our classes to actors. Remember, class can have only one actor… .

Ready? Check if we agree on ;). UIViewController should be at the mercy of The Designer, and the UserUpdater has to obey the API Guy. Now, when you know who is responsible for what, you probably know where you should move checking if fields are empty:

func update(with changes: UserChanges, completion:UserUpdateCompletionClosure) {
    let username = changes.username.isNotEmpty ? changes.username : user.username
    let description = changes.description.isNotEmpty ? changes.description : user.description
    let request = UpdateUserRequest(username: username, description: description)
    httpClient.send(request) { response in
        ...
    }
}

Conclusion

Simple “does it work?” is not a sufficient requirement for good quality code. Even the “trivial” thing where you want to put a piece of code matters. The Single Responsibility Principle points you a place where the lines fit. The Principle by saying “a class should have only one reason to change” means you should design your software that every class can be changed only by one actor.

If you follow the Single Responsibility Principle your classes will become smaller which transfers into more understandable code. However, the biggest benefit from SRP is that your software becomes less fragile and more resistant to the butterfly effect. For example, moving from the UITableView into the UICollectionView won’t affect how your software calculates prices, tax reports or any other business calculations or operations.


I hope SRP is much more understandable right now ;). If you have any questions or doubts write it in comments. I’ll be glad to help you.


… and if you enjoyed reading, please share the article with your friends by clicking here!

You Might Also Like