์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- Swift
- SwiftUI
- concurrency
- duno
- DynamicProgramming
- binarySearch
- ์ฐ์ํ์ค๋ถ๋ถ์์ด์ํฉ
- APPJAM
- ๊ณ ๋์ kit
- HAVIT
- SwiftUI ํํ ๋ฆฌ์ผ
- algoritm
- ๋์ ๊ณํ๋ฒ
- GroupBy
- discardableResult
- SwiftUI Tutorials
- 0์ด๋์ด์๋๊ธธ
- ์ด์งํ์
- SOPT
- URLSession
- IOS
- BFS
- SQL
- GCD
- Til
- ํ๋ก๊ทธ๋๋จธ์ค
- ๋ค์ด๋๋ฏนํ๋ก๊ทธ๋๋ฐ
- algorithm
- dfs
- ๊ธฐ์ด๋ฌธ๋ฒ
- Today
- Total
suvera-dev ๐ฅฆ
Swift) SOLID ์์น in Swift ๋ณธ๋ฌธ
SOLID ์์น์ด๋ ?
SOLID ์์น์ด๋ ๊ฐ์ฒด์งํฅ ์ค๊ณ์ ๋ ์ข์ ์ํคํ ์ณ๋ฅผ ์ค๊ณํ๊ธฐ ์ํด
์ง์ผ์ผํ๋ ์์น๋ค์ 5๊ฐ์ง๋ฅผ ์์ ์ฝ์ด๋ง ๋ฐ์ ์ ๋ฆฌํ ๋จ์ด์ ๋๋ค.
SOLID ์์น์ ์ ์์์ผํ์ฃ ?
๊ฐ๋ฐ์ ํ ๋ ๋น์ฅ ๊ธฐ๋ฅ์ ๊ตฌํํ๋ ๊ฒ๋ ์ค์ํ์ง๋ง,
์๋กญ๊ฒ ์ด๋ค ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋๊ฑฐ๋ ์ ์ง๋ณด์๊ฐ ํ์ํ ๋
๋์ฑ ์์ฐ์ฑ ์๊ณ ์ ์ฐํ๊ฒ ๋์ฒ๊ฐ ๊ฐ๋ฅํด์ผ ์ข๊ฒ ์ฃ .?
์ด๋ฌํ ์ข์ ์ค๊ณ๋ฅผ ์ํ ์ต์ํ์ ์์น๋ค์ ์ ๋ฆฌํ๊ฒ SOLID ์์น์ด๋ผ๊ณ
ํ ์ ์๋๋ฐ์. VIPER๋ MVVM๋ ๋ชจ๋ ์ด๋ฐ ์์น์ ์ ๊ฐํด์ ๋ง๋ค์ด์ก๋ค๊ณ ํฉ๋๋ค.
SOLID ์์น์ ์ ์ฉํ์ฌ ์ค๊ณํ๋ฉด !
1. ์ฌ์ฌ์ฉ๊ณผ ์ ์ง๊ด๋ฆฌ๊ฐ ์ฌ์ด, ๋ณ๊ฒฝ์ ์ ์ฐํ ์ฝ๋๋ฅผ ๊ฐ์ง๊ฒ ๋ฉ๋๋ค.
์ด๋ ํผํผํ ์ํํธ์จ์ด๋ฅผ ๋ง๋ค ์ ์๊ฒ ํ๋ฉฐ ๋์ ํ์ฅ์ฑ์ ๊ฐ์ง๊ฒ ํฉ๋๋ค.
2. ๋์ ์์ง๋ ฅ๊ณผ ๋ฎ์ ๊ฒฐํฉ๋ ( High Cohesion, Low coupling ) ์
์ ๊ณต ์ฑ
์์ ๋ณด๋๊ฒ ์๋๊ณ ๋ด ์ฝ๋์์ ๋ณผ ์ ์๋ค !
์ถ๊ฐ์ ์ผ๋ก, Swift ์์๋ SOLID ์์น์ ์๊ณ ์ ์ฉํด์ผ๋๋ ์ด์ ?
Swift๋ ๋ฉํฐํจ๋ฌ๋ค์ ์ธ์ด์ด์ง๋ง Foundation , UIKit ๋ฑ
์ฝ์ฝ์ํฐ์น ํ๋ ์์ํฌ๋ค์ ๊ธฐ๋ณธ์ ์ผ๋ก OOP์ ๊ทผ๊ฐ์ ๋๊ณ ์๋ค๊ณ ํฉ๋๋ค.
SOLID ์์น์ ์ ๋๋ก ์๊ณ ์๋ค๋ฉด ํ์์ ์ฐ๊ณ ์๋ ํด๋์ค๋ค์ด
์ ์ด๋ฐ์์ผ๋ก ๋ง๋ค์ด์ก๋์ง ์์์๊ณ ์์ผ๋ก ์ฐ๋ฆฌ๊ฐ ์์ฑํ ์ฝ๋์
์ด๋ป๊ฒ ๋ น์ฌ๋ผ์ ์์์ง ํ์ ํ ์ ์๊ฒ ์ฃ !
์ฒ์๋ถํฐ ์ฝ๋๋ฅผ ์ ์งค์๋ ์๊ฒ ์ง๋ง,
์ต์ํ ์๋ชป๋ ์ฝ๋๊ฐ ์ด๋ค๊ฑด์ง๋ฅผ ์๊ณ ํผํด๊ฐ์ ^^_ ๋ผ๋ ์ปจ์
๊ทธ๋ฌ๋ฉด 5๊ฐ์ง ์ฝ์ด์๋ ์ด๋ค ๊ฒ๋ค์ด ์๊ณ ,
Swift ์ธ์ด์๋ ์ด๋ป๊ฒ ์ ์ฉ์ด ๋ ๊น์ ?
์์๋ณด๋ฌ ๊ฐ๋ด ์๋น.
1. SRP(Single Responsibility Principle) - ๋จ์ผ ์ฑ ์ ์์น
ํด๋์ค๋ ํจ์๋ฅผ ์ค๊ณํ ๋, ๊ฐ ๋จ์๋ค์ ๋จ ํ๋์ ์ฑ ์๋ง์ ๊ฐ์ ธ์ผํ๋ค๋ ์์น !
ํ๋์ ํด๋์ค๊ฐ ๋ง์ ๋ฉ์๋ ๋ฐ ์ญํ ์ ๊ฐ์ง๊ฒ ๋๋ค๋ฉด ?
ํด๋์ค ๋ด๋ถ ํจ์๋ผ๋ฆฌ ๊ฐํ ๊ฒฐํฉ์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
ํด๋์ค ๋ด์์ ์์ ๋ฐ ์ถ๊ฐ๋ฅผ ์งํํ ๋,
๊ฐ๋ ์ฑ ์ ํ ๋ฐ ์ ์ง๋ณด์ ๋น์ฉ ์ฆ๊ฐ ๋ฑ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๊ฒ ์ฃ ..
๊ฐ ํด๋์ค ๋ณ๋ก ์ฑ ์์ ์ ์ ํ๊ฒ ๋๋ ์
์์ง๋๋ ๋๊ณ ๊ฒฐํฉ๋๋ ๋ฎ์ ํ๋ก๊ทธ๋จ์ ์ค๊ณํ๋๊ฒ ๋จ์ผ ์ฑ ์ ์์น !
SRP์ ๊ฐ์ฅ ๋ํ์ ์ธ ์๋ฐ ์ฌ๋ก๋ Massive View Controller ํ์์ ๋๋ค.
์๊ฑฐ ๋ง์ด ๋ค์ด๋ดค์ฃ ..? ์ด๋ฐ MVC์ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด
MVVM, MVP, VIPER ๋ฑ ์ฌ๋ฌ ๋ค๋ฅธ ํจํด๋ค์ด ์๊ฒจ๋๊ณ ์๋๋๊ณ ์๋๋ฐ,
๊ทธ๊ฒ๋ค์ ๊ณตํต์ ์ ๋๋ฌด ๋ง์ ์ญํ ์ ํ๊ณ ์๋ ๋ทฐ์ปจํธ๋กค๋ฌ๋ฅผ ์ชผ๊ฐ์
๋จ์ผ ์ฑ ์๋ง์ ๊ฐ์ง๋ ์ฌ๋ฌ ํด๋์ค๋ฅผ ๋ง๋ค๋ ค๊ณ ํ๋ ๊ฒ์ ๋๋ค !
SRP๋ฅผ ์งํค๊ธฐ ์ํด ๋น์ฅ ์๋ํด๋ณผ ์ ์๋ ๊ฒ ?
ํด๋์ค๋ฅผ ์๊ฒ ๋ง๋ค์ !
์ฌ์ค ํด๋์ค๊ฐ ์๋ค๋ ๊ฒ์ด SRP์ ์ถฉ๋ถ์กฐ๊ฑด์ ์๋์ง๋ง, ํ์์กฐ๊ฑด์ ๋๋ค !
๊ฐ์๊ธฐ ์ค์ณ์ง๋๊ฐ๋ ์ฑ์ผ ํ๋ก์ ํธ...
์ค์ํํธ ๋ฆฐํธ์ 10-200๋ฃฐ์ ์ ์ฉํด๋จ๋...
10-200๋ฃฐ์ด๋ ํจ์๋ 10์ค ์ด๋ด, ํด๋์ค๋ 200์ค ์ด๋ด๋ก ๋ง๋๋ ๊ฒ์ ๋๋ค..
์ฑ์ผ ์ ๋์ ํ๋ก์ ํธ๋ ํฐ ๋ฌด๋ฆฌ์์ด ๊ฐ๋ฅํ์ง๋ง
๊ฐ๋ ๊ธฐ๋ฅ์ด ๋ง์๋ ๋ทฐ์ปจ์ .. ์ปค๋ฐ์ด ์๋๊ฐ์ง๊ตฌ ๋๋ ๋ฆฌํฉํ ๋ง ํ์๋๋ฐ
์ด๋ฐ ํฐ ๊ทธ๋ฆผ์ด ์์๋ค๋..
ํจ์๋ 10์ค ๋ฃฐ์ ์งํค๋ ค๋ฉด ํจ์๋ ํ๋์ ์์ ๋ง ํด์ผ๋๋ค !!
๋ผ๋ ์์น์ ์งํฌ ์ ๋ฐ์ ์๊ณ ์ถ์ํ ๋ ๋ฒจ์ ๋ํด ๊ณ ๋ฏผ์ ํ๊ฒ ๋ฉ๋๋ค.
์์ (ํจ์)์ ์ด๋ ์์ค๊น์ง ์ชผ๊ฐ์
์ค๋ช (์ถ์ํ)ํ ๊ฒ์ธ์ง์ ๋ํด ๊ณ ๋ฏผ์ ํ๊ฒ ๋ง๋ค์ด ์ค๋๋ค.
โํด๋์ค๋ 200์คโ ๋ฃฐ์ ์งํค๋ ค๋ฉด ํ๋กํผํฐ๋ ํจ์, ๋ฉ์๋๋ฅผ
๊ทธ๋ฅ ์์ด ๊ฐ๋ ๊ณณ ์๋ฌด๋ฐ๋ ๋ง๋ค์ด์ ์ธ ์ ์์ต๋๋ค.
๊ผญ ์๊ฐ ์ด ๊ณณ์ ์์ด์ผ ํ๋ ์ด์ ๋ฅผ ์ฐพ์์ผ ํ๊ณ ,
ํด๋น ํด๋์ค์ ์์ ์ด์ ๊ฐ ์์ผ๋ฉด SRP ์๋ฐ์ด๋ค.
๊ฐ์ฅ ์ฝ๊ฒ ํ๋จํ ์ ์๋ ๋ฐฉ๋ฒ ํ๋๋, ํจ์๋ ๋ฉ์๋ ๋ด๋ถ์์
self์ ํ๋กํผํฐ๋ ๋ฉ์๋๋ฅผ ์ผ๋ง๋ ์ฐ๊ณ ์๋์ง ๋ณด๋ ๊ฒ์ด๋ผ๊ณ ํฉ๋๋ค.
๋ง์ฝ ํ๋๋ ์ฐ๊ณ ์์ง ์๋ค๋ฉด ๊ทธ ํด๋์ค ์์ ์์ ์ด์ ๊ฐ ์ ํ ์๋ ๊ฒ์ด๋ผ๊ณ
์๊ฐํด๋ ๋๊ฒ ์ฃ ..? ์๋ฌด๋๋..?
๋๋ self์ ํธ์ถ ๋น๋๊ฐ ์ ์์๋ก ํด๋์ค์ ์ฐ๊ด์ฑ์ด ๋จ์ด์ง๋ ๊ฒ์ด๋
๋์ค์ ํด๋์ค๋ฅผ ๋ฆฌํฉํ ๋ง ํ๊ฑฐ๋ ๋ค์ด์ดํธ ์์ผ์ผ ํ ์ํฉ์ด ์ค๋ฉด ์ฐ์ ์ ์ผ๋ก ๋ด์ซ์ ํ๋ณด๋ก
์ ์ฐ์ด๋๋ ๊ทธ๋ฐ... ๊ฒ์ด์ฃ !
SRP๋ ๋ชจ๋ ํจํด์ ์์์ด๋ผ๊ณ ํฉ๋๋ค.
SRP๋ฅผ ์ ๋๋ก ์งํค์ง ๋ชปํ ์ฑ๋ก ์ฝ๋ฉ์ ํ๋ฉด
๊ทธ ์ด๋ค ํจํด์ ๋์ ํด๋ณด๋ ค๊ณ ํด๋ ์ ์๋ ๊ฐ๋ฅ์ฑ์ด ๋๋ค๊ณ ํฉ๋๋ค.
์ด๋ฉ๋ฉ SRP๋ผ๋.. ์ผ๋จ.. ์์ข์ข
ํด๋์ค๋ ํ๋์ ์ญํ ๋ง ํด์ผํ๋ค๋ ๊ฒ,
๊ฐ์ฒด์งํฅ์ ๋ฐฐ์ฐ๋ฉด์ ๊ฐ์ฅ ๋จผ์ ๋ฐฐ์ฐ๋ ์์น์์๋ ์ ๋ง ์งํค๊ธฐ ์ฝ์ง ์์ ๊ฒ ๊ฐ๋ค์ !
์์ ์ฝ๋
๋์ ์์
class LoginService {
func login(id: String, pw: String) {
let userData = requestLogin()
let user = decodeUserInform(data: userData)
saveUserOnDatabase(user: user)
}
private func requestLogin() -> Data {
// Call API
return Data()
}
private func decodeUserInform(data: Data) -> User {
// Decoding User Inform from Data
return User(name: "", age: 10)
}
private func saveUserOnDatabase(user: User) {
// Save User
}
}
์์ LoginService๋ผ๋ ํด๋์ค ๋ด๋ถ์์
API ํธ์ถ, ๋์ฝ๋ฉ, ์ ์ ๋ฐ์ดํฐ ์ ์ฅ ๋ฑ ์ฌ๋ฌ๊ฐ์ง ์ญํ ์ ํ๊ณ ์๋ค์ !
์ฆ, ํด๋์ค ๋ด๋ถ์์ ํ๋์ ์ฑ ์์ด ์๋ ์ฌ๋ฌ์ฑ ์์ ๋์์ ์ง๊ณ ์๋ค๊ณ ํ ์ ์์ต๋๋ค
์ข์ ์์
protocol APIHandlerProtocol {
func requestLogin() -> Data
}
protocol DecodingHandlerProtocol {
func decode<T>(from data: Data) -> T
}
protocol DBhandlerProtocol {
func saveOnDatabase<T>(inform: T)
}
class LoginService {
let apiHandler: APIHandlerProtocol
let decodingHandler: DecodingHandlerProtocol
let dbHandler: DBhandlerProtocol
init(apiHandler: APIHandlerProtocol,
decodingHandler: DecodingHandlerProtocol,
dbHandler: DBhandlerProtocol) {
self.apiHandler = apiHandler
self.decodingHandler = decodingHandler
self.dbHandler = dbHandler
}
func login() {
let loginData = apiHandler.requestLogin()
let user: User = decodingHandler.decode(from: loginData)
dbHandler.saveOnDatabase(inform: user)
}
}
์์ ๋์ ์์์ ๋น๊ตํด์ ๊ฐ๊ฐ DB, Decoder, APIHandler ์ญํ ์ ํ๋
ํ๋กํ ์ฝ์ ๋ง๋ค์ด์ฃผ๊ณ ๊ฐ์์ ์ญํ ๋งํ๋ ๋ฉ์๋๋ง์ ๊ตฌํํ๊ฒ ํ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ LoginService์์๋ ๋จ์ง ์ด ํ๋กํ ์ฝ๋ค์ ํ์ฉํด์ ์ํธ์์ฉ๋ง์ ํ๊ณ ์์ต๋๋ค.
์ด์ ๊ณผ ๋น๊ตํด์ ํ์คํ LoginService๋ ๋ก๊ทธ์ธ์ ๊ด๋ จ๋ ๋ก์ง๋ง์ ๋ค๋ฃจ๋๋ฐ
๊ฐ๊ฐ์ ๋ชจ๋๋ค์ ํ์ฉํด์ ๋ก๊ทธ์ธ์ ๊ดํ ์ฑ ์๋ง์ ๊ฐ์ง๊ณ ์๋ค๋ ๊ฒ์ ์ ์ ์์ต๋๋ค.
2. OCP(Open-Closed Principle) - ๊ฐ๋ฐฉ, ํ์ ์์น
ํ์ฅ์๋ ์ด๋ ค์์ผ๋ ๋ณ๊ฒฝ์๋ ๋ซํ์์ด์ผํ๋ค๋ ์์น
ํ์ฅ์ ์ด๋ ค์๋ค ? ํด๋์ค์ ๊ธฐ๋ฅ์ ํ์ฅํ๋ ๊ฒ์ด ์ฌ์์ผ๋๋ค.
๋ณ๊ฒฝ์๋ ๋ซํ์๋ค ? ๊ธฐ์กด์ ๊ตฌํ๋์ด ์๋ ๊ฒ๋ค์ ๋ฐ๊พธ์ง ์๊ณ ํด๋์ค๋ฅผ ํ์ฅํ ์ ์์ด์ผํ๋ค.
์ฆ, ์ด๋ค ๊ธฐ๋ฅ์ ์ถ๊ฐํ ๋ ๊ธฐ์กด์ ์ฝ๋๋ ๋ง์ง์ง ์๊ณ ์๋ก ๋์ํ๋ ๊ธฐ๋ฅ์ ๋ํด์๋ง
์ฝ๋๊ฐ ์์ฑ์ด ๋์ด์ผํฉ๋๋ค.
์๊ตฌ์ฌํญ์ ๋ณ๊ฒฝ์ด๋ ์ถ๊ฐ์ฌํญ์ด ์๊ธฐ๋๋ผ๋ ๊ธฐ์กด ๊ตฌ์ฑ์์๋ ์์ ํ์ง ์๊ณ ,
ํ์ํ ๊ธฐ๋ฅ๋ง ํ์ฅ์ ํตํด์ ์ฌ์ฌ์ฉ ํ ์ ์๊ฒ !!
์ด๋ฌํ ํน์ฑ๋ค์ ์ถ์ํ๋ฅผ ํตํด์ ์ด๋ฃจ์ด์ง ์ ์์ต๋๋ค !
์ค์ํํธ์์ ์ถ์ํ๋ ์ฃผ๋ก Protocol์ ํตํด ์ด๋ฃจ์ด์ง๋๋ค !!
์์ SRP ์์ ์ฒ๋ผ ํ๋กํ ์ฝ์ ์ด์ฉํด์
๊ตฌํํ๋ค๋ฉด ๋ก์ง์์ ๋ณ๊ฒฝ์ฌํญ์ด ์์ ๋ ๊ฐ๊ฐ์ ํ๋กํ ์ฝ์ ๊ตฌํํ๊ณ ์๋ ๊ฐ์ฒด๋ฅผ ์ธ๋ถ์์ ์ฃผ์ ํ๋ฉด
๋๊ธฐ ๋๋ฌธ์ ์๋ก์ด ๊ธฐ๋ฅ์๋ ๋ณํ์์ด ๋์์ด ๊ฐ๋ฅํ๊ฒ ๋ฉ๋๋ค.!
OCP๋ฅผ ์ํ๊ธฐ ์ํด์๋ ๋ณํ์ง ์์ ๋ณธ์ง์ ์ธ ํน์ง (์ธํฐํ์ด์ค) ์
๋ค๋ฅธ ์์๋ก๋ถํฐ ์๋ณ๋ ์ ์๋ ๊ฐ์ฒด์ ๋ณธ์ง์ ์ธ ํน์ง (์ถ์ํ)๋ฅผ ์ ๊ตฌ๋ถํ๋ ๊ฒ์ด ์ค์ !
OCP ์๋ฐ์ ๋ํ์ ์ธ ์๋ ์ด๋ค ํ์ ์ ๋ํ ๋ฐ๋ณต์ ์ธ ๋ถ๊ธฐ๋ฌธ์ด๋ค.
์ฆ, ํ๋์ enum์ ๋ํด ์ฌ๋ฌ ๊ตฐ๋ฐ์์ ๋ฐ๋ณต์ ์ผ๋ก if/switch ๋ฌธ์ ์ฐ๊ณ ์๋ค๋ฉด
๊ณ ๋ฏผ์ ํด๋ด์ผํ๋ค. ์๋ํ๋ฉด, ์ด๋ฐ๊ฒฝ์ฐ์ ๊ธฐ๋ฅ ์ถ๊ฐ๋ case๋ฅผ ํ์ค ์ถ๊ฐํ๋ฉด ๋๋๊น ์ฝ์ง๋ง
๊ทธ๋ ๊ฒ ํ๋ ์๊ฐ ํด๋น enum์ ์ค์์นญ ํ๊ณ ์๋ ๋ชจ๋ ์ฝ๋๋ฅผ ์ฐพ์์ ์์ ํด์ค์ผํ๋ค.
OCP๋ if/switch๋ฅผ ์ต๋ํ ์ ์ฐ๋ ๋ฐฉ๋ฒ์ ํตํด ์ฐ์ตํ ์ ์๋ค.
๋ชจ๋ ๋ถ๊ธฐ๋ฌธ์ ์์ ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅํ๊ณ .. enum๊ฐ์ด ํ์ ์ ๋ถ๊ธฐํ๋ ์ง์ ์ ๋ํด์ !
๊ทผ๋ฐ ์ด ์๊ธฐ๋ฅผ ๋ฃ๊ณ ๋ง๋ ์๋๋ค๊ณ ์๊ฐํ๋๊ฒ ๋น์ฐํ๋ค..
์ด๋ป๊ฒ if/switch ์์ด ๋ถ๊ธฐ๋ฅผ ํ๋๊ณ ..
์์ ์ธ๊ธํ 10-200๋ฃฐ๊ณผ๋ ์ํธ๋ณด์์ ์ด๋ผ๋๋ฐ ๋ถ๊ธฐ๋ฌธ์ ์์ ๋ ๊ฒ๋ง์ผ๋ก๋
ํจ์ ๋ฐ ํด๋์ค์ ๊ธธ์ด๋ฅผ ๋ง์ด ์ค์ผ ์ ์๋ค.
if/switch ๋ฌธ์ ๋์ฒดํ ์ ์๋ ๋ฐฉ๋ฒ 2๊ฐ์ง
1. protocol์ ๋ง๋ค๊ณ ์์๋ฐ์ ์ฐ๋ ๋ฐฉ๋ฒ - ์ง์ ์ ์ผ๋ก OCP๋ฅผ ์งํค๋ ๊ตฌ์กฐ
2. ๊ฐ๋จํ๊ฒ ๋์ ๋๋ฆฌ๋ฅผ ํ์ฉํ๋ ๋ฐฉ๋ฒ - OCP๋ฅผ ์งํค๋ ๊ตฌ์กฐ๋ ์๋์ง๋ง, ๋ถ๊ธฐ๋ฌธ์ ์์ ๊ณ ์ถ์๋
์ ํ์ ์ผ๋ก ์ฌ์ฉํ๋ฉด ์ข๋ค.
์์์ฝ๋
1๋ฒ ํ๋กํ ์ฝ ํ์ฉ !
์ฒซ๋ฒ์งธ ์์ - ๋๋ฌผ
๊ธฐ์กด์ฝ๋
class Dog {
func makeSound() {
print("๋ฉ๋ฉ")
}
}
class Cat {
func makeSound() {
print("์ผ์น")
}
}
class Zoo {
var dogs: [Dog] = [Dog(), Dog(), Dog()]
var cats: [Cat] = [Cat(), Cat(), Cat()]
func makeAllSounds() {
dogs.forEach {
$0.makeSound()
}
cats.forEach {
$0.makeSound()
}
}
}
์ด๋ ๊ฒ ๋๋ค๋ฉด ์๋ก์ด ๋๋ฌผ์ด ์๊ฒผ์ ๋ Class๋ก ์๋กญ๊ฒ ์ ์ํ๊ณ
Zoo์ ๋ ๊ธฐ์กด ์ฝ๋๋ฅผ ์์ ํ๊ฒ ๋ฉ๋๋ค. ์๋ก์ด ๋๋ฌผ์ ๋ง๋ ๋ฉ์๋๋ฅผ ์ถ๊ฐํด์ค์ผ๊ฒ ์ฃ .. !
์ด๋ ๊ฒ ๋ถํ์ํ ๋ฉ์๋๋ค์ด ๋์ด๋๊ฒ ๋ฉ๋๋ค.
๋, ์ฌ๊ธฐ์ dog ํด๋์ค์ makeSound() ๋ผ๋ ๋ฉ์๋๋ฅผ ๋ณ๊ฒฝํ๊ฒ ๋๋ฉด,
์ด์ ๋ dog ํด๋์ค์ ์๋ ๋ฉ์๋์ด๊ธฐ ๋๋ฌธ์ Zoo class์์
dogs.makeSound() ๋ถ๋ถ์ ์๋ฌ๊ฐ ๋๊ฒ ๋ฉ๋๋ค.
๋ฌธ์ : ํด๋์ค๋ฅผ ์์ ํ๋ฉด ๋ฉ์๋๋ฅผ ๊ณ์ ์์ ํด์ผ๋๊ณ , ๋น์ทํ ํํ์ ๋ฉ์๋๊ฐ ๊ณ์ ์ถ๊ฐ๋๊ธฐ๋ ํฉ๋๋ค.
๊ทธ๋ ๋ค๋ฉด ํด๋์ค์ ๋ณธ์ง์ ์ธ ํน์ง + ํ์ฅ๋๋ ๋ถ๋ถ์ ์ด๋ป๊ฒ ๊ตฌ๋ถํ๋๊ฒ ์ข์๊น์?
protocol Animal {
func makeSound()
}
class Dog: Animal {
func makeSound() {
print("๋ฉ๋ฉ")
}
}
class Cat: Animal {
func makeSound() {
print("์ผ์น")
}
}
class Zoo {
var animals: [Animal] = []
func makeAllSounds() {
animals.forEach {
$0.makeSound()
}
}
}
์ค์ํํธ์์๋ ๋ณํ์ง ์๋ ๋ถ๋ถ์ ํ๋กํ ์ฝ์ ์ฌ์ฉํ์ฌ
์ธํฐํ์ด์คํ ํฉ๋๋ค. ๋ณํ๋ ๋ถ๋ถ์ ๊ฐ ํด๋์ค๋ณ๋ก ํ๋กํ ์ฝ์ ์ฑํํด ๊ตฌํํด์ฃผ๋ฉด ๋๊ฒ ์ฃ .
์ด๋ ๊ฒ ํ๋กํ ์ฝ์ ํ์ฉํด์ ์ค๊ณ๋ฅผ ์งํํ๊ฒ ๋๋ฉด ์๋กญ๊ฒ ๋๋ฌผ์ด ์ถ๊ฐ๋์ด๋
๊ธฐ์กด์ ์ฝ๋๋ ๋ง์ง์ง ์๊ณ ๊ทธ์ class ์๋ก์ด๋๋ฌผ: Animal์ผ๋ก ์ ์ธํ์ฌ
๊ตฌํ๋งํ๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค. ๊ทธ๋ ๊ฒ ๋๋ฉด Zoo ํด๋์ค์์๋ ๊ธฐ์กด์ ๋ฉ์๋๋ฅผ ์์ ํ ํ์ ์์ด
์๋ก์ด ๋๋ฌผ๋ค์ ์ถ๊ฐํ์ฌ ํจ์๋ฅผ ๋์ํ ์ ์๊ฒ ๋ ๊ฒ์ ๋๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก ํ๋กํ ์ฝ์ ๋ณ๊ฒฝ์ ๋ซํ์๊ธฐ ๋๋ฌธ์ makeSound() ๋ผ๋ ๋ฉ์๋๋ฅผ ์์ ํ ํ์๊ฐ ์๊ณ
์๋ก์ด ๋๋ฌผ์ด ์ถ๊ฐ๋๋ ์ํฉ์์๋ ํ์ฅ์ ์ด๋ ค์๋ค๊ณ ํ ์ ์์ต๋๋ค !
2๋ฒ ๋์ ๋๋ฆฌ ํ์ฉ !
์์ ์ค๋ช ์์ ๋ถ๊ธฐ๋ฌธ์ ์์ ๊ณ ์ถ์๋๊ฐ ์๋ค๋ฉด , ์๋ ๊ฒ ๋์ ๋๋ฆฌ๋ฅผ ์ฌ์ฉํด๋ณด๋ฉด ์ข์ ๊ฒ ๊ฐ๋ค์ !
switch reason {
case .initializing:
self.instructionMessage = "Move your phone".localized
case .excessiveMotion:
self.instructionMessage = "Slow down".localized
case .insufficientFeatures:
self.instructionMessage = "Keep moving your phone".localized
case .relocalizing:
self.instructionMessage = "Move your phone".localized
}
//์ ์ ํ ๊ณณ์ ๋์
๋๋ฆฌ ์์ฑ
let trackingStateMessages: [TrackingState.Reason : String]
= [.initializing. : "Move your phone".localized,
.excessiveMotion : "Slow down".localized,
.insufficientFeatures : "Keep moving your phone".localized,
.relocalizing : "Move your phone".localized]
//switch๋ฌธ ๋์ฒด
self.instructionMessage = trackingStateMessages[reason]
3๋ฒ ์ถ๊ฐ ์์
1๋ฒ ์์์ OCP๋ฅผ ์ ์ฉํด๋ณด๋ฉด, ์ด๋ ๊ฒ ๋ณํ์ง ์๋ ๋ถ๋ถ์ ํ๋กํ ์ฝ๋ก ์ ์ธํด์ฃผ๊ณ ,
๊ฐ ์ข ๋ฅ๋ณ ํธ๋ค๋ฌ์์ ํ๋กํ ์ฝ์ ์ฑํํ์ฌ ๊ตฌํํด์ค ์ ์์ต๋๋ค. ๊ทธ๋ฆฌ๊ณ
LoginService์์ ํ์ํ ํ์ ์ apihandler๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค !
protocol APIHandlerProtocol {
func requestAPI()
}
class getHandler: APIHandlerProtocol {
func requestAPI() {
print("getHandler")
}
}
class postHandler: APIHandlerProtocol {
func requestAPI() {
print("postHandler")
}
}
class putHandler: APIHandlerProtocol {
func requestAPI() {
print("putHandler")
}
}
class APIService {
var apiHandler: APIHandlerProtocol
init(handlerType: APIHandlerProtocol) {
apiHandler = handlerType
}
func requestAPIByHandler() {
apiHandler.requestAPI()
}
}
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let someService = APIService(handlerType: getHandler())
someService.requestAPIByHandler()
someService.apiHandler = putHandler()
someService.requestAPIByHandler()
}
}
3. LSP(Liskov Substitution Principle) - ๋ฆฌ์ค์ฝํ ์นํ ์์น
๋ถ๋ชจํด๋์ค๋ก ๋์ํ๋ ๊ณณ์์ ์์ํด๋์ค ์ธ์คํด์ค๋ฅผ ๋ฃ์ด์ฃผ์ด๋ ๋์ฒด๊ฐ ๊ฐ๋ฅํด์ผํ๋ค๋ ์์น
์์ ํด๋์ค๋ฅผ ๊ตฌํํ ๋, ๊ธฐ๋ณธ์ ์ผ๋ก ๋ถ๋ชจ ํด๋์ค์ ๊ธฐ๋ฅ์ด๋ ๋ฅ๋ ฅ๋ค์ ๋ฌผ๋ ค๋ฐ์ต๋๋ค.
์ฌ๊ธฐ์ ์์ ํด๋์ค๋ ๋์์ ํ ๋ ๋ถ๋ชจ ํด๋์ค์ ๊ธฐ๋ฅ๋ค์ ์ ํํ๋ฉด ์๋๋ค๋ ๋ป !
์ฆ, ๋ถ๋ชจ ํด๋์ค์ ํ์ ์ ์์ ํด๋์ค์ ์ธ์คํด์ค๋ฅผ ๋ฃ์ด๋ ๋๊ฐ์ด ๋์ํ์ฌ์ผ ํฉ๋๋ค.
์์ํด๋์ค๊ฐ ๋ถ๋ชจํด๋์ค์ ๊ธฐ๋ฅ์ ์ค๋ฒ๋ผ์ด๋ฉํด์ ๊ธฐ๋ฅ์ ๋ณ๊ฒฝํ๊ฑฐ๋ ์ ํํ๋ ๊ฒฝ์ฐ์
๊ฒฐ๊ณผ๊ฐ์ด ๋ค๋ฅด๊ฒ ๋์ค๋ฏ๋ก, LSP ์์น์ ์๋ฐํ ๊ฒ์ ๋๋ค.
์ ํ์ ์ธ ์๋ฐ ์ฌ๋ก๋ก๋ ์ง์ฌ๊ฐํ์ ์์๋ฐ์์ ๋ง๋ ์ ์ฌ๊ฐํ ํด๋์ค๋ฅผ ์๊ฐํ๋ฉด ๋ฉ๋๋ค!
์ ์ฌ๊ฐํ์ ๋๋น์ ๋์ด๊ฐ ๊ฐ์์ผ ํ๊ธฐ ๋๋ฌธ์ ๋๋น์ ๋์ด๋ฅผ ์์ ๋กญ๊ฒ ๋ฐ๊ฟ ์ ์๋
์ง์ฌ๊ฐํ ๋ถ๋ชจ ํด๋์ค์ ๋์์ ์ ํํด์ผ๋ง ์ํ๋ ๋์์ ๋ง๋ค ์ ์์ต๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ๊ฐ LSP์ ์๋ฐ์ด๋ค.
LSP๋ฅผ ์งํค๊ธฐ ์ํด์๋ ์ง์ฌ๊ฐํ์ด ์ ์ฌ๊ฐํ์ ์์๋ฐ๊ฑฐ๋, ์๋๋ฉด ๋๋น์ ๋์ด๋ฅผ ์์ let์ผ๋ก ๋ง๋ค์ด๋ฒ๋ฆฝ์๋ค !!
๋์ ์์
class Rectangle {
var width: Float = 0
var height: Float = 0
var area: Float {
return width * height
}
}
class Square: Rectangle {
override var width: Float {
didSet {
height = width
}
}
}
func printArea(of rectangle: Rectangle) {
rectangle.height = 3
rectangle.width = 6
print(rectangle.area)
}
let rectangle = Rectangle()
printArea(of: rectangle)
// 18
let square = Square()
printArea(of: square)
// 36
์ค์ ๋ก ์ ์ฌ๊ฐํ์ ์ง์ฌ๊ฐํ์ด๋ผ๊ณ ํ ์ ์์ต๋๋ค.
์ด ์๋ฆฌ์ ๋ฐ๋ผ ํ๋ก๊ทธ๋จ์ ๋ค์๊ณผ ๊ฐ์ด ์ค๊ณํ๊ฒ ๋๋ฉด ๋ฌธ์ ๊ฐ ์๊ธฐ๊ฒ ๋ฉ๋๋ค.
didset ๋ถ๋ถ์์ ๋ถ๋ชจ์ ํ๋กํผํฐ๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉ์ ํตํด
๋ณ๊ฒฝํ๊ณ ์๊ธฐ ๋๋ฌธ์, ์์ ์ธ์คํด์ค๋ฅผ ์์ฑํด์
๋๊ฐ์ ๋ฉ์๋์ ๋ฃ์ด๋ ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ์ด ๋์ค๊ฒ ๋ฉ๋๋ค !
์ด ๊ฒฝ์ฐ ๋ถ๋ชจ์ ์ญํ ์ ์์ ์ธ์คํด์ค์์ ๋์ผํ๊ฒ ์ํํ๊ณ ์์ง
๋ชปํ๊ธฐ ๋๋ฌธ์ LSP ์์น์ ์๋ฐํ ์ฌ๋ก๋ผ๊ณ ํ ์ ์์ด๋ค !
์ข์ ์์
protocol Shape {
var area: Float { get }
}
class Rectangle: Shape {
let width: Float
let height: Float
var area: Float {
return width * height
}
init(width: Float,
height: Float) {
self.width = width
self.height = height
}
}
class Square: Shape {
let length: Float
var area: Float {
return length * length
}
init(length: Float) {
self.length = length
}
}
์์ ๊ฐ์ด Rectangle, Square ๋๋ค Shape๋ผ๋ ํ๋กํ ์ฝ์ ์ฑํํ ํ,
์ค์ ๊ตฌํ๋ถ(area)๋ฅผ ํด๋์ค์๊ฒ ๋๊ธฐ๋ ํํ๋ก ์ค๊ณํ๋ฉด LSP์ ์ด๊ธ๋์ง ์๊ณ ํ๋ก๊ทธ๋จ์ ์ค๊ณํ ์ ์๊ฒ ์ฃ !
Shape์ ์๋ฆฌ๋ฅผ Square, Rectangle ๋ ๋ค ๋ชจ๋ ๋์ฒด๊ฐ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์
LSP๋ฅผ ์๋ฐํ์ง ์์ต๋๋ค. !
ํ์ง๋ง, LSP๋ฅผ ์ ๋ ์ด๊ธฐ์ง ์๊ณ ํ๋ก๊ทธ๋๋ฐ์ ํ๋๊ฑด ์ด๋ ค์ด ์ผ์ด๋ผ๊ณ ํฉ๋๋ค..
ํ์ง๋ง ๋๋ฌด ๋ง์ ๊ณณ์์ LSP๋ฅผ ์ด๊ธด๋ค๋ฉด ๋ฌธ์ ๊ฐ ์๊ธด๋ค.
๋ค๋ฅธ ํฐ์คํ ๋ฆฌ ์ฐธ๊ณ ...
์์ ํด๋์ค๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฝ๋ฉํ ์ ์์ด์ง๊ณ , ๊ทธ๋ ๊ฒ๋๋ฉด ์์ ์์ฒด๊ฐ ์๋ฏธ๊ฐ ์์ด์ง๊ณ OCP์กฐ์ฐจ ์งํฌ์ ์๊ฒ ๋๋ค.
์๋ฅผ ๋ค์ด UITableView๋ UITableViewCell์ ๊ธฐ์ค์ผ๋ก ๋ง๋ค์ด์ ธ ์๊ธฐ ๋๋ฌธ์
์ฐ๋ฆฌ๊ฐ ๋ง๋ ์ปค์คํ ์ ์ด LSP๋ฅผ ์งํค์ง ์๋๋ค๋ฉด ํ ์ด๋ธ๋ทฐ๋ ์ ๋๋ก ๋์ํ์ง ์์ ๊ฒ์ด๋ค.
๋ํ protocol๋ฅผ ๋ง๋๋ ์ด์ ๋ ์ถ์ํ๋ ์ธํฐํ์ด์ค๋ฅผ ๊ธฐ์ค์ผ๋ก ์ฝ๋๋ฅผ ์์ฑํ๊ธฐ ์ํด์์ธ๋ฐ
์์๋ฐ์ ํ์ ์ด protocol์ ๋ฉ์๋๋ฅผ ํดํ์์ผ๋ฒ๋ฆฌ๋ฉด
ํ๋กํ ์ฝ์ ๊ธฐ์ค์ผ๋ก ์์ฑ๋ ์ฝ๋๋ค์ด ์ค์ค์ด ๋ง๊ฐ์ง ์ ๋ฐ์ ์๋ค.
์์์ ๊ฐ์ฒด ์งํฅ ํ๋ก๊ทธ๋๋ฐ์ ์ค์ํ ๋ถ๋ถ์ด๊ณ ์ ์ฐ๋ฉด ์ ์ฉํ์ง๋ง ์๋ชป๋ ์์์ ๋ง๋ค๋ฉด ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
๋ฐ๋ฉด ๋์ ๋ฐ๋ผ์๋ LSP๋ฅผ ์๋ฐํจ์ผ๋ก์จ ํธ๋ฆฌํจ๊ณผ ๋จ์ํจ์ ์ป๊ฒ ๋ ์๋ ์๋ค.
๊ฒฐ๋ก ์ ์ผ๋ก, LSP๋ฅผ ๋ชจ๋ ๊ณณ์์ ์งํค๋ ค๊ณ ๋ง ํ๋ฉด ๋นํจ์จ์ ์ด๊ณ
๋๋ฌด ์์ฃผ ์๋ฐํ๋ฉด ์์ํ์ง ๋ชปํ ๊ฒฐ๊ณผ๋ค ๋๋ฌธ์ ์์ ์ฑ์ ํด์น๊ฒ ๋๋ค.
๊ทธ๋ฌ๋ฏ๋ก ์์์ ๋ง๋ค๋๋ LSP ์๋ฐ์ธ์ง ์๋์ง๋ฅผ ์์งํ๊ณ ์ฌ์ฉํ๋ ๊ฒ์ด ์ข๊ฒ ๋ค.
๊ฒฐ๋ก : ์ง๋์น LSP ๋ ๋นํจ์จ์ ์ด๊ณ , ์ง๋์น LSP ์๋ฐ์ ์์ ์ฑ์ ํด์น๊ธฐ ๋๋ฌธ์
๋ ์ฌ์ด์์ ์ด๋์ ๋ ์ถ๊ตฌํ ๊ฒ์ธ์ง์ ๋ํ ํ๋จ์ด ์ค์ํ ๊ฒ ๊ฐ์ต๋๋ค !
4. ISP(Interface Segregation Principle) - ์ธํฐํ์ด์ค ๋ถ๋ฆฌ ์์น
์ธํฐํ์ด์ค๋ฅผ ์ผ๋ฐํํ์ฌ ๊ตฌํํ์ง ์๋ ์ธํฐํ์ด์ค๋ฅผ ์ฑํํ๋ ๊ฒ๋ณด๋ค
๊ตฌ์ฒด์ ์ธ ์ธํฐํ์ด์ค๋ฅผ ์ฑํํ๋ ๊ฒ์ด ๋ ์ข๋ค๋ ์์น
์ธํฐํ์ด์ค๋ฅผ ์ค๊ณํ ๋, ๊ตณ์ด ์ฌ์ฉํ์ง ์๋ ์ธํฐํ์ด์ค๋ ์ฑํํ์ฌ ๊ตฌํํ์ง ๋ง๊ณ
์คํ๋ ค ํ ๊ฐ์ง์ ๊ธฐ๋ฅ๋ง์ ๊ฐ์ง๋๋ผ๋ ์ ๋ง ์ฌ์ฉํ๋ ๊ธฐ๋ฅ๋ง์ ๊ฐ์ง๋ ์ธํฐํ์ด์ค๋ก ๋ถ๋ฆฌํ๋ผ๋ ๊ฒ !
๋ญ์๋ฆฌ๋..
์ฌ์ฉํ์ง ์๋ ์ธํฐํ์ด์ค๋ ๊ตฌํํ์ง๋ง๋ผ !
์ค์ํํธ์์๋ ์ธํฐํ์ด์ค๋ฅผ ํ๋กํ ์ฝ์ ํ์ฉํ์ฌ ์ฒ๋ฆฌํ์ฃ !
ํ๋กํ ์ฝ์ ์ค๊ณํ๋ค๋ณด๋ฉด, ๋ค์ํ ๋ฉ์๋๊ฐ ๋ค์ด๊ฐ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
๋ชจ๋ ๊ฐ์ฒด์์ ๊ทธ ๋ฉ์๋๋ค์ ๋ค ํ์ฉํ๋ฉด ์๊ด์ด ์์ง๋ง
๋ช๋ช๊ฐ์ ๋ฉ์๋๊ฐ ํ์ํ์ง ์์ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค.
์ด๋ฐ๊ฒฝ์ฐ์ ISP์์น์ ์๋ฐํ๋ค๊ณ ๋ณด๋ ๊ฒ์ ๋๋ค.
์ด๋ฌํ ๊ฒฝ์ฐ์๋, ํ๋กํ ์ฝ ๋ญ์น๋ฅผ ๋์ฑ ์์ธํ๊ฒ ๋ถ๋ฆฌํ ํ์๊ฐ ์์ต๋๋ค !
ํ๋กํ ์ฝ์ ๊ฒฝ์ฐ์ ๋ง๊ฒ ๋ถ๋ฆฌํ๋ค๋ฉด, ๋ญ๋นํ๋ ๋ฉ์๋๊ฐ ์๊ฒ ๋๊ฒ ์ฃ !
๋์ ์์
protocol Shape {
var area: Float { get }
var length: Float { get }
}
class Square: Shape {
var width: Float
var height: Float
var area: Float {
return width * height
}
var length: Float {
return 0
}
init(width: Float,
height: Float) {
self.width = width
self.height = height
}
}
class Line: Shape {
var pointA: Float
var pointB: Float
var area: Float {
return 0
}
var length: Float {
return pointA - pointB
}
init(pointA: Float,
pointB: Float) {
self.pointA = pointA
self.pointB = pointB
}
}
Line, Square ๋ชจ๋ Shape์ ์์๋ฐ๋ ๊ฐ์ฒด์ด์ง๋ง
์ค์ ๋ก Square๋ length๋ผ๋ ๋ณ์๊ฐ ํ์๊ฐ ์๊ณ
Line์ area๋ผ๋ ๋ณ์๊ฐ ํ์์๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ผ์๋ ๋จ์ง Shape์ด๋ผ๋ ํ๋กํ ์ฝ์ ์ฑํํ๋ค๋ ์ด์ ๋ง์ผ๋ก ํ์์๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ์์ต๋๋ค.
์ด๋ฐ ๊ฒฝ์ฐ์ ISP์ ์์น์ ์งํค์ง ์๊ณ ์๋ค๊ณ ํ ์ ์์ ๊ฒ ๊ฐ์ต๋๋ค.
๋ถํ์ํ ๋ฉ์๋๋ฅผ ๊ตฌํํ์ง ์์ผ๋ ค๋ฉด ํ๋กํ ์ฝ์ ๋ ์์ธํ ๋ถ๋ฆฌํ๋๊ฒ ์ข๊ฒ ์ฃ !
์ข์ ์์
protocol AreaCalculatableShape {
var area: Float { get }
}
protocol LenghtCalculatableShape {
var length: Float { get }
}
class Square: AreaCalculatableShape {
var width: Float
var height: Float
var area: Float {
return width * height
}
init(width: Float,
height: Float) {
self.width = width
self.height = height
}
}
class Line: LenghtCalculatableShape {
var pointA: Float
var pointB: Float
var length: Float {
return pointA - pointB
}
init(pointA: Float,
pointB: Float) {
self.pointA = pointA
self.pointB = pointB
}
}
๊ธฐ์กด์ ํ์์๋ ๊ธฐ๋ฅ๋ค์ ๊ตฌํํ๊ณ ์๋ ์ธํฐํ์ด์ค๋ค์ ๋์ฑ ์ธ๋ถํํ์ฌ ๋๋์ด์ฃผ์์ต๋๋ค.
AreaCalculatableShape, LenghtCalculatableShape์ผ๋ก ๊ฐ๊ฐ ์ธํฐํ์ด์ค๋ฅผ ์ธ๋ถํ์์ผ
๋์ด๋ฅผ ๊ตฌํด์ผํ๋ Shape์๋ง AreaCalculatableShape ์ฑํํ์ฌ ๊ตฌํํ๊ณ
๊ธธ์ด๋ฅผ ๊ตฌํด์ผํ๋ Shape์๋ง LenghtCalculatableShape ์ฑํํ์์ต๋๋ค.
๊ฐ๊ฐ ํด๋์ค์์ ๊ตฌํํ์ง ์๋ ๋ฉ์๋๊ฐ ์๊ฒ ๋์ฃ !
๊ฐ๊ฐ์ ISP์ ์์น์ ์งํค๋ ํ๋ก๊ทธ๋จ์ ์ค๊ณ๊ฐ ๋์์ต๋๋ค.
์ด๋ ๊ฒ ISP์ ํต์ฌ์ ํ๋กํ ์ฝ์ ๋ถ๋ฆฌ๋ผ๋ ๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค !
5. DIP(Dependency Inversion Principle) - ์์กด๊ด๊ณ ์ญ์ ์์น
์์ ๋ชจ๋์ด ํ์ ๋ชจ๋์ ์์กดํ๋ฉด ์๋๊ณ ๋ ๋ชจ๋ ๋ชจ๋ ์ถ์ํ์ ์์กดํ๊ฒ ๋ง๋ค์ด์ผ ํ๋ค๋ ์์น
ํด๋์ค ์ฌ์ด์๋ ์์กด๊ด๊ณ๊ฐ ์กด์ฌํ ์ ๋ฐ์ ์์ต๋๋ค!
์์กด ๊ด๊ณ๊ฐ ์กด์ฌํ๋, ์ง์ ์ ์ผ๋ก ๊ตฌ์ฒด์ ์ธ ํด๋์ค๋ผ๋ฆฌ ์์กดํ์ง ๋ง๊ณ
๊ทธ ์ฌ์ด์ ์ต๋ํ ์ถ์ํ๋ ์ธํฐํ์ด์ค๋ฅผ ํ์ฉํด ์์กดํ๋ผ๋ ๊ฒ์ด DIP ์์น์ ๋๋ค !
์์ ๋ชจ๋์ด ํ์๋ชจ๋์ ์์กดํ๋ฉด ์๋๋ค๋ ๋ง์ด ์ง์ ์ ์ผ๋ก ์์กดํ์ง ๋ง๋ผ๋ ๋ง !
์ถ์ํ๋ฅผ ์งํํ์ฌ ๊ฐ๊ฐ์ ๋ชจ๋์ ๋ ์ถ์ํ๋ ๊ฒ์ ์์กดํ๊ฒ ๋ง๋ค์ด์ผํ๋ค๋ ๋ป์ ๋๋ค.
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ์ค๊ณํด์ผ ์ฌ์ฌ์ฉ์๋ ์ ์ฉํ๊ณ ํ๋๋ฅผ ์์ ํ๋๋ผ๋ ๋ค๋ฅธ ์์ ์ฌํญ์ด
๋ง์ด ์๋ ์ข์ ํ๋ก๊ทธ๋จ์ ์ค๊ณํ ์ ์๊ฒ ๋ฉ๋๋ค.
DIP ์์น์ ๋์ค์ Unit Test๋ฅผ ์งํํ ๋ ๋์ฑ ์ค์ํ๊ฒ ๋ ์์น์ธ๋ฐ
์์กด์ฑ ์ฃผ์ ์ด๋ผ๋ ๊ฐ๋ ์ด ๋์ต๋๋ค !.
์์ ๋ชจ๋์ ์ด๋ค ํ์ ๋ชจ๋์ ์ฌ์ฉํ ๋, ์์๋ชจ๋์์ ์ง์ ์ ์ผ๋ก
ํ์๋ชจ๋์ ์ด๊ธฐํํ์ง ์๊ณ ์ธ๋ถ์์ ํ์๋ชจ๋์ ์ด๊ธฐํ ํ ์ ์๊ฒ ํ๋ผ๋ ๋ป์ ๋๋ค !
๊ทธ๋ฆฌ๊ณ ์ด ์์ ๋ชจ๋, ํ์๋ชจ๋์ ๋ชจ๋ ์ถ์ํ๋ ๊ฐ์ฒด์ ์์กดํ ์ ์๊ฒ ํด์ผํฉ๋๋ค.
๋์์์
class APIHandler {
func request() -> Data {
return Data(base64Encoded: "This Data")!
}
}
class LoginService {
let apiHandler: APIHandler = APIHandler()
func login() {
let loginData = apiHandler.request()
print(loginData)
}
}
ํ์ฌ ์์๋ชจ๋์ธ LoginService๊ฐ ํ์ ๋ชจ๋์ธ APIHandler์ ์์กดํ๊ณ ์๋ ๊ด๊ณ๋ก
๋ง์ฝ APIHandler์ ๊ตฌํ ๋ฐฉ๋ฒ์ด ๋ณํํ๊ฒ ๋๋ฉด ํ๋ก๊ทธ๋จ์ ์ํฅ์ ๋ฏธ์น๊ฒ ๋๊ณ
์๋กญ๊ฒ LoginService๋ผ๋ ์์๋ชจ๋์ ์์ ํด์ผํ๋ ์ํฉ์ด ์ผ์ด๋ ์ ์์ต๋๋ค.
์ง์ APIHandler ํด๋์ค๋ฅผ ๊ฐ์ ธ์์ ์์กด์ ํ๊ณ ์๊ธฐ ๋๋ฌธ์ ๋ค๋ฅธ Handler๊ฐ ๋ค์ด์ค๋ ๊ฒฝ์ฐ?
์ง์ ์ฝ๋๋ฅผ ์์ ํ๊ฑฐ๋ ์ถ๊ฐํ ์ผ์ด ๋ง๊ธฐ ๋๋ฌธ !
๋ณํ์ ๋งค์ฐ ์ทจ์ฝํ ๊ตฌ์กฐ๋ผ๊ณ ํ ์ ์์ต๋๋ค..
์ด๋ฌํ ์ํฉ์ด DIP์ ์์น์ ์ด๊ธด ํ๋ก๊ทธ๋จ์ ์ค๊ณ๋ผ๊ณ ํ ์ ์์ต๋๋ค.
์ด๋ฅผ ์์ ํ๊ธฐ ์ํด ์์กด์ฑ ์ฃผ์ ์ด๋ผ๋ ๊ฒ์ ์ฌ์ฉํด์ ์์ ํด๋ณด๊ฒ ์ต๋๋ค
(DIP๋ฅผ ์ ์งํ๊ธฐ ์ํด ์์กด์ฑ์ ์ญ์ ์ํค๊ธฐ.)
์ข์ ์์
protocol APIHandlerProtocol {
func requestAPI() -> Data
}
class LoginService {
let apiHandler: APIHandlerProtocol
init(apiHandler: APIHandlerProtocol) {
self.apiHandler = apiHandler
}
func login() {
let loginData = apiHandler.requestAPI()
print(loginData)
}
}
class LoginAPI: APIHandlerProtocol {
func requestAPI() -> Data {
return Data(base64Encoded: "User")!
}
}
let loginAPI = LoginAPI()
let loginService = LoginService(apiHandler: loginAPI)
loginService.login()
์ด๋ ๊ฒ ์์ฑํ๊ฒ ๋๋ฉด LoginService๋ ๊ธฐ์กด์ APIHandler์ ์์กดํ์ง ์๊ณ
์ถ์ํ ์ํจ ๊ฐ์ฒด์ธ APIHandlerProtocol์ ์์กดํ๊ฒ ๋ฉ๋๋ค.
๊ทธ๋ ๊ธฐ ๋๋ฌธ์ APIHandlerProtocol์ ๊ตฌํ๋ถ๋ ์ธ๋ถ์์ ๋ณํ์ ๋ฐ๋ผ ์ง์ ํด์ ์ง์ ํด์ฃผ๋ฉด ๋๊ธฐ ๋๋ฌธ์
LoginService๋ ๊ตฌํ๋ถ์ ์๊ด์์ด ์ข ๋ ๋ณํ์ ๋ฏผ๊ฐํ์ง ์์
DIP์ ์์น์ ์งํจ ํ๋ก๊ทธ๋จ์ ์ค๊ณํ ์ ์๊ฒ ๋ฉ๋๋ค.
( ํ๋กํ ์ฝ ๊ตฌํ๋ถ๋ ์ธ๋ถ์์ ์ฒ๋ฆฌํด์ค ๋ค์, ๋ก๊ทธ์ธ ์๋น์ค๋ผ๋ ์ธ์คํด์ค๋ฅผ ๋ง๋ค ๋
์์กด์ฑ ์ฃผ์ ์ ์ฒ๋ฆฌํด ์ฃผ๊ธฐ ๋๋ฌธ์ ๋ณด๋ค ์ ์ฐํ ๊ตฌ์กฐ๋ก ์ฝ๋ ์์ฑ์ ํ ์ ์๋ค. )
์ด๋ ๊ฒ ์ธ๋ถ์์ ๋ด๋ถ์ ๋ณ์๋ฅผ ์ด๊ธฐํํด์ ์์กด๊ด๊ณ๋ฅผ ๊ฐ์ง๋ ๊ฒฝ์ฐ๋ฅผ ์์กด์ฑ ์ฃผ์ ์ด๋ผ๊ณ ํ๊ฒ ๋ฉ๋๋ค.
์ด ๋, ์์กด์ฑ ์ฃผ์ ์ ์ถ์ํ์์ผ ์งํํ๊ฒ ๋๋ฉด ๋์ฑ ๋ณํ์๋ ์์ ํ ํ๋ก๊ทธ๋จ์ ์ค๊ณํ ์ ์๊ฒ ๋ฉ๋๋ค.
protocol APIHandlerProtocol {
func requestAPI()
}
class getHandler: APIHandlerProtocol {
func requestAPI() {
print("getHandler")
}
}
class postHandler: APIHandlerProtocol {
func requestAPI() {
print("postHandler")
}
}
class putHandler: APIHandlerProtocol {
func requestAPI() {
print("putHandler")
}
}
class APIService {
var apiHandler: APIHandlerProtocol
init(handlerType: APIHandlerProtocol) {
apiHandler = handlerType
}
func requestAPIByHandler() {
apiHandler.requestAPI()
}
}
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let someService = APIService(handlerType: getHandler())
someService.requestAPIByHandler()
someService.apiHandler = putHandler()
someService.requestAPIByHandler()
}
}
์์ ๋ณด์ฌ๋๋ฆฐ ์ฝ๋์์๋ ์์กด์ฑ ์ฃผ์ ์ ํด์ฃผ๋ ๋ถ๋ถ์ด ์์์ต๋๋ค !
์ด์ฒ๋ผ 5๊ฐ์ง์ ์์น์ด ์๋ก ๊ด๊ณ๋ฅผ ๊ฐ๊ณ ์๋ ๊ฒ๋ ์๋ค.
ISP๋ฅผ ์งํค๊ธฐ ์ํด ๊ฒฐ๊ตญ SRP๋ฅผ ์งํค๊ฒ ๋๋ค๋๊ฐ..
๊ทธ๋ฌ๋ ์ด ์์น์ ๋ชจ๋ ์งํค๋ฉด์ ํ๋ก๊ทธ๋จ์ ์ค๊ณํ๊ธฐ๋ ํ๋ค๋ค๊ณ ์๊ฐํ๋ค
๋ค๋ค ๊ทธ๋ ๋ค๊ณ ๋งํ๊ธฐ๋ ํ๊ณ ,, ํ์ง๋ง ์ด๊ฑธ ๊ณต๋ถํ๋ฉด์, ์ด๋ค๊ฒ ๋์ ์ฝ๋์ด๊ณ ์ด๋ค๊ฒ ์ข์ ์ฝ๋์ธ์ง
ํ์ ํ ์ ์์๋ ๊ฒ ๊ฐ๋ค ๋ ์ข์๋ค !!
์์ ์ฝ๋ ์ฐธ๊ณ
[SWIFT] Swift SOLID ์์น
์๋ ํ์ธ์ ์ค๋์ SOLID ์์น์ ๋ํด ์ ๋ฆฌ๋ฅผ ํด๋ณด๋ ค๊ณ ํฉ๋๋ค. ๊ทผ๋ฐ, ์ด๊ฒ์ Swift ์ธ์ด์ ์ ๋ชฉ์์ผ์ ์ดํดํด๋ณด๊ณ ์์ฑํด๋ณด๊ฒ ์ต๋๋ค ๐ SOLID๋? SOLID ์์น์ด๋ ๊ฐ์ฒด์งํฅ ์ค๊ณ์ ๋ ์ข์ ์ํคํ ์ณ
dongminyoon.tistory.com
์ค์ํํธ๋ก ๋ค์๋ณด๋ ๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ: ํผํด์ผํ ์ฝ๋ฉ ์ต๊ด ยท Soojin Ro
๋ฐฐ๊ฒฝ ์ปดํจํฐ์ ํํ(painting)๋ฅผ ์ ๊ณตํ๊ณ ๊ฝค ์ฑ๊ณตํ ๋๊ตฐ๊ฐ๊ฐ ํ๋ก๊ทธ๋๋จธ๋ ๊ณผํ์๋ณด๋ค ํ๊ฐ์ ๊ณตํต์ ์ด ๋ ๋ง๋ค๊ณ ํ๋ค. ์ ๋ง๋ก, ํ๋ก๊ทธ๋๋ฐ์ ์ํ๋ ค๋ ๋ ธ๋ ฅ์ ํ๋ค๋ณด๋ฉด ๊ณผํ๋ณด๋ค๋ ๊ฒฝํ์ ์ผ
soojin.ro
[Design-Pattern-In-Swift] 1. SOLID ์์น์ Swift ์ฝ๋์ ์ ์ฉํด๋ณด๊ธฐ
GoF์ ๋์์ธํจํด์ด๋ผ๋ ์ฑ ์ ๊ธฐ๋ฐ์ผ๋ก ๋์์ธ ํจํด์ ๋ํด ๊ณต๋ถ๋ฅผ ํ๋ ค๊ณ ํฉ๋๋ค! ํ๋ก์ ํธ์์ ๋ฐ๋ณต์ ์ผ๋ก ๋ฐ์ํ๋ ๋ค์ํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ฌ์ฉ๋ ๋ฐฉ๋ฒ์ ๊ตฌ์กฐํ ์ํจ๊ฒ์ด ๋์์ธ ํจ
i-colours-u.tistory.com
'Language > Swift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ๊ณผ Swift - ์ ๊ทผ์ ์ด (2) | 2023.03.31 |
---|---|
๊ฐ์ฒด์งํฅ ํ๋ก๊ทธ๋๋ฐ๊ณผ Swift - Struct, Class, Property, Method (0) | 2023.03.30 |
Swift) ํ๋กํ ์ฝ ์งํฅ ํ๋ก๊ทธ๋๋ฐ (4) | 2022.04.03 |
Swift ) ๊ธฐ์ด ๋ฌธ๋ฒ 6์ผ์ฐจ - Class ์ Struct (2) | 2022.02.10 |
Swift ) Closure (0) | 2022.02.09 |