Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
레거시 프로젝트에서 의존성 주입하기
Search
Suyeol Jeon
December 05, 2019
Programming
1
2.5k
레거시 프로젝트에서 의존성 주입하기
왜 개념만 알려주고 적용 방법은 아무도 알려주지 않는가
Suyeol Jeon
December 05, 2019
Tweet
Share
More Decks by Suyeol Jeon
See All by Suyeol Jeon
성장하는 iOS 개발자 되기
devxoul
2
240
Let's TDD
devxoul
0
75
Hello, ReactorKit 👋
devxoul
0
90
Build Funnels with Google BigQuery
devxoul
0
42
RxSwift 시작하기
devxoul
1
360
ReactorKit으로 단방향 반응형 앱 만들기
devxoul
0
170
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
devxoul
10
3.2k
좋은 디자이너, 나쁜 프로젝트매니저, 이상한 개발자
devxoul
0
110
Other Decks in Programming
See All in Programming
NetworkXとGNNで学ぶグラフデータ分析入門〜複雑な関係性を解き明かすPythonの力〜
mhrtech
3
1k
私達はmodernize packageに夢を見るか feat. go/analysis, go/ast / Go Conference 2025
kaorumuta
2
490
CSC305 Lecture 01
javiergs
PRO
1
400
クラシルを支える技術と組織
rakutek
0
190
Le côté obscur des IA génératives
pascallemerrer
0
120
Railsだからできる 例外業務に禍根を残さない 設定設計パターン
ei_ei_eiichi
0
320
大規模アプリのDIフレームワーク刷新戦略 ~過去最大規模の並行開発を止めずにアプリ全体に導入するまで~
mot_techtalk
0
380
AIエージェント時代における TypeScriptスキーマ駆動開発の新たな役割
bicstone
4
1.5k
Pythonスレッドとは結局何なのか? CPython実装から見るNoGIL時代の変化
curekoshimizu
4
1.3k
iOSアプリの信頼性を向上させる取り組み/ios-app-improve-reliability
shino8rayu9
0
150
CSC509 Lecture 01
javiergs
PRO
1
430
プログラミングどうやる? ~テスト駆動開発から学ぶ達人の型~
a_okui
0
190
Featured
See All Featured
Faster Mobile Websites
deanohume
310
31k
Rails Girls Zürich Keynote
gr2m
95
14k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.7k
KATA
mclloyd
32
15k
A Modern Web Designer's Workflow
chriscoyier
697
190k
How To Stay Up To Date on Web Technology
chriscoyier
791
250k
For a Future-Friendly Web
brad_frost
180
9.9k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
507
140k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
16k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
34
6.1k
Learning to Love Humans: Emotional Interface Design
aarron
274
40k
Code Reviewing Like a Champion
maltzj
525
40k
Transcript
ۨѢद ۽ંীࢲ ઓࢿ ੑೞӝ ࣻৌ
ۨѢद ۽ંীࢲ ઓࢿ ੑೞӝ ࣻৌ ࠗઁ: ৵ ѐ֛݅ ঌ۰Ҋ ਊ
ߑߨ ইޖب ঌ۰ ঋחо
పझח য۵
పझח য۵ పझೞӝ જѱ ৈ ঋ
పझח য۵ పझೞӝ જѱ ৈ ঋ Coupling ъೞ
func fetchUser() -> Single<User> { }
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") }
✅ పझ ాҗ func fetchUser() -> Single<User> { return Networking.shared.get("/user/1")
}
✅ పझ ాҗ ⛔ పझ पಁ func fetchUser() -> Single<User>
{ return Networking.shared.get("/user/1") }
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ✅ పझ
ాҗ ⛔ పझ पಁ
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ✅ పझ
ాҗ ⛔ పझ पಁ
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ъೠ ઓ
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ъೠ ઓ
ডೠ ઓ
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ъೠ ઓ
ডೠ ઓ Networking Production
func fetchUser() -> Single<User> { return Networking.shared.get("/user/1") } ъೠ ઓ
ডೠ ઓ Networking NetworkingStub Production Testing
func fetchUser() -> Single<User> { return self.networking.get("/user/1") } ъೠ ઓ
ডೠ ઓ Networking NetworkingStub Production Testing
func fetchUser() -> Single<User> { return self.networking.get("/user/1") } UserService(networking: Networking())
func fetchUser() -> Single<User> { return self.networking.get("/user/1") } UserService(networking: Networking())
UserService(networking: NetworkingStub())
UserService(networking: Networking()) UserService(networking: NetworkingStub())
UserService(networking: Networking()) UserService(networking: NetworkingStub()) ب ফ֎ܳ য٣ࢲ ࢤࢿ೧ਃ?
Composition Root
Composition Root ઓࢿ Ӓېо ٜ݅যח Ҕ
Composition Root ઓࢿ Ӓېо ٜ݅যח Ҕ ۽Ӓ۔ ੑ
Composition Root ઓࢿ Ӓېо ٜ݅যח Ҕ ۽Ӓ۔ ੑ (=AppDelegate)
User Repo List Repo Detail
User Repo List Repo Detail
User Repo List Repo Detail UserService RepoService
User Repo List Repo Detail UserService RepoService Networking Networking
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module Composition
Root ীࢲ ࢤࢿ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module AppDependency
struct AppDependency { let window: UIWindow } CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
} CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
static func resolve() -> AppDependency { } } CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
static func resolve() -> AppDependency { return AppDependency( ) } } CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
static func resolve() -> AppDependency { return AppDependency( window: ... ) } } CompositionRoot
struct AppDependency { let window: UIWindow } extension AppDependency {
} CompositionRoot static func resolve() -> AppDependency { return AppDependency( window: ... ) }
let window = UIWindow() return AppDependency( window: window )
let window = UIWindow() window.rootViewController = ... return AppDependency( window:
window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
let networking = Networking() let window = UIWindow() window.rootViewController =
ListVC( userService: UserService( networking: networking ), detailVCFactory: { DetailVC( repoService: RepoService( networking: networking ) ) } ) return AppDependency( window: window )
AppDelegate AppDependency
class AppDelegate { var window: UIWindow? func application( _ application:
UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = UIWindow(...) self.window?.makeKeyAndVisible() return true } }
class AppDelegate { let dependency: AppDependency var window: UIWindow? func
application( _ application: UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = UIWindow(...) self.window?.makeKeyAndVisible() return true } }
class AppDelegate { let dependency: AppDependency var window: UIWindow? private
override init() { } func application( _ application: UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = UIWindow(...) self.window?.makeKeyAndVisible() return true } }
class AppDelegate { let dependency: AppDependency var window: UIWindow? private
override init() { self.dependency = AppDependency.resolve() } func application( _ application: UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = UIWindow(...) self.window?.makeKeyAndVisible() return true } }
class AppDelegate { let dependency: AppDependency var window: UIWindow? private
override init() { self.dependency = AppDependency.resolve() } func application( _ application: UIApplication, didFinishLaunchingWithOptions ... ) -> Bool { self.window = self.dependency.window self.window?.makeKeyAndVisible() return true } }
Composition Rootо పझ ജ҃ীࢲ प೯غ ঋب۾
Composition Rootо పझ ജ҃ীࢲ प೯غ ঋب۾ UIApplicationMain( CommandLine.argc, CommandLine.unsafeArgv, NSStringFromClass(UIApplication.self),
NSStringFromClass(NSClassFromString("MyTests.TestAppDelegate") ?? AppDelegate.self) )
Composition Rootо పझ ജ҃ীࢲ प೯غ ঋب۾ UIApplicationMain( CommandLine.argc, CommandLine.unsafeArgv, NSStringFromClass(UIApplication.self),
NSStringFromClass(NSClassFromString("MyTests.TestAppDelegate") ?? AppDelegate.self) ) https://github.com/devxoul/Pure
Composition Rootח పझ ജ҃ীࢲ प೯غݶ উػ
Composition Rootח పझ ജ҃ীࢲ प೯غݶ উػ ࢤࢿ ഐ ৻ ٘ח
ઁ
ۿ જ݅ അप ޙઁ
ۿ જ݅ അप ޙઁ ઓࢿ Ӓېী ࣘೞ ޅೠ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
ઓࢿ Ӓېী ࣘೞ ޅೠ
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵?
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵? 1. ੋఠಕझী ઓೠ
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵? 1. ੋఠಕझী ઓೠ UserService.shared.fetchUser()
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵? 1. ੋఠಕझী ઓೠ 2.
ੋझఢझܳ ࢤࢿೠ UserService.shared.fetchUser()
ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵? 1. ੋఠಕझী ઓೠ 2.
ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC() UserService.shared.fetchUser()
ೞաঀ ೧Ѿ೧ ࠇद.
Ҿӓ ݾ
Ҿӓ ݾ ݽٚ ېझо ઓࢿ Ӓېী ࣘೞѱ ػ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
Ҿӓ ݾ ݽٚ ېझо ઓࢿ Ӓېী ࣘೞѱ ػ അप ݾ
Ҿӓ ݾ ݽٚ ېझо ઓࢿ Ӓېী ࣘೞѱ ػ അप ݾ
যઁࠁ ؊ ա ٘ܳ ࢿೠ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module যઁ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module য়ט
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+1
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+2
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+3
1. ੋఠಕझী ઓೠ 2. ੋझఢझܳ ࢤࢿೠ let detailVC
= DetailVC() UserService.shared.fetchUser() ઓࢿ Ӓېী ࣘೞ ޅೠ. ৵?
1. ੋఠಕझী ઓೠ UserService.shared.fetchUser()
1. ੋఠಕझী ઓೠ ࢤࢿ۽ ׳߉ח UserService.shared.fetchUser()
1. ੋఠಕझী ઓೠ ࢤࢿ۽ ׳߉ח UserService.shared.fetchUser() init(userService: UserService)
1. ੋఠಕझী ઓೠ ࢤࢿ۽ ׳߉ח UserService.shared.fetchUser() init(userService: UserService) self.userService.fetchUser()
۽షਃ? рചחਃ??
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ যب ৻ࠗীࢲ ੑೡ
ࣻ ѱ غ
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ যب ৻ࠗীࢲ ੑೡ
ࣻ ѱ غ ਃ೧ ٸ ۽షਸ ٜ݅
1.1 ੋఠಕझী बпೞѱ ઓೠ UserService.shared.fetchUser()
1.1 ੋఠಕझী बпೞѱ ઓೠ UserService.shared.fetchUser()
1.1 ੋఠಕझী बпೞѱ ઓೠ UserService.fetchUser()
1.1 ੋఠಕझী बпೞѱ ઓೠ ࢤࢿ۽ ఋੑਸ ׳߉ח UserService.fetchUser()
1.1 ੋఠಕझী बпೞѱ ઓೠ ࢤࢿ۽ ఋੑਸ ׳߉ח UserService.fetchUser() init(userServiceType:
UserService.Type)
1.1 ੋఠಕझী बпೞѱ ઓೠ ࢤࢿ۽ ఋੑਸ ׳߉ח UserService.fetchUser() init(userServiceType:
UserService.Type) self.userServiceType.fetchUser()
2. ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC()
2. ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC() ࢤࢿ۽ ಂషܻܳ
׳߉ח
2. ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC() ࢤࢿ۽ ಂషܻܳ
׳߉ח init(detailVCFactory: () -> DetailVC)
2. ੋझఢझܳ ࢤࢿೠ let detailVC = DetailVC() ࢤࢿ۽ ಂషܻܳ
׳߉ח init(detailVCFactory: () -> DetailVC) let detailVC = self.detailVCFactory()
ࠂೠ ۽о դޖೞ ঋਸөਃ??
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ যب ৻ࠗীࢲ ੑೡ
ࣻ ѱ غ
അप ݾ যઁࠁ ؊ ա ٘ܳ ࢿೠ যب ৻ࠗীࢲ ੑೡ
ࣻ ѱ غ ࠂ೧ݶ Factory ఋੑਸ ೞ
ف ೧Ѿ ߑߨ ҕా
ف ೧Ѿ ߑߨ ҕా ઓࢿ ৻ࠗী ਤೠ. init(userService: UserService) init(detailVCFactory:
() -> DetailVC)
ف ೧Ѿ ߑߨ ҕా ઓࢿ ৻ࠗী ਤೠ. ਃী ٮۄ ਗೞח
ѐܳ ੑೡ ࣻ . ListVC(detailVCFactory: { DetailVCMock() }) UserVC(userService: UserServiceMock())
ઁ ઓࢿ Ӓېী ࣘೞѱ ٜ݅
ઁ ઓࢿ Ӓېী ࣘೞѱ ٜ݅ Rootীࢲ оө ࣽࢲ۽
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module য়ט
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+1
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+2
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module ղੌ+3
window.rootViewController = ListVC( ) য়ט
window.rootViewController = ListVC( userService: UserService( ) ) ղੌ
window.rootViewController = ListVC( userService: UserService( networking: networking ) ) ղੌ+1
window.rootViewController = ListVC( userService: UserService( networking: networking ), detailVCFactory: {
DetailVC( ) } ) ղੌ+2
window.rootViewController = ListVC( userService: UserService( networking: networking ), detailVCFactory: {
DetailVC( repoService: RepoService( ) ) } ) ղੌ+3
window.rootViewController = ListVC( userService: UserService( networking: networking ), detailVCFactory: {
DetailVC( repoService: RepoService( networking: networking ) ) } ) ղੌ+4
AppDelegate UIWindow ListVC DetailVC UserService RepoService Networking Module Module
పझ ജ҃ীࢲ AppDelegateо प೯ظਃ DetailVCী ۄఠܳ ֈӝҊ रযਃ ಂషܻ ۽о
ցޖ ࠂ೧ઉਃ
Pure https://github.com/devxoul/Pure