Saturday, October 21, 2017

Interface Segregation Principle in SOLID (Object-Oriented Design)

In this post, Let’s discuss ISP (Interface Segregation Principle) which is one of the SOLID principles of OOP design.

S  - Single Responsibility Principle
O - Open/Closed Principle
L  - Liskov Substitution Principle
I   - Interface Segregation Principle
D  - Dependency Inversion Principle

The Interface-segregation principle states that no client should be forced to depend on methods it does not use. ISP splits interfaces that are very large into smaller and more specific ones so that client will only have to know about the methods that are of interest to them. Such shrunken interfaces are also called as role interfaces.
  • Courtesy wikipedia.org

I am going to use Xcode9 and Swift 4 for the example ion this post.

Let’s take a Vehicle protocol, having necessary methods for vehicles.

  
    protocol VehicleProtocol {

        func numberOfGears() -> Int
        func isGearedOne() -> Bool
        func numberOfTyres() -> Int
    
        func start()
        func stop()    

    }


Let’s take a Car class which confirms to this protocol.

  
  class Car: VehicleProtocol  {

      func numberOfTyres() -> Int {
          return 4
      }
    
      func numberOfGears() -> Int {
          return 5
      }
    
      func isGearedOne() -> Bool {
          return true
      }
    
      func start() {
          print("starting off in first gear")
      }
    
      func stop() {
          print("stopping off in first gear")
      }
    
  }


For car, These all methods looks and fits good.

Whereas, Take a Horse class, 

  
   class Horse: VehicleProtocol  {

      func numberOfTyres() -> Int {
          return 4
      }
    
      func numberOfGears() -> Int {
          return 5
      }
    
      func isGearedOne() -> Bool {
          return true
      }
    
      func start() {
          print("starting off in first gear")
      }
    
      func stop() {
          print("stopping off in first gear")
      }
    
  }



For which below protocol methods looks very odd.

  1. numberOfGears
  2. isGearedOne
  3. numberOfTyres


If we ignore those protocols, You will end up with Build errors as shown below.



Here comes the ISP principle, Let me bring that again,

The Interface-segregation principle states that no client should be forced to depend on methods it does not use. ISP splits interfaces that are very large into smaller and more specific ones so that client will only have to know about the methods that are of interest to them. Such shrunken interfaces are also called as role interfaces.
  • Courtesy wikipedia.org

Let’s solve the above Horse scenario as per this principle.

I will separate VehicleProtocol into 2 different protocols based on their role as per the ISP principle.

  
   protocol VehicleData {

        func numberOfGears() -> Int
        func isGearedOne() -> Bool
        func numberOfTyres() -> Int
    
    }

   protocol VehicleActions {
    
        func start()
        func stop()
    
    }


VehicleData protocol’s role is to get the data of the vehicle
VehicleActions protocol’s role is to take the actions of the vehicle.

That’s how we have split a large interface into 2 small interfaces based on the role.

So now, Car can confirm to both VehicleData and VehicleActions,
Horse can confirm to VehicleActions.


  
  class Car: VehicleData, VehicleActions  {

    func numberOfTyres() -> Int {
        return 4
    }
    
    func numberOfGears() -> Int {
        return 5
    }
    
    func isGearedOne() -> Bool {
        return true
    }
    
    func start() {
        print("starting off in first gear")
    }
    
    func stop() {
        print("stopping off in first gear")
    }
    
  }

  class Horse: VehicleActions {
    
    func start() {
        print("started running")
    }
    
    func stop() {
        print("stopped running")
    }
    
  }


Now, You must have got an idea of why iOS is having two separate UITableView protocols, One for DataSource and one for Delegate :)

UITableViewDataSource
UITableViewDelegate

If you are not worried by the cell selections, You can ignore the UITableViewDelegate.

Hope this post is useful. Feel free to comment incase of any queries.