Skip to main content

SRP 원칙

· 3 min read

SOLID란

  • 객체지향 설계에 더 좋은 아키텍쳐를 설계하기 위해 지켜야하는 원칙들의 5가지를 앞의 약어만 따서 정리한 단어
  • 디자인 패턴 중, VIPER, MVVM들도 모두 이런 원칙에 입각하여 만들어진 패턴이다
  1. SRP(Single Responsibility Principle) - 단일 책임 원칙
  • 클래스나 함수를 설계할 때, 각 단위들은 단 하나의 책임만을 가져야한다는 원칙

  • 클래스나 함수가 새롭게 변해야 한다면 하나의 역할을 가진 상태에서 새로운 것으로 변해야한다는 것(즉, 하나의 일만하고 변해도 하나의 일만 해야 한다)

  • 예제 코드

// SRP( Single Responsibility Priciple) - 단일 책임 원칙
// API, Database, Decoding (Bad Case)
class LoginServiceBad {
func login(id: String, pw: String) {
let userData = requestlogin()
let user = decodeUserInfom(data: userData)
saveUserOnDatabase(user: user)
}

private func requestlogin() -> Data {
return Data()
}

private func decodeUserInfom(data: Data) -> User {
return User(name: "testUser", age: 10)
}

private func saveUserOnDatabase(user: User) {
print("User data \(user.name) are saved!!!")
}

}

class User {
var name: String
var age: Int

init(name: String, age: Int) {
self.name = name
self.age = age
}

private func toString() {
print("My Name is: \(self.name), and \(self.age) years old")
}
}
  • LoginService 클래스가 API request, Data decoding, Database control 3가지의 기능을 모두 구현하고 있어 SRP 원칙에 어긋나게 된다
// use Protocols to

protocol APIHanlderProtocol {
func requestLogin() -> Data
}

protocol DecodingHandlerProtocol {
func decode<T>(from data: Data) -> T
}

protocol DatabaseHandlerProtocol {
func saveOnDatabase<T>(inform: T)
}

class LoginServiceNice {
let apiHandler: APIHanlderProtocol
let decodingHandler: DecodingHandlerProtocol
let databaseHandler: DatabaseHandlerProtocol

init(
apiHandler: APIHanlderProtocol,
decodingHandler: DecodingHandlerProtocol,
databaseHandler: DatabaseHandlerProtocol
) {
self.apiHandler = apiHandler
self.decodingHandler = decodingHandler
self.databaseHandler = databaseHandler
}

func login() {
let loginData = apiHandler.requestLogin()
let user: User = decodingHandler.decode(from: loginData)
databaseHandler.saveOnDatabase(inform: user)
}
}

class RequestManager: APIHanlderProtocol {
func requestLogin() -> Data {
return Data()
}
}

class DecodingManager: DecodingHandlerProtocol {
func decode<T>(from data: Data) -> T {
return User(name: "testUserName", age: 20) as! T
}
}

class DatabaseManager: DatabaseHandlerProtocol {
func saveOnDatabase<T>(inform: T) {
print("Database completed Save process")
}
}


let loginServiceNice = LoginServiceNice(
apiHandler: RequestManager(),
decodingHandler: DecodingManager(),
databaseHandler: DatabaseManager()
)

loginServiceNice.login()

  • LoginSerice 클래스는 정말 로그인 관련된 내용만 구현하게 하고 API, Decoding, Database 는 각각의 핸들러를 만들어 외부에서 주입 받아 SRP 원칙을 따르도록 변경하여 처리한다

참조