[프로그래밍 초식] 사소한 개선 - 섞여 있는 계산/반영 로직 분리

·2022년 11월 12일
0

프로그래밍 초식

목록 보기
1/1
post-thumbnail

이 포스팅은 최범균님의 유튜브 영상을 보고 정리한 글입니다.


위의 코드에서는 다양한 조건으로 뭔가를 계산하고, 그 결과를 반영한다.
즉, 계산과 반영 코드가 섞여있다.

[단점]

  • 계산 로직을 이해하는데 결과 반영 코드가 방해가 된다.
  • 계산 로직만 테스트하기 어렵다.

계산과 반영 코드를 분리해줘야한다.

[계산 코드]와 [계산 결과를 사용하는 코드]를 분리

  • 계산하는데 필요한 값 (입력값)
  • 계산 결과로 생성되는 값 (출력값)

입력값과 출력값의 행성관계


시각적으로 나타내보면 입력과 출력이 무엇인지 알아내는데 도움이 된다.

시각화로 알아낸 입력값과 출력값

  • 입력값: order, loginDate
  • 출력값: sdate, edate

알아낸 내용들을 바탕으로 계산 로직을 분리해보자.

// 1. 메소드를 하나 만들고, if절이나 다른 용도로 사용됐던 모든 필요한 값들을 메소드 파라미터로 전달하는 방식 
ServicePeriod period = calculatePeriod(order.getGubun(), order.getPayType(), ..., loginDate);

// 2. 메소드를 만들고, order라는 객체를 통으로 주는 방식
ServicePeriod period = calculatePeriod(order, loginDate);

// 3. 같은 클래스의 메소드로 하지 않고, 별도의 객체로 분리해서 객체를 통해 계산하는 방식
ServicePeriod period = new ServicePeriodCalculator(order, loginDate).calculate();

// ServicePeriod
LocalDate sdate = period.getSdate();
LocalDate edate = period.getEdate();

여기서는 3번째 방식을 선택했다.
그 이유는, 객체를 따로 분리해야 로직을 테스트하기 쉽기 때문이다.
ServicePeriod를 만들고, ServicePeriod는 출력값 (edate, sdate)를 갖도록 하자.


public class ServicePeriodCalculator {
	private Order order;
	private LocalDate loginDate;

	public ServicePeriodCalculator(Order order, LocalDate loginDate) {
		this.order = order;
		this.loginDate = loginDate;
	}

	public Main calculate() {
		LocalDate edate = null;
		LocalDate currDate = order.getDate();
		LocalDate nextDate = YearMonth.from(currDate.plusMonths(1)).atDay(1);
		if (order.getGubun().equals("AA")) {
			if (order.getPayType().equals("A") ||
				(order.getPayType().equals("W") && order.getIncludePay().equals("1"))) {
				if (order.getPayMonth().equals("T")) {
					edate = YearMonth.from(currDate).atEndOfMonth();
				} else if (order.getPayMonth().equals("N")) {
					edate = YearMonth.from(currDate).plusMonths(1).atEndOfMonth();
				}
				return new ServicePeriod(currDate, edate);
			} else if (order.getPayType().equals("W") && order.getIncludePay().equals("2")) {
				// ... 생략
			}
		} else {
			if (order.getUnit().equals("D")) {
				edate = loginDate.plusDays(order.getQty());
			} else if (order.getUnit().equals("M")) {
				edate = loginDate.plusMonths(order.getQty());
			}
			return new ServicePeriod(loginDate, edate);
		}
	}
}
public class Main {

	public void provideServicePeriod(Long ordNo, LocalDate loginDate) {
		// period, order 구하고 검사하는 코드 생략
		ServicePeriod period = new ServicePeriodCalculator(order, loginDate).calculate();
		updatePeriod(period, period.getSdate(), period.getEdate());
	}
}

분리에서 오는 장점

  • 계산 로직만 테스트할 수 있다.
  • 계산 로직 리팩토링이 수월해진다.

0개의 댓글