Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feat/#91] View의 인터페이스 분리 #95

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

mooyoung2309
Copy link
Member

@mooyoung2309 mooyoung2309 commented Jun 23, 2023

PR 요약

구조를 변경을 제안합니다.
(저의 의견 입니다.)

왜 이렇게 했냐면,
가장 큰 문제점은 View의 컴포넌트에서 나타난다고 생각해요.
다른 FeatureA에서 만든 AButton을 FeatureB에서 접근할 수 있는 구조 자체가 문제 입니다. 왜냐면 FeatureA에서만 쓰려고 만들었는데, B에서 접근이 가능합니다. View가 인터페이스에 들어가 있으면 FeatureA에서만 쓰이고 싶은 Cell들 또한 외부에서 접근이 가능해집니다.

이렇게 되면 DesignSystem에 PumpingButton을 넣는것과, FeatureA에 Interface에 PumpingButton을 넣고 FeatureB, C, D 에서 FeatureAInterface를 import하여 PumpingButton을 사용하는 것과 동일한 레벨이 됩니다. 왜냐면 Feature사이끼리 Interface는 자유롭게 접근 가능하기 때문에 이렇게 가능합니다. 그렇다면 FeatureShared를 만들어서 Pumping 버튼을 Interface에 넣고 공유하는 것도 가능해집니다.

중요한 점은 다른 Feature에서 공유될 View의 Interface의 범위를 어디까지 생각할 것이냐인데, 저는 다른 Feature에서 공유되는 것은 하나의 Screen 이라고 생각이 들었습니다. 그래서 Interface에 View를 넣는것이 좋다고 생각했는데, 이런 문제점을 생각하게 되었고,, 고민을 많이 해보고 pr 날립니다 ㅎㅎ

View의 Interface 변경사항

뷰는 이제 실제 구현부와 분리됩니다. 외부로부터 주입받은 Content를 띄워주지만 타입으로서 활용됩니다.

public struct WorkoutEndView<Content: View>: View {
    private let store: StoreOf<WorkoutEndStore>
    public var content: () -> Content
    
    public init(store: StoreOf<WorkoutEndStore>, @ViewBuilder content: @escaping () -> Content) {
        self.store = store
        self.content = content
    }
    
    public var body: some View {
        content()
    }
}

View의 Implement 변경사항

뷰의 실제 구현은 다른 struct에서 구현되고 이를 View의 Content에 주입합니다.

public struct WorkoutEndViewImpl: View {
    private let store: StoreOf<WorkoutEndStore>
    
    init(store: StoreOf<WorkoutEndStore>) {
        self.store = store
    }
    
    public var body: some View {
    ....
    }
}

extension WorkoutEndView<WorkoutEndViewImpl> {
    public init(store: StoreOf<WorkoutEndStore>) {
        self.init(store: store) {
            WorkoutEndViewImpl(store: store)
        }
    }
}

실제 init이 되는 부분의 예시

...
// navigation 부분
case .end: // 변경된 방식
    IfLetStore(self.store.scope(state: \.workoutEnd, action: { .workoutEnd($0) })) {
        WorkoutEndView<WorkoutEndViewImpl>(store: $0)
    }
case .record: // 기존 방식
    IfLetStore(self.store.scope(state: \.workoutRecord, action: { .workoutRecord($0) })) {_ in
        WorkoutRecordView(store: $0)
    }

📌 변경 사항

✅ PR check list

Linked Issue

close #91

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[feat] workout end 디테일 UI
1 participant