dev_공부일지/Spring 6

관심사 분리 1. 메소드 단위

dev_0hoon 2024. 9. 17. 16:59
package com.hellopayment;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.LocalDateTime;
import java.util.stream.Collectors;

public class PaymentService {

    public Payment prepare(Long orderId, String currency, BigDecimal foreignCurrencyAmount) throws IOException {
        //활율 가져오기
        // https://open.er-api.com/v6/latest/USD
        URL url = new URL("https://open.er-api.com/v6/latest/" + currency);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));

        String response = br.lines().collect(Collectors.joining());
        br.close();

        ObjectMapper mapper = new ObjectMapper();
        ExRateData data = mapper.readValue(response, ExRateData.class);
        BigDecimal exRate = data.rates().get("KRW");
        
        System.out.println(data);
        System.out.println(exRate);
        //금액 계산
        BigDecimal convertedAmount = foreignCurrencyAmount.multiply(exRate);

        //유효 시간 계산
        LocalDateTime validUntil = LocalDateTime.now().plusMinutes(30);

        return new Payment(orderId, currency, foreignCurrencyAmount, exRate, convertedAmount, validUntil);
    }

    public static void main(String[] args) throws IOException {
        PaymentService paymentService = new PaymentService();
        Payment payment = paymentService.prepare(100L, "USD", BigDecimal.valueOf(50.7));
        System.out.println(payment);

    }

}

위의 코드는 요구사항에 맞게 동작하는 코드를 만들었다.

기능을 건들지 않고, 내부의 코드구조를 개선하는 것을 리팩토링이라고 한다.

 

코멘트(주석)을 다는 이유는 내용의 의미도 있지만, 코드가 어렵기에 내용을 적는 경우가 많다.

코드를 쉽게 만들어 주는 것이 핵심이라는 것.

 

 

관심사의 분리 (Separation of Concerns (SoC))

- 관심사라는 것은 변경의 관점으로 잡는 것이 좋다. (어떤 내용이 변경될 것이다. 라는 것)

- 만약 API를 가져오는 부분을 최신 라이브러리로 변경한다거나, DB에서 가져오자 라든가로 변경 될 수 있다.

 

    public Payment prepare(Long orderId, String currency, BigDecimal foreignCurrencyAmount) throws IOException {
        BigDecimal exRate = getExRate(currency);
        BigDecimal convertedAmount = foreignCurrencyAmount.multiply(exRate);
        LocalDateTime validUntil = LocalDateTime.now().plusMinutes(30);

        return new Payment(orderId, currency, foreignCurrencyAmount, exRate, convertedAmount, validUntil);
    }

    private BigDecimal getExRate(String currency) throws IOException {
        URL url = new URL("https://open.er-api.com/v6/latest/" + currency);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        BufferedReader br = new BufferedReader(new InputStreamReader(connection.getInputStream()));
        String response = br.lines().collect(Collectors.joining());
        br.close();

        ObjectMapper mapper = new ObjectMapper();
        ExRateData data = mapper.readValue(response, ExRateData.class);
        BigDecimal exRate = data.rates().get("KRW");
        return exRate;
    }

1. 환율을 가져오는 부분을 메소드로 만들어줬다.

- getExRate로 환율가져오기라는 주석은 더이상 의미가 없다.

 

2. 금액 계산하기 부분은 메소드명으로 이미 설명이 충분하므로 굳이 메소드로 만들 필요가 없다.

3. validUntil부분도 마찬가지 이므로 그대로 사용하면 충분하다.

4. 만약 환율을 가져오는 방식이 바뀔경우, getExRate만 변경하면 된다.