seaking110 님의 블로그
계산기 만들기 트러블 슈팅 본문
계산기 만들기 트러블 슈팅
Lv 2 여러개의 예외 클래스 생성
- 문제 상황
- 예외 처리 부족: 두 번째 숫자가 0인 경우, 나눗셈 연산 시 오류가 발생할 수 있음. 이를 처리하기 위해 DivideException이라는 사용자 정의 예외 클래스를 만들었음.
- 연산 기호 검증 문제: 연산 기호가 아닌 입력값이 주어질 경우에도 예외 처리가 필요했음. 이를 위해 또 다른 예외 클래스 InvalidOperatorException을 정의했으나, 예외가 다중 상속이 되지 않아 처리 필요
- 해결 방법
- 예외 클래스 상속 클래스 변경
- Exception -> RuntimeException 으로 변경
- Exception
- checked Exception으로 반드시 처리해야하는 예외
- 코드가 복잡, 개발자가 매번 처리 코드 작성 필요
- 예외가 반드시 처리되어야 하는 상황에 적합 (파일 입출력, 네트워크 통신)
- RuntimeException
- Unchecked Exception으로 예외처리 강제 x
- throws 선언 없이 사용 가능, 코드가 간결
- 개발자가 예외를 의도적으로 처리하지 않아도 되지만 프로그램이 종료될 가능성 존재
- 여러 예외 클래스 생성 방법 선택
- 두 가지 대안 비교
- 하나의 큰 예외 클래스로 통합
- 장점: 코드가 단순해지고 관리가 쉬워짐.
- 단점: 예외의 세분화가 어려워지고, 각각의 예외를 구분하지 못할 가능성이 있음.
- 상속을 활용한 예외 계층 구조 설계
- BaseCalculationException이라는 상위 예외 클래스를 정의하고, 이를 상속받아 DivideException과 InvalidOperatorException을 구현.
- 장점: 예외를 개별적으로 처리하면서도 공통 로직을 상위 클래스에서 관리할 수 있음, 확장성과 가독성이 향상 됨
- 단점: 설계가 조금 복잡해질 수 있음.
- 하나의 큰 예외 클래스로 통합
- 두 가지 대안 비교
- 상속을 활용한 예외 계층 구조 설계로 코드 유지보수성과 확장성을 높혔고 다양한 예외를 통합적으로 관리할 수 있었으며, 추가적인 기능 확장에도 유연하게 대응할 수 있게 되었다.

Lv 3 제네릭 타입 이용 문제
1. 입력 값을 제네릭 타입으로 리턴하는 문제
- 문제
- 입력 메서드를 구분 했을 때 double 혹은 int로 받은 입력 값을 T num으로 리턴을 해야한다.
- 해결 방안
- Class<T> 와 cast 메서드 사용
- 런타임에서의 타입 안정성을 보장
- 컴파일 단계에서는 타입 안정성을 완벽히 보장 x
- Class<T> 와 cast 메서드 사용
2. 와일드 카드 사용 시 오류
ArithmeticCalculator<? extends Number> cal = null;
- 문제
- 이런식으로 와일드 카드를 사용하면 cal을 사용해서 메서드를 불러올 시 오류가 발생
- 와일드카드는 타입 안정성을 보장하지만 값을 설정하거나 수정 즉 읽기 전용으로만 제한
- 문제 해결
- 와일드 카드를 삭제하면 되지만 그렇다면 계산기 초기 선언을 못함
- 제네릭 타입 캐스팅 방법 사용
if (type == 1) {
cal = new ArithmeticCalculator<Integer>();
ArithmeticCalculator<Integer> intCal = (ArithmeticCalculator<Integer>) cal;
intCal.setType(0); // Integer 타입에 맞는 초기값
break;
} else if (type == 2) {
cal = new ArithmeticCalculator<Double>();
ArithmeticCalculator<Double> doubleCal = (ArithmeticCalculator<Double>) cal;
doubleCal.setType(0.0); // Double 타입에 맞는 초기값
break;
}
Lv 3 같은 클래스에서의 필드 접근 방식 고민
- 필드 직접 접근 방식
public List<Double> largeResult(double d) {
largeResult.clear();
saveResult.stream()
.filter(f -> f > d)
.forEach(f -> largeResult.add(f));
return getLargeResult();
}
- 장점
- 간단하고 직관적
- 불필요한 메서드 호출 필요 x
- 메서드를 통한 간접 접근 방식
public List<Double> largeResult(double d) {
largeResult.clear();
saveResult.stream()
.filter(f -> f > d)
.forEach(this::setLargeResult);
return getLargeResult();
}
private void setLargeResult(Double value) {
largeResult.add(value);
}
- 장점
- 캡슐화
- 재사용성 향상
- 로직 변경 용이
최종 선택: 캡슐화를 강화하고, 코드 재사용성을 높일 수 있는 간접 접근 방식을 채용
'Today I Learned' 카테고리의 다른 글
| 객체간의 결합도와 다형성 (0) | 2025.01.14 |
|---|---|
| 키오스크 과제 1일차 (0) | 2025.01.13 |
| 계산기 만들기 (0) | 2025.01.10 |
| 모던 자바 (0) | 2025.01.08 |
| Thead (1) | 2025.01.07 |