kacper99
kacper99

Reputation: 157

SOLID principles in mvp architecture

I use model view presenter architecture in my app and I wonder what's better for respect solid principles and reusability.

So I have 4 classes: View Controller, Presenter, Model and Service. But I have a doubt in connection between presenter and service. I am not sure if I don't break single responsibility principle.

Presenter:

class WorkoutPresenter() {
  // some code

    let workoutSettingsService = WorkoutSettingsService()
    
    func changeUnitFromKGtoLBInHistory() {
        workoutSettingsService.changeUnitFromKGtoLBInHistory()
    }
    
    func changeUnitFromLBtoKGInHistory() {
        workoutSettingsService.firstFunction()
    }
    
    func changeUnitFromKGtoLBInCalendar() {
        workoutSettingsService.secondFunction()
    }
}

class WorkoutSettingService {

  func firstFunction() {
         // some code
  }
  func secondFunction() {
            // some code
  }
  func thirdFunction() {
          // some code 
  }

}

Now workout service has 3 responsibilities (first, second and third function) Or maybe better option would be create different class for each function and then call them in WorkoutService, something like:

class WorkoutSettingService {
    
    let firstFunctionClass: FirstFunctionClass
    let secondFunctionClass: SecondFunctionClass
    let thirdFunction: ThirdFunctionClass
    
    init(firstFunctionClassClass: FirstFunction, secondFunctionClass: SecondFunctionClass, thirdFunctionClass: ThirdFunctionClass) {
        self.firstFunctionClass = firstFunction
        self.secondFunctionClass = secondFunction
        self.thirdFunctionClass = thirdFunction
      
    }
    
    func firstFunctionCall() {
        firstFunctionClass.function()
    }
    func secondFunctionCall() {
        secondFunctionClass.function()
    }
    func thirdFunctionCall() {
        thirdFunctionClass.function()
    }
}

And then call it in Presenter like before. Or maybe better than accessing to this new three class is create a protocols and set delegates from service to this new specific classes?

I hope you understand what my problem is. If you have other idea how to connect presenter with service in clean way, go ahead.

Upvotes: 1

Views: 490

Answers (1)

Bharad
Bharad

Reputation: 86

The cleaner approach in my opinion would be to introduce protocols to your service class and segregate the responsibilities.

To make the example simpler, I am going to assume that func changeUnitFromKGtoLBInHistory() and func changeUnitFromLBtoKGInHistory() have to invoke a service with respect to some history data and the func changeUnitFromKGtoLBInCalendar() has to invoke current calendar data.

First we introduce 2 protocols to do that

protocol InHistoryServiceProtocol {
    func firstFunction()
    func secondFunction()
}

protocol InCalendatServiceProtocol {
    func thirdFunction()
}

Then we update the class WorkoutSettingService to conform to protocol as below:

class WorkoutSettingService: InHistoryServiceProtocol, InCalendatServiceProtocol {

  func firstFunction() {
         // some code
  }
  func secondFunction() {
            // some code
  }
  func thirdFunction() {
          // some code
  }

}

Now we use protocol composition to gracefully handle the service class in the presenter

class WorkoutPresenter {
  // some code
    typealias WorkoutServiceProtocols = InHistoryServiceProtocol & InCalendatServiceProtocol

    let workoutSettingsService: WorkoutServiceProtocols = WorkoutSettingService()
    
    func changeUnitFromKGtoLBInHistory() {
        workoutSettingsService.firstFunction()
    }
    
    func changeUnitFromLBtoKGInHistory() {
        workoutSettingsService.secondFunction()
    }
    
    func changeUnitFromKGtoLBInCalendar() {
        workoutSettingsService.thirdFunction()
    }
}

This way you have the flexibility to add/remove responsibilities in the Work out service class respecting the SOLID principles. It also becomes easy to mock the data and inject into presenter for testing.

Upvotes: 1

Related Questions