SOLID principles in Swift /iOS

Anil kothari
4 min readMay 3, 2022

--

SOLID principles inherently become a part of iOS interview rounds since the applications have too many functionalities residing inside them, which keep on continuously changing in every release.

The target audience for this blog is all the senior software engineers (4 to 9 years of experience) who are working on iOS technologies.

Before we jump up to the SOLID principles let’s try to understand the need for these principles and why so much emphasis has been given to these principles in iOS interviews.

Common problems in software applications

Rigidity: Rigidity is the tendency for software to be difficult to change, even in simple ways. Every change causes a cascade of subsequent changes in the dependent modules. e.g one small functionality change in a release touches the source code of a lot of dependent files in the app.

Fragility: Closely related to rigidity is fragility. Fragility is the tendency of the software to break in many places every time it is changed. Often the breakage occurs in areas that have no conceptual relationship with the area that was changed.

Immobility: One engineer will often discover that he needs a module that is similar to one that another engineer wrote. Immobility is the inability to reuse software from other projects or parts of the same project.

Tight Coupling: Modules that work in only one type of system and are dependent upon each other.

SOLID Principles

These were introduced by Robert C. Martin and are an acronym for five design principles intended to make software designs more understandable, flexible, and maintainable.

  1. Single Responsibility Principle (SRP)

It states that every module or class or file should have responsibility for a single part of the functionality provided by the software (for an actor).

Violation

Any time you think of the name of the class or interface with the “and” keyword. It means that you violate SRP.

Route to achieve

Try using a facade design pattern where one class is handling the objects of other classes.

Example

Below code shows DataHandler class to save the model into database, without following SRP.

Above code can be easily refactor keeping SRP in mind. One more advantage you will have that below code is testable while above is not testable.

Few other example:

A subclass of UIViewController should only handle its view and data to be shown on it. It should not be concerned with navigation (where to go) , networking, analytics, caching etc.

2. Open/Closed Principle (OCP)

A module should be open for extension but closed for modification.

Violation

Use of type checking should not be present in code.

Route to achieve

Conforming to the OCP is through the use of templates or generics.

Architectural Goals of the OCP. By using these techniques to conform to the OCP, we can create modules that are extensible, without being changed. This means that, with a little forethought, we can add new features to existing code, without changing the existing code and by only adding new code.

Example : Consider you are working on a food delivery application with two different types of users, GuestUser and SubscribedUser. You have to calculate the price of the delivery item.

In the above totalPaymentPrice method has multiple problems:

Adding one more user type will change this method.

Code is not 100% testable or you have to provide invalid objects to test line 33.

Creation of an protocol like DeliveryPricePayable resolve the issue. code is now extendable to support other different types of users as well e.g Premium Users. Just need to create Premium user class and confirming to DeliveryPricePayable protocol.

3. Liskov Substitution Principle (LSP)

Subclasses should be substitutable for their base classes.

Don’t override the methods in the derived classes which change the behaviour of the base classes.

Violation

Whenever you’re checking if an instance is of a specific type and try to handle it differently.

Conclusion

This principle is just an extension of the Open Close principle and it means that we must make sure that new derived classes are extending the base classes without changing their behaviour.

4. Interface segregation Principle (ISP)

Vision: No client should be forced to depend on methods it does not use.

Route to achieve: Create protocol with only one type of responsibility to handle and combine them in a single protocol only on need basis.

a) Encodable only for swift models to json conversion.

b) Decodable only for json to swift model conversion.

c) Codable captures both the responsibilities.

5. Dependency Inversion Principle (DIP)

This principle states that

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

Route to achieve: Dependency should be on abstractions not upon concrete classes.

Example:

An application should not have references of each module (like analytics, networking etc) in the application. Instead of that you have an interface (protocol) which can do the processing work for you.

It will be of great advantage when you are trying to move from one library to another in the application.

Suppose you are trying to change the current source code with implementation of google analytics to Firebase. Only the protocol implementation needs to be changed and not the references in all the applications.

Suggestion

During an interview try to explain the interview with valid methods which you have used while implementing the above principles. Try to give more examples from the inbuilt modules of the iOS SDK.

Where to go from here?

You can read Clean Architecture book by Robert C. Martin in which he explains all the principles along with other important topics on application architecture.

--

--

Anil kothari

More than a decade of working experience in iOS programming and publishing apps to the app store.