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

7주차 과제 #7

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

7주차 과제 #7

wants to merge 2 commits into from

Conversation

ThirFir
Copy link
Contributor

@ThirFir ThirFir commented Dec 17, 2024

Work Description ✏️

  • 로그인, 회원가입 화면을 MVI로 마이그레이션

To Reviewers 📢

아직 익숙하지가 않아서 어찌저찌 해놓긴 했는데, MVI가 맞는지도 모르겠고, 코드도 더 어려워진 거 같아요 ㅠㅠ
저는 아직까지는 MVVM이 훨씬 편한 거 같습니다...

MVI는 조금 더 공부를 해봐야겠어요...ㅎㅎ

@ThirFir ThirFir added the 과제 label Dec 17, 2024
@ThirFir ThirFir self-assigned this Dec 17, 2024
Copy link

@KkamSonLee KkamSonLee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다 !! MVI 패턴이라는게 불편할수도 있으면서 이점이 확실한 패턴이기도 해요 글에 적힌 이점들을 이해하는 것보다 직접 사용하면서 어떤 이점들이 있는지 체감하셔보시는 것을 추천드립니다! ㅎㅎ

Comment on lines +92 to +95
data class UpdateUsername(val username: String) : SignInIntent
data class UpdatePassword(val password: String) : SignInIntent
data object TrySignIn : SignInIntent
data object TryAutoSignIn : SignInIntent

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intent 의 이름은 View 에서 어떤 이벤트가 발생했는지에 대한 단순한 행동만을 나타내는게 좋은 것 같아요! 아래와 같이요! 행동에 대한 ViewModel 의 Action을 다르게 하는 느낌이면 좋을 것 같아요. "SignIn 버튼을 눌렀다" 정도만 알게 하고 나머지는 뷰모델에게 위임 한다는 느낌이에요!

  • OnUsernameInputChanged
  • OnPasswordInputChanged
  • OnSignInClick
  • OnAutoSignInClick

Comment on lines +65 to +67
if (errorResult != null) {
_effect.emit(SignInEffect.ShowSnackbar("Error"))
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UiState 필드 중에 결과를 들고 있는거라면 SignInResult 를 제거하고, SignInEffect.ShowSnackbar 라는 SideEffect에 보여줄 snackbarMessage를� 넘겨서 처리하는 방법도 좋을 것 같아요 ! 그리고 ShowSnackbar, ShowToast, ShowProgress (Hide 도 동일) 같은 이펙트들은(다 쓰라는건 아니에요) 공통 SideEffect 와 같은 Interface 에 선언해두고 그걸 상속해두고 쓰면 편할 것 같긴합니다! 다른 SideEffect에서도 비슷한 Effect가 생길 가능성이 커서요! :)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

만일 위 리뷰를 반영하기 위해서 getString 을 viewModel 에서 하기 위해서 혹시나 @ApplicationContext context : Context 를 주입받으려고 하신다면 해당 Context 를 주입 받은 ResourceProvider 같은 클래스에서 getString 같은 동작을 해주는 클래스를 주입 받아보면 좋습니다! Context 는 사용할 수 있는 게 많지만 잘못 사용하면 에러가 날 가능성이 높아서요! 뷰모델에서는 크게 쓰일 일이 많지 않기 때문에 분리해도 좋을 것 같숩니닷

}

sealed interface SignInEffect {
data class ShowSnackbar(val message: String) : SignInEffect

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • 요렇게 바꾸면 좋을 것 같아요 ㅎㅎ SignUp 도요!
Suggested change
data class ShowSnackbar(val message: String) : SignInEffect
data class ShowSnackBar(val message: String) : SignInEffect

Comment on lines +26 to +27
private val _effect = MutableSharedFlow<SignUpEffect>()
val effect = _effect.asSharedFlow()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기에선 _effect 에 set 하는 부분이 없는 것 같아요 SignUpScreen 에서는 올 것을 기대하고 있구요!

Copy link

@chrin05 chrin05 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MVI 어려운거 공감합니다..과제하느라 고생하셨어요!

Comment on lines +91 to +100
sealed interface SignUpResult {
data object Success : SignUpResult
data object UsernameInputEmpty : SignUpResult
data object PasswordInputEmpty : SignUpResult
data object HobbyInputEmpty : SignUpResult
data object InvalidUsername : SignUpResult
data object InvalidPassword : SignUpResult
data object InvalidHobby : SignUpResult
data object AlreadyExistUsername : SignUpResult
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 에러처리를 위해 요렇게 작성하셨군요!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

결과를 이런식으로 따로 뺄 수도 있군요.

Comment on lines +92 to +94
usernameInput = uiState.username,
passwordInput = uiState.password,
hobbyInput = uiState.hobby,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

인자를 각각 넘겨주셨군요, 만약에 관리하게 되는 값이 많아진다면 코드가 너무 길어질 거 같아서 저는 uiState 자체를 넘겼는데 이부분에 대해서 고민을 한 번 해봐야할 거 같네요. 변수를 각각 넘겨준 이유가 따로 있는지 궁금합니다!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uiState 자체를 넘겨주면 컴포넌트가 실제로 사용하지 않는 상태에도 접근 가능 해지기 때문에,
필요한 상태만 개별적으로 전달해준다면 리컴포지션을 방지할 수 있어서 이렇게 해주신 것이 맞을까요!?

Copy link

@0se0 0se0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7주차까지 너무 수고많으셨습니다~ 행복 앱잼 하세요!!

Comment on lines +92 to +94
usernameInput = uiState.username,
passwordInput = uiState.password,
hobbyInput = uiState.hobby,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

uiState 자체를 넘겨주면 컴포넌트가 실제로 사용하지 않는 상태에도 접근 가능 해지기 때문에,
필요한 상태만 개별적으로 전달해준다면 리컴포지션을 방지할 수 있어서 이렇게 해주신 것이 맞을까요!?

Comment on lines +91 to +95
sealed interface SignInIntent {
data class UpdateUsername(val username: String) : SignInIntent
data class UpdatePassword(val password: String) : SignInIntent
data object TrySignIn : SignInIntent
data object TryAutoSignIn : SignInIntent
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

여기 부분들 따로 파일 분리를 해주시지 않은 이유가 따로 있을까요?

Copy link
Member

@Roel4990 Roel4990 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

7주차까지 수고 많으셨습니다! 앱잼 화이팅!!

Comment on lines +91 to +100
sealed interface SignUpResult {
data object Success : SignUpResult
data object UsernameInputEmpty : SignUpResult
data object PasswordInputEmpty : SignUpResult
data object HobbyInputEmpty : SignUpResult
data object InvalidUsername : SignUpResult
data object InvalidPassword : SignUpResult
data object InvalidHobby : SignUpResult
data object AlreadyExistUsername : SignUpResult
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

결과를 이런식으로 따로 뺄 수도 있군요.

Comment on lines +84 to +89
data class SignInUiState(
val username: String = "",
val password: String = "",
val isLoading: Boolean = false,
val signInResult: SignInResult? = null
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

State, Event, Effect, Intent, ..은 따로 예를 들어 SignInContract.kt 파일을 만들어서 따로 빼서 관리하는건 어떨까요?!


sealed interface SignUpEffect {
data class ShowSnackbar(val message: String) : SignUpEffect
data object Success : SignUpEffect
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SignUpEffect 랑 SignUpResult 안에 둘다 Success 가 있는데 이름을 다르게 지정하는게 어떨까요? 처음 보는 사람을 헷갈릴 수도 있을 것 같아요!

Copy link
Contributor

@jihyunniiii jihyunniiii left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

고생하셨습니다 ~

Comment on lines +88 to +99
onSignInButtonClicked = {
viewModel.handleIntent(SignInIntent.TrySignIn)
},
onNavigateToSignUp = onNavigateToSignUp,
usernameInput = usernameInput,
passwordInput = passwordInput,
onUsernameInputChanged = viewModel::onUsernameInputChanged,
onPasswordInputChanged = viewModel::onPasswordInputChanged
usernameInput = uiState.username,
passwordInput = uiState.password,
onUsernameInputChanged = {
viewModel.handleIntent(SignInIntent.UpdateUsername(it))
},
onPasswordInputChanged = {
viewModel.handleIntent(SignInIntent.UpdatePassword(it))
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

handleIntent 함수 자체만 넘길 수도 있어요! (세영이 PR처럼!) 알고 계시면 좋을 것 같습니다.

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.

6 participants