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
さようなら Date。 ようこそTemporal! 3年間先行利用して得られた知見の共有
8beeeaaat
3
1.5k
詳解!defer panic recover のしくみ / Understanding defer, panic, and recover
convto
0
250
Android 16 × Jetpack Composeで縦書きテキストエディタを作ろう / Vertical Text Editor with Compose on Android 16
cc4966
2
260
パッケージ設計の黒魔術/Kyoto.go#63
lufia
3
440
Testing Trophyは叫ばない
toms74209200
0
890
Laravel Boost 超入門
fire_arlo
3
220
AI時代のUIはどこへ行く?
yusukebe
18
9k
はじめてのMaterial3 Expressive
ym223
2
880
テストコードはもう書かない:JetBrains AI Assistantに委ねる非同期処理のテスト自動設計・生成
makun
0
420
Processing Gem ベースの、2D レトロゲームエンジンの開発
tokujiros
2
130
🔨 小さなビルドシステムを作る
momeemt
4
690
Ruby Parser progress report 2025
yui_knk
1
450
Featured
See All Featured
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
44
2.5k
Build The Right Thing And Hit Your Dates
maggiecrowley
37
2.9k
Thoughts on Productivity
jonyablonski
70
4.8k
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
15
1.7k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
31
2.5k
Into the Great Unknown - MozCon
thekraken
40
2k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
285
13k
A designer walks into a library…
pauljervisheath
207
24k
The Power of CSS Pseudo Elements
geoffreycrofte
77
6k
Building Better People: How to give real-time feedback that sticks.
wjessup
368
19k
Agile that works and the tools we love
rasmusluckow
330
21k
Context Engineering - Making Every Token Count
addyosmani
3
56
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