-
Notifications
You must be signed in to change notification settings - Fork 0
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
Week7 필수과제 구현 #12
base: develop
Are you sure you want to change the base?
Week7 필수과제 구현 #12
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
State와 Effect 사용을 잘 하신것 같아요! 고생하셨습니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
뭔가 가독성 측면에서, baseViewModel 과 interface, Util 파일을 분리해도 좋을 것 같아요!
private fun validateUserName(username: String) = | ||
username.isNotBlank() && username.length <= 8 | ||
|
||
private fun validatePassword(password: String) = | ||
password.isNotBlank() && password.length <= 8 | ||
|
||
private fun validateHobby(hobby: String) = | ||
hobby.isNotBlank() && hobby.length <= 8 | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 부분은 서버에서 검증해주고 있어 필요 없을거 같네요!
data object NavigateToSignIn : SignUpUiEffect() | ||
data object NavigateUp : SignUpUiEffect() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
오 저는 navigate이동과 popup을 동시에 사용했는데, 분리할 수도 있군요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저번에 코리 남겨달라 하셨어서 한번 놀러왔어요~
제가 일정이 있어서 전부 다 읽지는 못하고 위에 절반 정도밖에 못읽었어요.
그런데 잘하시네여 ㅎㅎ 잘 보고갑니당
질문하고 싶으신 코멘트가 있다면 멘션하고 답글 달아주셔도 좋고 따로 연락주셔도 좋습니다 :)
앱잼 화이팅입니다~ 🚀
@Provides | ||
@Singleton | ||
fun provideUserRegisterRepository(userService: UserService): SignUpRepository { | ||
return SignUpRepositoryImpl(userService) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 코드만 말하는게 아니라 아래있는 다른 모듈들도 공통되는 사항이니 한번 확인 부탁해요!
Pair(400, "01") to "잘못된 요청입니다.", | ||
Pair(400, "01") to "아이디, 비밀번호, 취미를 올바르게 입력해주세요.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
사소한 실수~
key 두개가 똑같아용
fun UserData.toUserLoginRequestDto(): SignInRequestDto = SignInRequestDto( | ||
username = this.username, | ||
password = this.password | ||
) | ||
|
||
fun UserData.toRegisterRequestDto(): SignUpRequestDto { | ||
return SignUpRequestDto( | ||
username = this.username, | ||
password = this.password, | ||
hobby = this.hobby | ||
) | ||
} | ||
|
||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
두가지 방법이 혼용되어있는 것 같아요.
Mapper를 object로 사용하실거라면 내부에는 단순 function을 넣는게 일반적이고, 확장함수처럼 사용하신다면 굳이 Mapper로 감싸지 않아도 된답니다
val result: MyHobbyResponseResultDto? = null, | ||
val code: String? = null |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
serialName이 없어도 현재는 정상 작동될거에요
그런데 프로덕션으로 출시를 하고, 난독화 과정을 거친다면 result
라는 변수는 a
와 같이 변환되어요. 그렇기 때문에 난독화 한다면 서버통신 과정에서 오류가 발생할 수 있습니다
그렇기에 serialName을 붙여주는게 좋은 습관입니당
) : MyHobbyRepository { | ||
override suspend fun getMyHobby(): Result<MyHobbyEntity> = | ||
runCatching { | ||
getMyHobbyDataSource.getMyHobby().result?.let { Mapper.toMyHobbyEntity(it) }!! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
저는 !! 연산자를 상당히 싫어하는 편이에요.
물론 현재는 runCatching으로 감싸두었기 때문에 여기서 오류가 난다고 해도 Result가 fail로 전달되어 앱은 안전할거에요.
하지만 오류를 확인하는 곳에서는 NPE로 오류가 나올것이기 때문에 오류를 찾기 힘들어질 수도 있어요. 그렇기에 null이 오류라면 throw를 활용해 명시적으로 알려주거나 null이 정상이라면 그것 자체를 반환하는 것도 방법이 될 수 있을 것 같아요
class MyHobbyUseCase( | ||
private val getMyHobbyRepository: MyHobbyRepository |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이부분도 Inject로 받아온다면 더욱 편해질거에요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
어 뭐야 SignInUseCase에선 쓰셨네요?
val mainContents: List<HomeContent> = emptyList(), | ||
|
||
val commonContents: List<HomeCommonContent> = emptyList(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
List는 불변객체가 아닌 읽기전용이에요. 그렇기에 리컴포지션의 대상이 돼요.
@stable, @immutable 어노테이션을 활용하거나 ImmutableLIst
를 활용하신다면 리컴포지션을 줄일 수 있을거에요
LazyColumn( | ||
modifier = modifier, verticalArrangement = Arrangement.spacedBy(16.dp) | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이렇게 활용하신다면 LazyColumn을 사용하는 의미가 없는 것 같아요.
Column에 ScrollState를 적용하는건 어떨까요??
HorizontalPager( | ||
state = pagerState, | ||
contentPadding = PaddingValues(horizontal = 10.dp), | ||
pageSpacing = 10.dp | ||
) { page -> | ||
HomeBannerPage( | ||
index = page, | ||
banners = banners | ||
) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pager, Lazy~ 이런것들을 사용하실 때 key를 활용하시면 리컴포지션을 줄일 수 있을거에요
Modifier.height(240.dp) | ||
) { | ||
Image( | ||
painter = painterResource(rankers[index]), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
painter내부를 보면 UnStable해요. 그렇기에 Stable한 ImageVector를 사용한다면 리컴포지션을 줄일 수 있어요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
매주 과제 수행하시느냐 너무 고생많으셨습니다!! 앱잼도 화이팅~
@Composable | ||
fun HomeTopBar( | ||
onLiveButtonClick: () -> Unit | ||
) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
home에서만 쓰는 topbar라면 home쪽으로 옮겨줘도 좋을 것 같아용
여기는 파일 전역에서 쓰는 컴포넌트들을 넣어주면 될 것 같습니다
data class SignUpUiState( | ||
val signUpUsername: String = "", | ||
val signUpPassword: String = "", | ||
val signUpHobby: String = "", | ||
val isSignUpPasswordVisible: Boolean = false | ||
) | ||
|
||
sealed class SignUpResult { | ||
object Initial : SignUpResult() | ||
object Success : SignUpResult() | ||
object FailureInformationLength : SignUpResult() | ||
object FailureDuplicateUsername : SignUpResult() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Contract에 있는 UiState랑은 어떤게 다른건가요?? SignUpUiState가 두개 있길래요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고생하셨습니다 ~
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
UI 단에서 사용되는 sealed class니 presentation 단에 위치시켜주어도 좋을 것 같아요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
core에 위치시키신 이유가 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
위에 있는 Route class와 같은 친구인 것 같은데 확인해보시면 좋을 것 같네요
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
마찬가지로 core에 위치시키신 이유가 있는지 궁금합니다.
data를 저장하고 가져오는 로직이니 data 레이어와 조금 더 어울리는 것 같아서요.
SignUpResponseEntity( | ||
no = it.no, | ||
status = signUpResponseDto.code(), | ||
code = signUpResponseDto.body()!!.code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
!!는 NPE를 발생시킬 수 있기 때문에 사용을 지양하는 것이 좋습니다 ~
import org.sopt.and.R | ||
import org.sopt.and.core.navigation.Screen | ||
|
||
data class MainBottomTab( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enum을 사용해보셔도 좋을 것 같네요 ~
getMyHobby: () -> Unit, | ||
modifier: Modifier = Modifier | ||
) { | ||
getMyHobby() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getMyHobby의 결과값을 넘겨주는 형태로 해서 MyInfoProfile의 책임을 더 분리하는 게 어떨까요?
data object NavigateUp : SignUpUiEffect() | ||
} | ||
|
||
enum class Field { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
enum으로 선언하신 이유가 있나요?
Related issue 🛠
Work Description ✏️
Screenshot 📸
이전 화면과 동일합니다.
Uncompleted Tasks 😅
To Reviewers 📢
MVI 진짜 쉽지 않네요...
이전 코리 반영과 더 고민해서 추가 작업해보겠습니다.
이번 주도 다들 시험 보느라 고생하셨어요!