책임감 있게 모든 일에 최선을 다하는 백엔드 개발자 Zin 입니다.
Kotlin, Java, Spring Boot 을 이용한 백엔드 애플리케이션을 개발합니다. 적절한 관심사 분리를 통해 의존성을 관리하고 유연하고 확장성이 좋은 설계를 지향합니다.
안정적이고 좋은 성능의 기술의 사용과 함께 서비스 사용자, 운영 등 다양한 관점을 가지고 비즈니스 임팩트를 고민합니다.
질문&답변
2024.08.29
도메인 모델 아키텍처 패턴 추가 리팩토링
안녕하세요, 다람님!수강은 물론 리팩터링까지 진행하시다니, 멋집니다. 😀먼저, 질문주신 1, 2, 3번은 말씀하신 내용이 맞습니다.추가적으로 공유해주신 내용에서 크게 3가지를 말씀드리고 싶습니다. Domain Service의 적용Payment 도메인에 ExRateProvider와 Clock을 직접 넘겨 구현한 것이 의도하신 도메인 모델 패턴으로 볼 수 있겠습니다. 추가 리팩토링Test Code에서 @BeforeEach 라는 애노테이션 붙인 메소드를 만드시면, 각 테스트 메소드가 실행되기 전에 '준비'하는 작업을 구성해둘 수 있습니다. 또한 중복 코드를 제거하는 효과도 생기겠죠? 아래는 제가 만든 예시 입니다.class PaymentTest { private Clock clock; private ExRateProviderStub exRateProvider; @BeforeEach void setUp() { this.clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); this.exRateProvider = new ExRateProviderStub(valueOf(1_000)); } @Test void createPrepared() throws IOException { Payment payment = Payment.createPrepared( 1L, "USD", BigDecimal.TEN, exRateProvider, clock ); Assertions.assertThat(payment.getConvertedAmount()).isEqualByComparingTo(valueOf(10_000)); Assertions.assertThat(payment.getValidUntil()).isEqualTo(LocalDateTime.now(clock).plusMinutes(30)); } @Test void isValid() throws IOException { Payment payment = Payment.createPrepared( 1L, "USD", BigDecimal.TEN, exRateProvider, clock ); Assertions.assertThat(payment.isValid(clock)).isTrue(); Assertions.assertThat( payment.isValid(Clock.offset(clock, Duration.of(30, ChronoUnit.MINUTES)))).isFalse(); } }해당 Test Class 자체에서 Payment가 전역에서 필요하다면 Payment 도 setUp()에 넣을 수 있겠죠? ExRateProviderStub 오브젝트를 저장하는 변수의 타입을 ExRateProvider로 지정하면 테스트하는 목적과 대상이 더욱 명확히 보일 것 같습니다. 위 예시에서 ExRateProviderStub 타입 선언만 ExRateProvider 으로 바꿔줘도, 테스트 코드를 읽으면서 ExRateProvider를 테스트에 사용한다는 것이 명확해집니다.class PaymentTest { private Clock clock; private ExRateProvider exRateProvider; @BeforeEach void setUp() { this.clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); this.exRateProvider = new ExRateProviderStub(valueOf(1_000)); } // 생략 } Lambda 활용위의 예시 같이 new 생성자로 ExRateProviderStub을 사용할 수도 있습니다. 또 다르게는, 인터페이스에 메소드가 1개일 경우 Lambda를 통해 그 1개의 메소드를 사용하는 방법도 있습니다. 이는 테스트 목적으로 추가 Class를 정의하지 않고도 실행할 수 있는 방법이기도 합니다.class PaymentTest { private Clock clock; private ExRateProvider exRateProvider; @BeforeEach void setUp() { this.clock = Clock.fixed(Instant.now(), ZoneId.systemDefault()); this.exRateProvider = currency -> BigDecimal.valueOf(1_000); } // 생략 } 제 예시 코드가 정답은 아닙니다. 다만, 왜 이렇게 구성하고 고치는지 이해하면 그게 더 나은 개발이고 코드라고 생각합니다. 😁 지금처럼 꾸준히 강의나 학습을 통해 성장하시길 응원하겠습니다!