Object-Oriented Programming: Beyond the Basics

Oct 17 2023 · Swift 5.9, iOS 17, Xcode 15

Lesson 05: Liskov Substitution, Interface Segregation & Dependency Inversion

Demo 2

Episode complete

Play next episode

Next
Transcript

In the last demo, you learned about the Liskov Substitution principle. In this demo, you’ll put the Interface Segregation principle to work.

Open the starter playground. It already has an implementation for CarProtocol with a variety of methods. You’ll also find a group of classes representing the AI modules that access your car. Each AI module has a reference to the car it’ll control as a protocol type.

AICarControlsModule is the AI module responsible for controlling the car’s driving capabilities. It needs the methods accelerate(), brake() and steer(). It doesn’t need anything from the navigation or radio controls.

The first issue you’ll have is that the controls module has access to other systems that it neither needs nor is responsible for. This could open room for bugs where someone from the team working on the controls module could accidentally access another system. Same for the other modules — they could access the driving controls of the car, causing some serious, life-threatening situations.

CarProtocol defines four sets of completely unrelated operations. It would be best to break down that protocol into smaller protocols, where each is responsible for one system only.

To implement this, completely delete CarProtocol and replace it with the following:

protocol CarControlsProtocol {
  func accelerate()
  func brake()
  func steer()
}

protocol CarNavigationProtocol {
  func navigateTo(destination: String)
  func cancelNavigation()
}

protocol CarRadioProtocol {
  func changeRadioStation(stationNumber: Float)
  func changeVolume(volume: Int)
}

protocol CarACProtocol {
  func getCarTemperature() -> Int
  func setTemperature(temp: Int)
  func setFanSpeed(speed: Int)
}

Next, update the carReference type in each AI module to match the corresponding protocol type:

class AICarControlsModule {
  var carReference: CarControlsProtocol! // updated
}

class AICarNavigationModule {
  var carReference: CarNavigationProtocol! // updated
}

class AICarEntertainmentModule {
  var carReference: CarRadioProtocol! // updated
}

class AICarWeatherModule {
  var carReference: CarACProtocol! // updated
}

Separating out the protocols like this has two main benefits:

  1. Each module can now only access the system it needs.
  2. You can define a car type that doesn’t conform to either of those protocols, if needed. For example, some cars don’t have their own navigation system; the driver needs to rely on their phone’s navigation system to get around.

By following the SOLID principles here, you’re able to give your overall system flexibility and focus.

See forum comments
Cinema mode Download course materials from Github
Previous: Instruction 2 Next: Instruction 3