프로젝트를 진행하다가 동료분이 UseCase의 invoke함수에 operator를 안 붙였다는 이야기를 PR에서 언급하신 걸 보았다.
예를 들어서 아래와 같이 토큰을 가져오는 UseCase가 있다고 가정하면, 밑에 있는 invoke함수에 operator가 없으면 아래와 같이 호출해야 한다
GetMemberUseCase("1").invoke()
class GetMemberUseCase(
private val memberRepository: MemberRepository
) {
fun invoke(id:String): Flow<MemberResponse> = flow{
emit(memberRepository.getMember(id))
}
}
하지만 invoke 함수에 operator키워드를 붙이면 객체를 함수처럼 호출할 수 있다. GetMemberUseCase("1")은 내부적으로 GetMemberUseCase().invoke("1")로 컴파일된다.
GetMemberUseCase("1")
...라고 인지하고 작업을 재개했었다.
하지만 시간날 때 기초지식을 정리해야 갓발자가 될 수 있다
코틀린은 자바와 다르게 관례가 있다. 관례란 미리 정해둔 이름을 사용한 메서드를 통해서 긴 식 대신더 짧고 간결한 식을 쓸 수 있게 지원하는 것이다.
인라인하는 람다를 제외한 모든 람다는 함수형 인터페이스를 구현하는 클래스로 컴파일된다.
술어 클래스 내부와 술어가 쓰이는 주변에 복잡한 로직이 있는 경우 관심사를 분리해내는데 유용하다.
data class Perfume(
val price:String, val brand:String, val genderType:Gender, val StorageType:Storage
)
val perfume1 = Perfume(100000, "channel", Gender.WOMAN, Storage.SOLD_OUT)
val perfume2 = Perfume(140000, "gucci", Gender.MAN, Storage.FEW_LEFT)
for (perfume in listOf(perfume1, perfume2).filter(it.name == "gucci" && Gender.WOMAN && Storage.FEW_LEFT)){
//처리
}
위의 함수의 복잡한 filter조건을 사용해서 향수를 걸러내는 코드가 있다.
filter 에 들어가는 람다식이 그렇게 어려운 내용은 아니지만,예시 코드인 걸 감안하면 이런식의 코드는 조잡하다.
람다를 여러 메서드로 나누고 뜻을 명확히 알 수 있는 이름으로 바꾸는 게 더 좋다.
이렇게 람다를 함수 타입 인터페이스를 구현하는 클래스로 변환하고, 그 클래스의 invoke 메서드를 오버라이드하면 깔끔한 리팩토링이 가능하다.
data class Perfume(
val price:String, val brand:String, val genderType:Gender, val StorageType:Storage
)
class GucciBlackFridaySaleTarget():(Perfume) -> Boolean {
operator fun invoke(perfume:Perfume):Boolean{
return EventCalendar.BLACK_FRIDAY == LocalDate.now() && perfume.isGucci*(
}
private fun Perfume.isGucci():Boolean{
return brand == "gucci"
}
}
val perfume1 = Perfume(100000, "channel", Gender.WOMAN, Storage.SOLD_OUT)
val perfume2 = Perfume(140000, "gucci", Gender.MAN, Storage.FEW_LEFT)
val target = GucciBlackFridaySaleTarget()
for (perfume in listOf(perfume1, perfume2).filter(target)){
//처리
}
Kotlin in Action - DSL 만들기
https://onlyfor-me-blog.tistory.com/837