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
76
Hello, ReactorKit 👋
devxoul
0
90
Build Funnels with Google BigQuery
devxoul
0
44
RxSwift 시작하기
devxoul
1
360
ReactorKit으로 단방향 반응형 앱 만들기
devxoul
0
170
Swift - 혼자 공부하면 분명히 안할테니까 같이 공부하기
devxoul
10
3.2k
좋은 디자이너, 나쁜 프로젝트매니저, 이상한 개발자
devxoul
0
110
Other Decks in Programming
See All in Programming
CSC305 Lecture 09
javiergs
PRO
0
320
あなたとKaigi on Rails / Kaigi on Rails + You
shimoju
0
220
20251016_Rails News ~Rails 8.1の足音を聴く~
morimorihoge
3
870
Webサーバーサイド言語としてのRustについて
kouyuume
1
5k
Ktorで簡単AIアプリケーション
tsukakei
0
120
Introduce Hono CLI
yusukebe
6
3.2k
フロントエンド開発のためのブラウザ組み込みAI入門
masashi
7
3.6k
PHPに関数型の魂を宿す〜PHP 8.5 で実現する堅牢なコードとは〜 #phpcon_hiroshima / phpcon-hiroshima-2025
shogogg
1
350
AI 駆動開発におけるコミュニティと AWS CDK の価値
konokenj
5
290
釣り地図SNSにおける有料機能の実装
nokonoko1203
0
200
Introducing RemoteCompose: break your UI out of the app sandbox.
camaelon
2
100
Inside of Swift Export
giginet
PRO
1
180
Featured
See All Featured
Why You Should Never Use an ORM
jnunemaker
PRO
59
9.6k
Git: the NoSQL Database
bkeepers
PRO
431
66k
RailsConf 2023
tenderlove
30
1.3k
GraphQLの誤解/rethinking-graphql
sonatard
73
11k
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
How to Think Like a Performance Engineer
csswizardry
27
2.2k
Optimising Largest Contentful Paint
csswizardry
37
3.5k
BBQ
matthewcrist
89
9.9k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
A designer walks into a library…
pauljervisheath
209
24k
For a Future-Friendly Web
brad_frost
180
10k
Being A Developer After 40
akosma
91
590k
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