ìŒ | ì | í | ì | 목 | êž | í |
---|---|---|---|---|---|---|
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 | 31 |
- discardableResult
- duno
- SOPT
- íë¡ê·žëëšžì€
- GroupBy
- ì°ìíì€ë¶ë¶ììŽìí©
- SwiftUI Tutorials
- 0ìŽëìŽìëêžž
- HAVIT
- concurrency
- Swift
- GCD
- ê³ ëì kit
- URLSession
- dfs
- SQL
- binarySearch
- êž°ìŽë¬žë²
- IOS
- ëì ê³íë²
- Til
- algorithm
- algoritm
- SwiftUI
- ë€ìŽë믹íë¡ê·žëë°
- BFS
- ìŽì§íì
- SwiftUI íí 늬ìŒ
- DynamicProgramming
- APPJAM
- 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륌 ì§í€ê² ëë€ëê°..
ê·žë¬ë ìŽ ìì¹ì 몚ë ì§í€ë©Žì íë¡ê·žëšì ì€ê³íêž°ë íë€ë€ê³ ìê°íë€
ë€ë€ ê·žë ë€ê³ ë§íêž°ë íê³ ,, íì§ë§ ìŽê±ž ê³µë¶íë©Žì, ìŽë€ê² ëì ìœëìŽê³ ìŽë€ê² ì¢ì ìœëìžì§
íì í ì ììë ê² ê°ë€ ë ì¢ìë€ !!
ìì ìœë ì°žê³
'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 |