-
Notifications
You must be signed in to change notification settings - Fork 0
UML
작성 중...
@startuml
' STYLE START
hide empty members
skinparam shadowing false
' STYLE END
class "NetworkService" as NetworkService << (P, GoldenRod) protocol >> {
~request(with:)
~request(with:)
}
class "DefaultNetworkService" as DefaultNetworkService << (C, DarkSeaGreen) >> {
~networkRequester : NetworkRequesting
~init(requester:)
~request(with:)
~request(with:)
}
class "NetworkRequesting" as NetworkRequesting << (P, GoldenRod) protocol >> {
~get(url:session:)
~getWithoutDecode(url:session:)
}
class "DefaultNetworkRequester" as DefaultNetworkRequester << (C, DarkSeaGreen) >> {
~get(url:session:)
~getWithoutDecode(url:session:)
}
class "EndPoint" as EndPoint << (S, SkyBlue) struct >> {
~scheme : String
~host : String
~path : String
~method : HTTPMethod
~init(scheme:host:apiPath:httpMethod:)
~asURL()
}
class "AppFlowCoordinator" as AppFlowCoordinator << (C, DarkSeaGreen) >> {
~navigationController : UINavigationController
-appDIContainer : AppDIContainer
~init(navigationController:appDIContainer:)
~start()
}
class "AppDIContainer" as AppDIContainer << (C, DarkSeaGreen) >> {
-apiNetworkService
-toaster
-imageCacher
~makeSceneDIContainer()
}
class "SceneDIContainer" as SceneDIContainer << (C, DarkSeaGreen) >> {
-dependencies : Dependencies
~init(dependencies:)
~makeBanChanRepository()
~makeFoodImagesRepository()
~makeMainFoodViewFlowCoordinator(navigationController:)
~makeMainFoodUseCase()
~makeMainFoodViewModel(action:)
~makeMainFoodViewController(actions:)
~makeDetailFoodUseCase(detailHash:)
~makeDetailFoodViewModel(action:prepare:)
~makeDetailFoodViewController(actions:prepare:)
}
class "AppDelegate" as AppDelegate << (C, DarkSeaGreen) >> {
~application(_:didFinishLaunchingWithOptions:)
}
class "SceneDelegate" as SceneDelegate << (C, DarkSeaGreen) >> {
~window : UIWindow?
~appDiContainer
~appFlowCoordinator : AppFlowCoordinator?
~scene(_:willConnectTo:options:)
}
class "DefaultBanChanRepository" as DefaultBanChanRepository << (C, DarkSeaGreen) >> {
~networkService : NetworkService
~init(networkService:)
~fetchBestSection()
~fetchIndividualSection(api:)
~fetchFoodDetail(hashId:)
}
class "DefaultFoodImagesRepository" as DefaultFoodImagesRepository << (C, DarkSeaGreen) >> {
~networkService : NetworkService
~imageCacher : ImageCacher
~init(networkService:imageCacher:)
~fetchFoodImage(with:)
-setCache(data:id:)
-getCache(id:)
}
class "APIEndPoint" as APIEndPoint << (S, SkyBlue) struct >> {
~{static} getSectionsEndPoint(api:)
~{static} getFoodDetailEndPoint(hash:)
}
class "ImageCacher" as ImageCacher << (C, DarkSeaGreen) >> {
~{static} shared
-init()
~container
}
class "DetailPreparation" as DetailPreparation << (S, SkyBlue) struct >> {
~productName : String
~hashId : String
~badge : [String]?
}
class "DetailFoodUseCase" as DetailFoodUseCase << (P, GoldenRod) protocol >> {
~fetchDetail()
~fetchFoodImage(imageString:)
~mockOrder(orderCount:)
}
class "DefaultDetailFoodUseCase" as DefaultDetailFoodUseCase << (C, DarkSeaGreen) >> {
-banchanRepository : BanChanRepository
-foodImageRepository : FoodImagesRepository
-detailHash : String
~init(banchanRepository:foodImageRepository:detailHash:)
~fetchDetail()
~fetchFoodImage(imageString:)
~mockOrder(orderCount:)
}
class "MainFoodUseCase" as MainFoodUseCase << (P, GoldenRod) protocol >> {
~fetchBestSections()
~fetchIndividualSection(api:)
~fetchFoodImage(imageString:)
}
class "DefaultMainFoodUseCase" as DefaultMainFoodUseCase << (C, DarkSeaGreen) >> {
-banchanRepository : BanChanRepository
-foodImageRepository : FoodImagesRepository
~init(banchanRepository:foodImageRepository:)
~fetchBestSections()
~fetchFoodImage(imageString:)
~fetchIndividualSection(api:)
}
class "BanChanRepository" as BanChanRepository << (P, GoldenRod) protocol >> {
~fetchBestSection()
~fetchIndividualSection(api:)
~fetchFoodDetail(hashId:)
}
class "Repository" as Repository << (P, GoldenRod) protocol >> {
~networkService : NetworkService
}
class "FoodImagesRepository" as FoodImagesRepository << (P, GoldenRod) protocol >> {
~fetchFoodImage(with:)
}
class "Cacher" as Cacher << (P, GoldenRod) protocol >> {
~container : NSCache<NSString, T>
~setCache(with:id:)
~getCache(id:)
}
class "MainFoodViewFlowCoordinatorDependencies" as MainFoodViewFlowCoordinatorDependencies << (P, GoldenRod) protocol >> {
~makeMainFoodViewController(actions:)
~makeDetailFoodViewController(actions:prepare:)
}
class "MainFoodViewFlowCoordinator" as MainFoodViewFlowCoordinator << (C, DarkSeaGreen) >> {
-navigationController : UINavigationController?
-dependencies : MainFoodViewFlowCoordinatorDependencies
-toaster : Toaster
~init(navigationController:dependencies:toaster:)
~start()
-pushFoodDetailView(prepare:)
-presentAlert(bool:)
-showToast(text:)
}
class "DetailFoodViewModelActions" as DetailFoodViewModelActions << (S, SkyBlue) struct >> {
~presentAlert : (Bool) -> Void
}
class "DetailFoodViewModelInput" as DetailFoodViewModelInput << (P, GoldenRod) protocol >> {
~touchOrderButton()
}
class "DetailFoodViewModelOutput" as DetailFoodViewModelOutput << (P, GoldenRod) protocol >> {
~productName : Observable<String>
~eventBadge : Observable<[String]>
~detailDescImage : Observable<Data>
~thumbnailImage : Observable<Data>
~itemCountToPurchase : BehaviorSubject<Int>
~totalPriceToDisplay : BehaviorSubject<String>
~productDescription : Observable<String>
~foodPrices : Observable<[String]>
~deliveryFee : Observable<String>
~deliveryInfo : Observable<String>
~pointToEarn : Observable<String>
}
class "DetailFoodViewModel" as DetailFoodViewModel << (P, GoldenRod) protocol >> {
}
class "DefaultDetailFoodViewModel" as DefaultDetailFoodViewModel << (C, DarkSeaGreen) >> {
-disposeBag
-detailFoodUseCase : DetailFoodUseCase
-actions : DetailFoodViewModelActions?
-itemPrice : Int
-loadedData : BehaviorSubject<FoodDetail>
~productName : Observable<String>
~eventBadge : Observable<[String]>
~detailDescImage : Observable<Data>
~thumbnailImage : Observable<Data>
~productDescription : Observable<String>
~foodPrices : Observable<[String]>
~deliveryFee : Observable<String>
~deliveryInfo : Observable<String>
~pointToEarn : Observable<String>
~itemCountToPurchase : BehaviorSubject<Int>
~totalPriceToDisplay : BehaviorSubject<String>
~init(detailFoodUseCase:actions:prepare:)
-loadData()
-totalPriceBind()
}
class "DefaultDetailFoodViewModel" as DefaultDetailFoodViewModel12 << (X, Orchid) extension >> {
touchOrderButton()
}
class "DetailFoodViewController" as DetailFoodViewController << (C, DarkSeaGreen) >> {
~imagePagingScrollView : UIScrollView!
~imagePageController : UIPageControl!
~productNameLabel : UILabel!
~productDescriptionLabel : UILabel!
~productPrice : UILabel!
~eventBadgeStackView : UIStackView!
~deliveryFeeLabel : UILabel!
~deliveryInfoLabel : UILabel!
~pointLabel : UILabel!
~foodDescImageStackView : UIStackView!
~quantityStepper : UIStepper!
~quantityCountLabel : UILabel!
~totalPriceLabel : UILabel!
~orderButton : UIButton!
-disposeBag
-viewModel : DetailFoodViewModel!
~viewDidLoad()
~{static} create(with:)
~bind()
-addContentScrollView(image:)
}
class "MainFoodViewModelActions" as MainFoodViewModelActions << (S, SkyBlue) struct >> {
~pushFoodDetailView : (DetailPreparation) -> Void
~showToast : (String) -> Void
}
class "MainFoodViewModelInput" as MainFoodViewModelInput << (P, GoldenRod) protocol >> {
~didSelect(item:)
~sectionTouched(sectionName:sectionItemCount:)
}
class "MainFoodViewModelOutput" as MainFoodViewModelOutput << (P, GoldenRod) protocol >> {
~sceneTitle : String
~mainSectionRelay : BehaviorRelay<[MainSection]>
~dataSource : RxTableViewSectionedAnimatedDataSource<MainSection>
~sectionData : [MainSection]
}
class "MainFoodViewModel" as MainFoodViewModel << (P, GoldenRod) protocol >> {
}
class "DefaultMainFoodViewModel" as DefaultMainFoodViewModel << (C, DarkSeaGreen) >> {
-disposeBag
-mainFoodUseCase : MainFoodUseCase
-actions : MainFoodViewModelActions?
~mainSectionRelay : BehaviorRelay<[MainSection]>
~sceneTitle : String
~dataSource : RxTableViewSectionedAnimatedDataSource<MainSection>
~sectionData : [MainSection]
~init(mainFoodUseCase:actions:)
-loadData()
}
class "DefaultMainFoodViewModel" as DefaultMainFoodViewModel13 << (X, Orchid) extension >> {
didSelect(item:)
sectionTouched(sectionName:sectionItemCount:)
}
class "FoodListItemCell" as FoodListItemCell << (C, DarkSeaGreen) >> {
~foodImageView : UIImageView!
~foodTitleLabel : UILabel!
~foodDescriptionLabel : UILabel!
~foodPriceLabel : UILabel!
~eventBadgeStackView : UIStackView!
~disposeBag
~detailHashId
~awakeFromNib()
~prepareForReuse()
~bind(with:data:)
}
class "FoodListHeader" as FoodListHeader << (C, DarkSeaGreen) >> {
~sectionTitleButton : UIButton!
~init(reuseIdentifier:)
~init(coder:)
~awakeFromNib()
~setTitle(text:)
}
class "MainFoodViewController" as MainFoodViewController << (C, DarkSeaGreen) >> {
~mainFoodTableView : UITableView!
~disposeBag
-viewModel : MainFoodViewModel!
~viewDidLoad()
~{static} create(with:)
-setupView()
-bind()
-setTableViewCell()
}
class "StoryboardInitiating" as StoryboardInitiating << (P, GoldenRod) protocol >> {
~{static} defaultFileName : String
~{static} instantiateViewController(_:)
}
class "Toaster" as Toaster << (C, DarkSeaGreen) >> {
~showUpWith(text:to:)
}
MainFoodViewFlowCoordinator <-up DetailFoodViewController: present
MainFoodViewFlowCoordinator <-up MainFoodViewController: present
StoryboardInitiating <|--down DetailFoodViewController : inherits
StoryboardInitiating <|--down MainFoodViewController : inherits
NetworkService <|.. DefaultNetworkService : confirms to
NetworkRequesting <|.. DefaultNetworkRequester : confirms to
URLConvertible <|-- EndPoint : inherits
MainFoodViewFlowCoordinatorDependencies <|-- SceneDIContainer : inherits
BanChanRepository <|-- DefaultBanChanRepository : inherits
FoodImagesRepository <|-- DefaultFoodImagesRepository : inherits
Cacher <|-- ImageCacher : inherits
DetailFoodUseCase <|.. DefaultDetailFoodUseCase : confirms to
MainFoodUseCase <|.. DefaultMainFoodUseCase : confirms to
Repository <|.. BanChanRepository : inherits
Repository <|.. FoodImagesRepository : confirms to
DetailFoodViewModelInput <|.. DetailFoodViewModel : confirms to
DetailFoodViewModelOutput <|.. DetailFoodViewModel : confirms to
DetailFoodViewModel <|.. DefaultDetailFoodViewModel : confirms to
MainFoodViewModelInput <|.. MainFoodViewModel : confirms to
MainFoodViewModelOutput <|.. MainFoodViewModel : confirms to
MainFoodViewModel <|.. DefaultMainFoodViewModel : confirms to
DefaultDetailFoodViewModel <.. DefaultDetailFoodViewModel12 : ext
DefaultMainFoodViewModel <.. DefaultMainFoodViewModel13 : ext
@enduml
class "MainFoodViewController" as MainFoodViewController << (C, DarkSeaGreen) >> { ~mainFoodTableView : UITableView! ~disposeBag -viewModel : MainFoodViewModel! ~viewDidLoad() ~{static} create(with:) -setupView() -bind() -setTableViewCell() } class "StoryboardInitiating" as StoryboardInitiating << (P, GoldenRod) protocol >> { ~{static} defaultFileName : String ~{static} instantiateViewController(_:) } class "DetailFoodViewController" as DetailFoodViewController << (C, DarkSeaGreen) >> { ~imagePagingScrollView : UIScrollView! ~imagePageController : UIPageControl! ~productNameLabel : UILabel! ~productDescriptionLabel : UILabel! ~productPrice : UILabel! ~eventBadgeStackView : UIStackView! ~deliveryFeeLabel : UILabel! ~deliveryInfoLabel : UILabel! ~pointLabel : UILabel! ~foodDescImageStackView : UIStackView! ~quantityStepper : UIStepper! ~quantityCountLabel : UILabel! ~totalPriceLabel : UILabel! ~orderButton : UIButton! -disposeBag -viewModel : DetailFoodViewModel! ~viewDidLoad() ~{static} create(with:) ~bind() -addContentScrollView(image:) } class "MainFoodViewFlowCoordinator" as MainFoodViewFlowCoordinator << (C, DarkSeaGreen) >> { -navigationController : UINavigationController? -dependencies : MainFoodViewFlowCoordinatorDependencies -toaster : Toaster ~init(navigationController:dependencies:toaster:) ~start() -pushFoodDetailView(prepare:) -presentAlert(bool:) -showToast(text:) }
DetailFoodViewController <-down MainFoodViewFlowCoordinator : present MainFoodViewController <-down MainFoodViewFlowCoordinator : present StoryboardInitiating <|--down DetailFoodViewController : inherits StoryboardInitiating <|--down MainFoodViewController : inherits
class "DefaultBanChanRepository" as DefaultBanChanRepository << (C, DarkSeaGreen) >> { ~networkService : NetworkService ~init(networkService:) ~fetchBestSection() ~fetchIndividualSection(api:) ~fetchFoodDetail(hashId:) } class "DefaultFoodImagesRepository" as DefaultFoodImagesRepository << (C, DarkSeaGreen) >> { ~networkService : NetworkService ~imageCacher : ImageCacher ~init(networkService:imageCacher:) ~fetchFoodImage(with:) -setCache(data:id:) -getCache(id:) } class "BanChanRepository" as BanChanRepository << (P, GoldenRod) protocol >> { ~fetchBestSection() ~fetchIndividualSection(api:) ~fetchFoodDetail(hashId:) } class "Repository" as Repository << (P, GoldenRod) protocol >> { ~networkService : NetworkService } class "FoodImagesRepository" as FoodImagesRepository << (P, GoldenRod) protocol >> { ~fetchFoodImage(with:) }
FoodImagesRepository <|-- DefaultFoodImagesRepository : inherits BanChanRepository <|-- DefaultBanChanRepository : inherits Repository <|.. BanChanRepository : inherits Repository <|.. FoodImagesRepository : confirms to
class "NetworkService" as NetworkService << (P, GoldenRod) protocol >> { ~request(with:) ~request(with:) } class "DefaultNetworkService" as DefaultNetworkService << (C, DarkSeaGreen) >> { ~networkRequester : NetworkRequesting ~init(requester:) ~request(with:) ~request(with:) } class "NetworkRequesting" as NetworkRequesting << (P, GoldenRod) protocol >> { ~get(url:session:) ~getWithoutDecode(url:session:) } class "DefaultNetworkRequester" as DefaultNetworkRequester << (C, DarkSeaGreen) >> { ~get(url:session:) ~getWithoutDecode(url:session:) } class "EndPoint" as EndPoint << (S, SkyBlue) struct >> { ~scheme : String ~host : String ~path : String ~method : HTTPMethod ~init(scheme:host:apiPath:httpMethod:) ~asURL() }
class "APIEndPoint" as APIEndPoint << (S, SkyBlue) struct >> { ~{static} getSectionsEndPoint(api:) ~{static} getFoodDetailEndPoint(hash:) }
EndPoint <-down APIEndPoint : dependency
AppDIContainer <-down DefaultNetworkService : assiciation DefaultNetworkService <-down DefaultNetworkRequester : association DefaultNetworkService <-down EndPoint: dependency
NetworkService <|.. DefaultNetworkService : confirms to NetworkRequesting <|.. DefaultNetworkRequester : confirms to
class "DetailFoodUseCase" as DetailFoodUseCase << (P, GoldenRod) protocol >> {
~fetchDetail()
~fetchFoodImage(imageString:)
~mockOrder(orderCount:)
}
class "DefaultDetailFoodUseCase" as DefaultDetailFoodUseCase << (C, DarkSeaGreen) >> {
-banchanRepository : BanChanRepository
-foodImageRepository : FoodImagesRepository
-detailHash : String
~init(banchanRepository:foodImageRepository:detailHash:)
~fetchDetail()
~fetchFoodImage(imageString:)
~mockOrder(orderCount:)
}
class "MainFoodUseCase" as MainFoodUseCase << (P, GoldenRod) protocol >> {
~fetchBestSections()
~fetchIndividualSection(api:)
~fetchFoodImage(imageString:)
}
class "DefaultMainFoodUseCase" as DefaultMainFoodUseCase << (C, DarkSeaGreen) >> {
-banchanRepository : BanChanRepository
-foodImageRepository : FoodImagesRepository
~init(banchanRepository:foodImageRepository:)
~fetchBestSections()
~fetchFoodImage(imageString:)
~fetchIndividualSection(api:)
}
class "DetailFoodViewModelActions" as DetailFoodViewModelActions << (S, SkyBlue) struct >> {
~presentAlert : (Bool) -> Void
}
class "DetailFoodViewModelInput" as DetailFoodViewModelInput << (P, GoldenRod) protocol >> {
~touchOrderButton()
}
class "DetailFoodViewModelOutput" as DetailFoodViewModelOutput << (P, GoldenRod) protocol >> {
~productName : Observable
~eventBadge : Observable<[String]>
~detailDescImage : Observable
~thumbnailImage : Observable
~itemCountToPurchase : BehaviorSubject
~totalPriceToDisplay : BehaviorSubject
~productDescription : Observable
~foodPrices : Observable<[String]>
~deliveryFee : Observable
~deliveryInfo : Observable
~pointToEarn : Observable
}
class "DetailFoodViewModel" as DetailFoodViewModel << (P, GoldenRod) protocol >> {
}
class "DefaultDetailFoodViewModel" as DefaultDetailFoodViewModel << (C, DarkSeaGreen) >> {
-disposeBag
-detailFoodUseCase : DetailFoodUseCase
-actions : DetailFoodViewModelActions?
-itemPrice : Int
-loadedData : BehaviorSubject
~productName : Observable
~eventBadge : Observable<[String]>
~detailDescImage : Observable
~thumbnailImage : Observable
~productDescription : Observable
~foodPrices : Observable<[String]>
~deliveryFee : Observable
~deliveryInfo : Observable
~pointToEarn : Observable
~itemCountToPurchase : BehaviorSubject
~totalPriceToDisplay : BehaviorSubject
~init(detailFoodUseCase:actions:prepare:)
-loadData()
-totalPriceBind()
}
class "MainFoodViewModelActions" as MainFoodViewModelActions << (S, SkyBlue) struct >> {
~pushFoodDetailView : (DetailPreparation) -> Void
~showToast : (String) -> Void
}
class "MainFoodViewModelInput" as MainFoodViewModelInput << (P, GoldenRod) protocol >> {
~didSelect(item:)
~sectionTouched(sectionName:sectionItemCount:)
}
class "MainFoodViewModelOutput" as MainFoodViewModelOutput << (P, GoldenRod) protocol >> {
~sceneTitle : String
~mainSectionRelay : BehaviorRelay<[MainSection]>
~dataSource : RxTableViewSectionedAnimatedDataSource
~sectionData : [MainSection]
}
class "MainFoodViewModel" as MainFoodViewModel << (P, GoldenRod) protocol >> {
}
class "DefaultMainFoodViewModel" as DefaultMainFoodViewModel << (C, DarkSeaGreen) >> {
-disposeBag
-mainFoodUseCase : MainFoodUseCase
-actions : MainFoodViewModelActions?
~mainSectionRelay : BehaviorRelay<[MainSection]>
~sceneTitle : String
~dataSource : RxTableViewSectionedAnimatedDataSource
~sectionData : [MainSection]
~init(mainFoodUseCase:actions:)
-loadData()
}
DetailFoodUseCase <|.. DefaultDetailFoodUseCase : confirms to MainFoodUseCase <|.. DefaultMainFoodUseCase : confirms to
DetailFoodViewModelInput <|.. DetailFoodViewModel : confirms to DetailFoodViewModelOutput <|.. DetailFoodViewModel : confirms to DetailFoodViewModel <|.. DefaultDetailFoodViewModel : confirms to DefaultDetailFoodViewModel <- DefaultDetailFoodUseCase : association
MainFoodViewModelInput <|.. MainFoodViewModel : confirms to MainFoodViewModelOutput <|.. MainFoodViewModel : confirms to MainFoodViewModel <|.. DefaultMainFoodViewModel : confirms to DefaultMainFoodViewModel <- DefaultMainFoodUseCase : association
class "AppFlowCoordinator" as AppFlowCoordinator << (C, DarkSeaGreen) >> { ~navigationController : UINavigationController -appDIContainer : AppDIContainer ~init(navigationController:appDIContainer:) ~start() } class "AppDIContainer" as AppDIContainer << (C, DarkSeaGreen) >> { -apiNetworkService -toaster -imageCacher ~makeSceneDIContainer() } class "SceneDIContainer" as SceneDIContainer << (C, DarkSeaGreen) >> { -dependencies : Dependencies ~init(dependencies:) ~makeBanChanRepository() ~makeFoodImagesRepository() ~makeMainFoodViewFlowCoordinator(navigationController:) ~makeMainFoodUseCase() ~makeMainFoodViewModel(action:) ~makeMainFoodViewController(actions:) ~makeDetailFoodUseCase(detailHash:) ~makeDetailFoodViewModel(action:prepare:) ~makeDetailFoodViewController(actions:prepare:) } class "SceneDelegate" as SceneDelegate << (C, DarkSeaGreen) >> { ~window : UIWindow? ~appDiContainer ~appFlowCoordinator : AppFlowCoordinator? ~scene(_:willConnectTo:options:) } class "ImageCacher" as ImageCacher << (C, DarkSeaGreen) >> { ~{static} shared -init() ~container } class "Cacher" as Cacher << (P, GoldenRod) protocol >> { ~container : NSCache<NSString, T> ~setCache(with:id:) ~getCache(id:) } class "MainFoodViewFlowCoordinatorDependencies" as MainFoodViewFlowCoordinatorDependencies << (P, GoldenRod) protocol >> { ~makeMainFoodViewController(actions:) ~makeDetailFoodViewController(actions:prepare:) }
class "Toaster" as Toaster << (C, DarkSeaGreen) >> { ~showUpWith(text:to:) }
SceneDelegate <-down AppDIContainer : association SceneDelegate <-down AppFlowCoordinator : association
AppDIContainer <-down SceneDIContainer: dependency
AppDIContainer <-down Toaster : assiciation AppDIContainer <-down ImageCacher : assiciation
MainFoodViewFlowCoordinatorDependencies <|-- SceneDIContainer : inherits
Cacher <|-- ImageCacher : inherits