-
Notifications
You must be signed in to change notification settings - Fork 25
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
[베리] 2, 3단계 자동 DI 미션 제출합니다 #46
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.
화이팅!
private fun initContainer() { | ||
DefaultContainer.addInstance( | ||
DefaultProductRepository() | ||
) | ||
DefaultContainer.addInstance( | ||
ShoppingDatabase.getDatabase(applicationContext).cartProductDao() | ||
) | ||
DefaultContainer.addInstance( | ||
InMemoryCartRepository() | ||
) | ||
DefaultContainer.addInstance( | ||
Injector.inject<RoomDBCartRepository>() | ||
) | ||
} |
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.
이전에 다른 크루에게 달린 리뷰를 참고해보겠습니다!
컴포넌트로 등록하려는 대상 클래스에 추가한 애너테이션을 활용하면 이와 같은 코드를 없애고 라이브러리를 더 사용자 친화적으로 만들 수 있을 거예요. 아래의 글이 도움 될 거예요.
https://www.baeldung.com/reflections-library
binding.item = product | ||
binding.tvCartProductCreatedAt.text = dateFormatter.formatDate(product.createdAt) | ||
// TODO: Step2 - dateFormatter를 활용하여 상품이 담긴 날짜와 시간을 출력하도록 변경 |
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.
TODO 주석은 이만 보내줘도 괜찮을 것 같아요!! 안녕~👋🏼
// Reflection | ||
implementation(kotlin("reflect")) | ||
|
||
testImplementation("junit:junit:4.13.2") |
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.
junit4를 사용하신 이유가 있을까요?
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.
지금까지 junit4 를 써와서 익숙한 라이브러리를 사용하였습니다! 🤗
// Inject 어노테이션 붙은 파라미터들만 들어옴 | ||
val dependencies: MutableMap<KParameter, Any> = mutableMapOf() | ||
parameters.forEach { parameter -> | ||
val annotation: Annotation? = parameter.annotations.firstOrNull { it != 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.
문맥상 Inject 어노테이션이 있는지 확인해야할 것 같아요.
이 경우에는 firstOrNull은 적절하지 않습니다.
더 적절한 api를 활용해주세요!
val annotation: Annotation? = parameter.annotations.firstOrNull { it != Inject() } | ||
val annotationType = AnnotationType(annotation, parameter.type.jvmErasure) | ||
dependencies[parameter] = | ||
container.getInstance(annotationType) ?: throw NoSuchElementException() |
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.
throw Exception을 할 때 메시지가 없다면 오류 발생시 원인을 찾기 어려울 것 같습니다.
di/src/test/java/InjectorTest.kt
Outdated
} | ||
|
||
@Test | ||
fun `의존성 모듈이 모두 제공될 때 자동 DI 가 성공하는지 테스트`() { |
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.
다음 리뷰 요청때까지 더 많은 미션 요구사항을 만족시킨 상태라면 더 더 더 좋을 것 같아요!
어렵겠지만 조금만 더 화이팅해보자고요!
베리의 다음 리뷰요청 기대하면서 저도 열심히 해보겠습니다!
수달~!~! 드디어 리뷰 요청 보냅니당..ㅎㅎ
|
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.
베리 step2, step3 필수 요구사항을 모두 잘 만족시키신 것 같아요! 고생 많으셨습니다!!
추가로 고민해봤으면 하는 부분에 대해 코멘트 남겨두었습니다.
step4 마감일이 많이 남지 않았으니 읽어만 보시고, step4 요구사항 구현을 우선시하면 될 것 같습니다!
화이팅입니다!
import woowacourse.shopping.model.CartProduct | ||
import woowacourse.shopping.model.Product | ||
|
||
class RoomDBCartRepository @Inject constructor(private val dao: CartProductDao) : |
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.
constructor에 Inject를 달면 사용할 때 편할 것 같네요! 줍줍해갑니다!
@@ -14,10 +15,12 @@ import kotlin.reflect.full.memberFunctions | |||
import kotlin.reflect.full.staticFunctions | |||
import kotlin.reflect.jvm.jvmErasure | |||
|
|||
annotation class AA |
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.
급하셨나요ㅋㅋㅋㅋㅋㅋㅋ🫠
아무리 테스트라지만 네이밍 버리지 말아주세요ㅠㅠ
어떤 테스트를 위한 것인지 이름에서 드러나게 해주세요!
fun getDatabase(context: Context): ShoppingDatabase { | ||
return INSTANCE ?: synchronized(this) { | ||
val instance = Room.databaseBuilder( | ||
context, | ||
ShoppingDatabase::class.java, | ||
databaseName | ||
).build() | ||
INSTANCE = instance | ||
instance | ||
} | ||
} |
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.
인스턴스화에 사용한 context가 역할을 다하고 종료되어 사라졌을 때 문제가 발생할 수 있을 것 같아요.
이는 step4와도 관련이 있을 것 같네요!
@Test | ||
fun `인터페이스가 아닌 클래스를 생성자로 주입받는 경우 생성자에 @Inject 키워드만 붙이면 된다`() { | ||
// given | ||
class FakeViewModel @Inject constructor(val fakeRepository: FakeRepository) | ||
|
||
// when | ||
Injector.inject<FakeViewModel>() | ||
} |
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.
than이 없어요😱
생성이 잘 됐다는 것을 확인하는게 애매할 수 있을 것 같네요.
저의 경우에는 than에서 FakeViewModel
의 fakeRepository
가 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.
Injector가 유능하게도 혼자서 많은 일을 하고 있는 것 같아요.
Injector의 일을 덜어줄 객체가 있다면 좋을 것 같아요!
coEvery { | ||
cartRepository.addCartProduct(product) | ||
} answers { nothing } |
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.
mock 객체를 지원하는 라이브러리를 사용하지 않고, fake 객체를 사용해 테스트하는 방법도 있습니다!
안녕하세요 수달 ~! 그동안 잘 지내셨나용 ㅎㅎ🦦
2,3 단계 자동 DI 미션 제출합니다!
시간이 부족해서 필수 요구사항만 만족했습니다 😅 선택 요구사항은 차차 채워나가겠습니다!
그리고 기존에는 Repository 인스턴스를
Module 클래스
안에서 생성한 후, 해당Module 리스트를 Injector 가 가지고 있는
형태였습니다.그러나 기존 구조로는 Recursive DI 를 구현하는데에 한계가 생겨서 구조를 조금 수정하였습니다!
현재는
Application 에서 Repository 인스턴스를 생성
하여Container Object 에 저장
하여 Injector 가 이 Container 에 접근하여 인스턴스를 가져오는 구조로 수정하였습니다!2단계 요구 사항 중 Recursive DI 부분 제 코드가... 뭔가 자동 Recursive DI 가 아니라...수동의 느낌이...물씬 나는 점 피드백 부탁드립니다! ㅠ
추가로 궁금한 점 있으시면 편하게 질문주세요!🤗
android-di
2 단계 - Annotation
기능 요구 사항
필드 주입
Annotation
Recursive DI
선택 요구 사항
프로그래밍 요구 사항
3 단계 - Qualifier
기능 요구 사항
Qualifier
모듈 분리
선택 요구 사항