[TIL] 2025-01-09_계산기3_리펙토링

Yuri·2025년 1월 9일

TIL

목록 보기
25/59

🔫 계산기 과제 Lv3 구현하며 겪은 문제점과 해결방법, 새로 알게된 점을 기록합니다.

🧑‍🔧 계산기 과제 리펙토링

계산기 Lv 3의 소스를 검토하던 중 연산 수행 역할을 하는 ArithmeticCalculator의 코드 가독성이 떨어져 수정을 고민하게 되었다.

문제점

코드를 보면 각 사칙연산 메서드가 ArithmeticCalculator 안에 add, substract, multiply, divide 라는 이름으로 구현되어있고 calculate 메서드에서는 입력된 연산기호에 따라 해당 메서드를 호출하는 식으로 구성되어 있다.

사칙연산 메서드는 모두 2개의 매개변수를 입력받아 계산하고 그 결과값을 반환하는 단순한 메서드이다. (나눗셈의 경우만 divide by zero 예외가 발생할 수 있어 해당 예외를 던진다.)

추상 메서드와 오버라이딩을 활용하면 calculator의 사칙연산 호출부분을 깔끔하게 구현할 수 있지 않을까?

사칙연산 메서드를 호출하는 부분만 보면 결국 OperatorType 이라는 Enum 클래스에 따라 어떤 메서드를 호출할 지 결정된다. 사실 사칙연산 기호를 그냥 받아서 처리해도 되는데 굳이 Enum으로 처리할 이유가 있을까?

해결 방법

Enum 도 클래스이다. 즉, Enum 안에 추상 메서드를 정의하고 각 Enum 상수에서 구현하여 Enum 상수별로 다르게 동작하는 행위를 지정할 수 있다.

▶︎ 기존 코드

▶︎ 수정 코드: 추상 메서드와 익명 클래스로 정의한 코드

추상 메서드 calculate: 모든 연산은 BigDecimal 2개를 매개변수로 받고, Number 를 반환한다.
각 Enum 상수는 추상 메서드 calculate를 상속받아 덧셈, 뺄셈, 곱셈, 나눗셈을 구현한다.

▶︎ 수정 코드: ArithmeticCalculator 호출

수정 후 코드를 보면 switch로 분기처리할 필요없이 operatorType에 따라 정해진 calculate 메서드를 호출하여 결과값을 반환한다.

➕) 익명 클래스는 함수형 프로그래밍, 람다 표현식으로도 만들 수 있다.

위의 익명 클래스로 구현했던 사칙연산을 람다 표현식을 이용한 함수형 인터페이스 BiFunction으로 수정하여 OperatorType 의 코드 가독성이 높아졌다.

  • 함수형 인터페이스 표준 API
함수형 인터페이스메서드 형태API 활용매개변수반환값
Runnablevoid Run()매개 변수를 사용 안하고 리턴을 하지 않는 함수 형태로 이용
→ 대표적으로 쓰레드의 매개 변수로 이용
XX
Consumervoid accept(T t)매개 변수를 사용만 하고 리턴을 하지 않는 함수 형태로 이용OX
SupplierT get()매개 변수를 사용 안하고 리턴만 하는 함수 형태로 이용XO
Function<T, R>R apply(T t)매개값을 매핑(=타입변환)해서 리턴하기OO
Predicateboolean test(T t)매개값이 조건에 맞는지 단정해서 boolean 리턴OO
OperatorR applyAs(T t)매개값을 연산해서 결과 리턴하기OO

위에서는 표준 API 중 두 개의 매개변수를 받아 매핑 해서 리턴하는 BiFunctio<T, U, R> 을 사용하였다.

배운 점

  • Enum 상수는 상태와 행위를 한 곳에서 관리할 수 있다.
  • Enum 클래스 내부에서 추상 메서드와 익명 클래스로 행위를 지정할 수 있다.
  • Enum의 행위를 구현한 익명 클래스는 람다 표현식으로도 만들 수 있다.

이번 과제를 구현하면서 과제 요구조건에 따라 코드를 짰지만 스스로 그 필요성과 개선 방안을 찾으려 하는 자세가 아직은 많이 부족하다고 느낀다. 만약, 요구사향에 Enum을 쓰라는 조건이 없었다면 위와 같이 코드를 짤 수 있었을까? 라는 생각이 든다. 항상 더 나은 방안을 고민하는 좋은 개발자의 자세가 시간과 노력으로 갖춰지면 좋겠다.

참고자료
☕ 자바 Enum 열거형 타입 문법 & 응용 💯 정리
☕ 함수형 인터페이스 표준 API 총정리

profile
안녕하세요 :)

0개의 댓글