Notice
Recent Posts
Recent Comments
Link
«   2026/10   »
일 월 화 수 목 금 토
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Tags more
Archives
Today
Total
관리 메뉴

seaking110 님의 블로그

계산기 만들기 트러블 슈팅 본문

Today I Learned

계산기 만들기 트러블 슈팅

seaking110 2025. 1. 10. 12:59

 

계산기 만들기 트러블 슈팅

 

Lv 2 여러개의 예외 클래스 생성

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

 

Lv 3 제네릭 타입 이용 문제

1. 입력 값을 제네릭 타입으로 리턴하는 문제

  • 문제
    • 입력 메서드를 구분 했을 때 double 혹은 int로 받은 입력 값을 T num으로 리턴을 해야한다.
  • 해결 방안
    • Class<T> 와 cast 메서드 사용
      • 런타임에서의 타입 안정성을 보장
      • 컴파일 단계에서는 타입 안정성을 완벽히 보장 x

 

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