강의

멘토링

로드맵

인프런 커뮤니티 질문&답변

정라잇님의 프로필 이미지
정라잇

작성한 질문수

토비의 클린 스프링 - 도메인 모델 패턴과 헥사고날 아키텍처 Part 1

Member 도메인 코드 개선

코틀린에서 value class 적용 시 문제

작성

·

5

0

안녕하세요 코틀린으로 현재 강의를 수강하고 있는 수강생입니다.

 

현재 자바로 작성된 코드를 보고 설명과 함께 어떤 이유로 이런 코드를 작성한 것인지 생각하며, 코틀린으로 이 개념을 적용하면 어떻게 작성할 수 있을지 DDD와 클린 아키텍처를 코틀린 문법 활용하여 구상하는 연습 중입니다.

 

현재 Member 도메인 코드 개선 강의에서 value class 적용하여 필드의 값이 바뀌는 문제(email자리에 nickname이 오더라도 같은 String이라 컴파일 에러가 안 남)를 해결하려 시도했습니다

 

package org.example.splearn.domain

@JvmInline
value class Email(
    val value: String,
)

@JvmInline
value class Nickname(
    val value: String,
)

@JvmInline
value class PasswordHash(
    val value: String,
)

class Member private constructor(
    val email: Email,
    var nickname: Nickname,
    var passwordHash: PasswordHash,
    var status: MemberStatus,
) {
    fun activate() {
        check(status == MemberStatus.PENDING) {
            "회원이 PENDING 상태가 아닙니다"
        }
        this.status = MemberStatus.ACTIVATE
    }

    fun deactivate() {
        check(status == MemberStatus.ACTIVATE) {
            "회원이 ACTIVE 상태가 아닙니다"
        }
        this.status = MemberStatus.DEACTIVATED
    }

    fun verifyPassword(
        password: String,
        passwordEncoder: PasswordEncoder,
    ): Boolean = passwordEncoder.matches(password, this.passwordHash.value)

    fun changeNickname(nickname: String) {
        this.nickname = Nickname(nickname)
    }

    fun changePassword(
        password: String,
        passwordEncoder: PasswordEncoder,
    ) {
        this.passwordHash = PasswordHash(passwordEncoder.encode(password))
    }

    fun isActive(): Boolean = this.status == MemberStatus.ACTIVATE

    companion object {
        fun create(
            memberCreateRequest: MemberCreateRequest,
            passwordEncoder: PasswordEncoder,
        ): Member =
            Member(
                email = memberCreateRequest.email,
                nickname = memberCreateRequest.nickname,
                passwordHash =
                    PasswordHash(
                        passwordEncoder.encode(memberCreateRequest.password.value),
                    ),
                status = MemberStatus.PENDING,
            )
    }
}

강의대에서는 static 메소드인 of에서 MemberCreateRequest를 파라미터로 사옹하고 있습니다. 코틀린이라 companion object를 사용했구요

 

그러던 중 "헥사고날 아키텍처의 특성을 고려하면 의존성 외부 로직인 dto가 내부로 향해야 하고 따라서 도메인이 dto에 의존하는 것이 괜찮을까" 하는 의문이 들었습니다.

 

companion object {
        fun create(
            email: Email,
            nickname: Nickname,
            password: String,
            passwordEncoder: PasswordEncoder,
        ): Member =
            Member(
                email = email,
                nickname = nickname,
                passwordHash =
                    PasswordHash(
                        passwordEncoder.encode(password),
                    ),
                status = MemberStatus.PENDING,
            )
    }

그래서 코드를 수정해 보면 이런 식으로 수정해 볼 수 있을 것 같습니다.

 

이에 대해서 토비님 의견이 어떠신지 여쭙고 싶습니다

답변

답변을 기다리고 있는 질문이에요
첫번째 답변을 남겨보세요!
정라잇님의 프로필 이미지
정라잇

작성한 질문수

질문하기