SOLID Design Principle using Swift

Solid principles, swift, design principles

SOLID Design Principle using Swift

Solid principles, swift, design principles

Lets discuss the SOLID principles in Swift.

SOLID

Five letters stands for design principles intended to make software designs more understandable, flexible and maintainable.

Concepts

  1. Single responsibility principle: a class should have only a single responsibility (i.e. changes to only one part of the software’s specification should be able to affect the specification of the class).
  2. Open/closed principle: software entities … should be open for extension, but closed for modification.
  3. Liskov substitution principle: objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.
  4. Interface segregation principle: many client-specific interfaces are better than one general-purpose interface.
  5. Dependency inversion principle: one should “depend upon abstractions, [not] concretions.”

1. What is the Single Responsibility Principle?

Let’s look at an example.

At first glance, all these methods represent functions of a air conditioner. So it makes sense to define them in the AirConditionerOld class.

Before single responsibility principle

It turns out a air conditioner can do a lot of things!

This AirConditionerOld class violates the Single Responsibility Principle. The responsibilities are:

  • A air conditioner can be Switch On or OFF features.
  • A air conditioner can provide Change Mode features.
  • A air conditioner provides Change Fan Speed features.

Protocol comes to your rescue as Super Man, So are you ready?

image from external source

We’ve decoupled a air conditioner’s responsibilities into three separate interfaces. This prevents the ‘users’ of AirConditionerOld from mixing these responsibilities.

Decoupling of AirconditionerOld Class

However, even with the use of protocols(AirConditionerOld class conforms to above protocols) to separate the multiple functions, the AirConditionerOld class still implements all these functions in its implementation.

Delegation comes to your rescue as Wonder Women.

One solution to maintain this separation of concern is for the AirConditionerOld class to delegate the SwitchOption, ModeOption, and FanSpeedOption functions of a car to other objects.

Ahh Wonder women helped me out!!!!!

The implementation of the protocol methods simply invoke the corresponding methods of these new classes.

After restructuring of AirConditionerOld class , it becomes AirConditionerNew class

I have left out some of the issues to cover in below discussion, Can you find out any other violation of any design principle?

2. What is the Open–closed principle?

We have a air-conditioner which supports SwitchOption, ModeOption, and FanSpeedOption.

Consider your product planning team add one new feature to the air-conditioner named — Humidity and requested you to support this feature in your current application.

Yeah Sure, I got new modification and its very simple.

You will open AirConditionerNew class and add the function called changeHumidity and it worked..But really is it a good way to change your software entities again and again and Is it error free? Hmmm… Time to think.

Extension comes to your rescue as Iron man.

3. What is Liskov substitution principle?

Objects in a program should be replaceable with instances of their subtypes without altering the correctness of that program.

So…what does that really mean?

Decorator Design Pattern comes to your rescue as Aquaman.

Decorator pattern suggests giving the client the ability to specify whatever combination of “features” is desired.

The solution to this class of problems involves encapsulating the original object inside an abstract wrapper interface. Both the decorator objects and the core object inherit from this abstract interface. The interface uses recursive composition to allow an unlimited number of decorator “layers” to be added to each core object.

Consider an example..

Here we have a ACFeature protocol that defines the interface all of our products will have. There’s a FullPriceAirConditioner class that implements ACFeature protocol.

The interesting thing is DiscountedAirConditioner. It is used to apply one or many discounts to a product. The way it works is it implements a ACFeature interface and wraps around a decorated FullPriceAirConditioner object. It delegates all the messages sent to it to an underlying FullPriceAirConditioner and adds (“decorates with”) additional behavior in the price() method to apply a discount to the resulting product price.

This is the Liskov Substitution Principle at work. Since DiscountedAirConditioner is a subtype of FullPriceAirConditioner, Even after we have created discountedProduct instance, Base class price and other features is intact as shown in below logs and we have replaced Object Instance with Subtypes.

4. What is Interface segregation principle?

The Interface Segregation Principle instructs us as developers to: Make fine grained interfaces that are client-specific.

Consider below example:

In this example, I need to add one feature for Centralized Air conditioner which can have multiple ac units in it. When we create CentralizedAC Class , everything seems fine But when we create Split AC class, Our NewACFeature interfaces forces SplitAC class to implement getCentralizedAirConditionerCount function which violates Interface Segregation principle.

Solution for this kind of problem is to have interfaces with single responsibility to make sure that you are not forcing your class which conforms to your protocol to implement unwanted interface which was not required at all.

Lets see the solution:

Solution

5. What is Dependency Inversion Principle?

High level modules should not depend on low level modules both should depend on Abstractions.

Here the CoreDataController is a low level module, its easy to reuse in other projects, the problem is with high level module ConversationDataController, its tightly coupled with CoreDataController.

We can solve this dependency using a Database Protocol. In this way ConversationDataController can use abstract protocol without caring for type of database used, lets see how the ConversationDataController will look after applying this.

Now you can reuse the ConversationDataController without any hazzle or hectic.

Hope this article is useful for people looking to understand solid principle, Please ❤️ to recommend this post to others 😊. Let me know your feedback. :)

References:

  1. https://en.wikipedia.org/wiki/SOLID
  2. https://github.com/Vinodh-G/SOLID-Principles-Swift