Skip to content

[산군] 4단계 자동 DI 미션 제출합니다#64

Merged
EmilyCh0 merged 10 commits into
woowacourse:s9hnfrom
s9hn:step4
Sep 27, 2023
Merged

[산군] 4단계 자동 DI 미션 제출합니다#64
EmilyCh0 merged 10 commits into
woowacourse:s9hnfrom
s9hn:step4

Conversation

@s9hn

@s9hn s9hn commented Sep 19, 2023

Copy link
Copy Markdown

안녕하세요 해선생님.. 주변에서 해시 짱잘했다는 소문이 자자자합니다..

구조를 다 고쳤는데 크게 달라진건 없는 것 같고 해시랑 구조 비슷해보이긴해요

테스트를 짜면서 하긴했는데, 아직 테린이라 테스트 많이 봐주시면 감사하겠습니다.

테스트맞추면서 코드짤때는 깔끔하게 짰는데, 테스트를 구리게짜서 그런가 실제 본 코드에 도입할 때는 엄청 예외상황이 많더라구요.. 시간이없어서 예외상황 급하게 처리하다보니 Injector가 굉장히 비대해졌습니다..

현재 테스트와 빌드는 터지진않습니다 잘부탁합니다!

@s9hn s9hn changed the title Step4ㅇ [산군] 4단계 자동 DI 미션 제출합니다 Sep 19, 2023

@EmilyCh0 EmilyCh0 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

2,3 단계 요구사항에 테스트까지 추가하느라 할 게 많았을 텐데 미션 너무 고생하셨습니다!! 코멘트 확인해 주시고, 남은 요구사항 완료해서 다시 리뷰 요청해주세요!

import com.created.customdi.annotation.Qualifier

@Qualifier
annotation class Database

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

한정자는 구현체를 식별할 수 있는 일종의 ID라고 생각하는데요!
계층 구조로 같은 한정자를 사용한다면 Qualifier의 의미가 조금 퇴색된다고 생각합니다!

해시가 달아준 코맨트가 제가 이해한 바가 맞을까요?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

식별에 사용하는 일종의 ID로 CartRespository에서만 사용하는 Database 어노테이션이라면
CartDatabase 이런식으로 식별 가능한 이름이어야 하는 것 아닐까해서 남긴 코멘트였습니다!

Comment thread customDi/build.gradle.kts Outdated
implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.21")
implementation("androidx.core:core-ktx:1.9.0")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.9.0")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

customDi에 material?? 🤔

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

기본생성이였는데 이런 사소한것까지 ㄷㄷ

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

제 di 모듈에도 있네요ㅋㅋㅋ

import kotlin.reflect.jvm.jvmErasure

object Injector {
const val INVALID_CLASS_TYPE = "[ERROR] Its class type cannot be injected"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

이것만 public 이네요!

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

inline내부에서만 사용되는 문자열이라 private이 안되는데 방법이 있을까유

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

앗 이 부분은 제가 잘못 본 것 같아요 😅 public하게 둘수밖에 없네요!

Comment on lines +73 to +81
val module = modules.find { module ->
module::class.declaredFunctions.any {
if (func.annotations.any { it.hasQualifier() }) {
it.annotations.filter { it.hasQualifier() } == func.annotations.filter { it.hasQualifier() }
} else {
it.returnType.jvmErasure == func.returnType.jvmErasure
}
}
} ?: throw IllegalArgumentException(INVALID_FUNCTION)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

코드를 이해하기 너무 어려워요! it 보다는 이름을 정해주는게 어떨까요?

Comment on lines +61 to +71
@Test
fun `생성자로 QualifiedClass3을 갖는 A 인스턴스가 생성된다`() {
// given : QualifiedClass3는 Qualifier를 가지고 있다
class A(@TestQualifier3 qualifiedClass3: QualifiedClass3)

// when : inject를 호출하면
val actual = Injector.inject<A>()

// then : 해당 타입에 대한 인스턴스가 생성된다.
assertEquals(true, actual is A)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Qualifier를 테스트하려면 클래스 A가 Qualify 타입을 받아야 할 것 같아요!

class A(@TestQualifier3 qualifiedClass3: Qualify)

생성된 actual 인스턴스가 가지고 있는 qualifiedClass3가 진짜로 QualifiedClass3 타입인지도 확인하면 좋을 것 같습니다!

import org.junit.Test
import kotlin.reflect.full.primaryConstructor

class InjectorTest {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

테스트 굿 👍
Single 인스턴스를 두 번 생성했을 때 정말 싱글톤인지, Normal을 두 번 생성했을 때 다른 인스턴스인지도 테스트해보면 좋을 것 같아요!

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

dateFormatter도 필드 인젝션으로 주입해 볼 수 있을 것 같아요!

Comment on lines +47 to +51
Log.d("12312311", property.toString())
Log.d("12312322", property.parameters.toString())
val instance = property.getSingletonIfInstantiated()
?: property.instantiate()
Log.d("12312344", property.toString())

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

로그 제거!

Comment on lines +17 to +23
@InMemory
fun provideCartRepository(): CartRepository =
InMemoryCartRepository()

@Database
fun provideCartRepository(cartProductDao: CartProductDao): CartRepository =
DatabaseCartRepository(cartProductDao)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  • CartRepository는 앱 전체 LifeCycle 동안 유지되도록 구현한다.

CartRepository는 Singleton 어노테이션을 붙여야 하는 거 맞나요??

Comment on lines +57 to +65
fun Any.getSingletonIfInstantiated(): Any? {
val type = when (this) {
is KProperty1<*, *> -> returnType.jvmErasure
is KParameter -> type.jvmErasure
else -> throw IllegalArgumentException()
}

return DiContainer.singletonInstance[type]
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

예외상황을 다 찾지는 못했는데.. 일단 싱글톤인데 Qualifier가 붙은 경우 인스턴스를 못 찾는 것 같아요! (CartRepository가 매번 생성됨)

@s9hn

s9hn commented Sep 25, 2023

Copy link
Copy Markdown
Author

흐에... 미션..이 우선순위가 많이 내려가서 플젝하고 근로하고 이것저것하느라 많이 못했네요..

해시도 그동안 리뷰하느라 고생했습니다 감사함다!

혹시 궁금하시면 구경..해보셔도 되고 피알도 언제든 환영입니다!

@EmilyCh0 EmilyCh0 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

산군! DI 미션 너무 고생하셨습니다!! 더 수정하고 싶다고 하셔서 대기하고 있었는데 리뷰를 더 미룰 수 없을 것 같아 우선 approve 하겠습니다! 머지 원하실 때 dm 주세요~

Comment on lines +32 to +34
private fun setupDateFormatter() {
dateFormatter = DateFormatter(this)
}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

여전히 개발자가 직접 DateFormatter 인스턴스를 관리하는 것으로 보이네요! 저는 다음과 같이 액티비티에 필드 주입을 했는데 참고만해주세요!
→ CartActivity가 DiActivity 상속, DiActivity가 AppCompatActivity 상속하도록 하고 DiActivity의 onCreate에서 필드 주입. (약간 BaseActivity 느낌으로??)

@EmilyCh0 EmilyCh0 merged commit c892ae8 into woowacourse:s9hn Sep 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants