[TIL] 2025-01-04_계산기2_ 리펙토링

Yuri·2025년 1월 4일

TIL

목록 보기
21/59

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

레벨 2의 계산기 과제의 요구사항은 다음과 같다.

클래스를 적용해 기본적인 연산을 수행할 수 있는 계산기 만들기

Lv1에서 구현한 App 클래스의 메서드에 Calculator 클래스가 활용될 수 있도록 수정
 
[1] 연산 수행 역할은 Calculator 클래스가 담당
 1) 양의 정수 2개(0 포함)와 연산 기호를 매개변수로 받아 사칙연산(➕,➖,✖️,➗) 기능을 수행한 후 
 2) 결과 값을 반환하는 메서드와 연산 결과를 저장하는 컬렉션 타입 필드를 가진 Calculator 클래스를 생성
 
[2] App 클래스의 main 메서드에서 Calculator 클래스의 연산 결과를 저장하고 있는 컬렉션 필드에 직접 접근하지 못하도록 수정
* 간접 접근을 통해 필드에 접근하여 가져올 수 있도록 구현 (Getter 메서드)
* 간접 접근을 통해 필드에 접근하여 수정할 수 있도록 구현합니다. (Setter 메서드)

[3] Calculator 클래스에 저장된 연산 결과들 중 가장 먼저 저장된 데이터를 삭제하는 기능을 가진 메서드를 구현
App 클래스의 main 메서드에 삭제 메서드가 활용될 수 있도록 수정

▶︎ 기존코드

  • App.java (프로그램 실행 역할)
package com.example.calculator2;

import java.util.InputMismatchException;
import java.util.Scanner;

public class App {
    public static void main(String[] args) {
        /* Calculator 인스턴스 생성 */
        Calculator calculator = new Calculator();
        Scanner sc = new Scanner(System.in);

        while (true) {
            try {
                System.out.print("첫 번째 숫자를 입력하세요: ");
                int num1 = sc.nextInt();
                System.out.print("두 번째 숫자를 입력하세요: ");
                int num2 = sc.nextInt();
                sc.nextLine(); // nextInt() 입력 후 버퍼의 개행문자(\n) 제거
                System.out.print("사칙연산 기호를 입력하세요: ");
                char operator = sc.nextLine().charAt(0);

                /* 연산 수행 역할은 Calcuator 클래스가 담당 */
                int result = calculator.calculate(num1, num2, operator);

                System.out.println("결과 : " + result);
                System.out.println("더 계산하시겠습니까? (exit 입력 시 종료) ");
                System.out.print("(remove 입력 시 가장 오래된 결과 삭제): ");
                String command = sc.nextLine();
                if (command.equals("exit")) {
                    /* 반복문 종료 */
                    System.out.print("전체 연산 결과: ");
                    System.out.println(calculator.getResultQueue().toString());
                    return;
                } else if (command.equals("remove")) {
                    System.out.println("가장 오래된 연산 결과를 삭제합니다.");
                    calculator.resetResult();
                }
            } catch (InputMismatchException e) {
                System.out.println("잘못된 숫자 입력입니다.");
                sc.nextLine(); // nextInt() 입력 후 버퍼의 개행문자(\n) 제거
            }  catch (ArithmeticException | IllegalArgumentException e) {
                System.out.println(e.getMessage());
            }
        }
    }


}

▶︎ 개선사항

  • 기존코드의 아쉬운 점
  1. remove로 가장 오래된 연산 결과를 지운 후에 무조건 다음 계산을 진행
    : 결과를 지운 후 '프로그램을 종료하거나, 가장 오래된 연산 결과를 지우거나, 다음 계산을 진행하거나' 사용자가 선택할 수 있도록 수정
    → 🏁 플래그를 선언하여 분기처리, remove를 끝내면 사용자에게 다시 물어본다.

  2. 잘못된 입력으로 예외가 발생한 후, 계산을 다시 진행
    : 예외 발생 후 사용자가 다음 행동을 선택할 수 있도록 수정
    → 사용자가 메뉴를 입력하는 것은 계산의 성공과 실패여부에 상관없다. (finally 사용)

▶︎ 수정코드

  • AppRef.java (수정한 App 클래스)
package com.example.calculator2;

import java.util.InputMismatchException;
import java.util.Scanner;

/**
 * 필수기능 Lv2. 클래스를 적용해 기본적인 연산을 수행할 수 있는 계산기 만들기
 * <p>
 * Lv1에서 구현한 App 클래스의 메서드에 Calculator 클래스가 활용될 수 있도록 수정
 * 연산 수행 역할은 Calculator 클래스가 담당
 * 연산 결과는 Calculator 클래스의 연산 결과를 저장하는 필드에 저장
 * </p>
 * ref1) loopQuit 분기로 command 반복 수행: remove를 입력한 후 다시 exit, remove, 그 외 입력받기
 * ref2) finally : 계산 성공, 실패 여부와 상관 없이 사용자 입력(command) 실행
 */
public class AppRef {
    public static boolean loopQuit = false;
    public static void main(String[] args) {
        /* Calculator 인스턴스 생성 */
        Calculator calculator = new Calculator();
        Scanner sc = new Scanner(System.in);

        while (true) {
            try {
                loopQuit = false;
                System.out.print("첫 번째 숫자를 입력하세요: ");
                int num1 = sc.nextInt();
                System.out.print("두 번째 숫자를 입력하세요: ");
                int num2 = sc.nextInt();
                sc.nextLine(); // nextInt() 입력 후 버퍼의 개행문자(\n) 제거
                System.out.print("사칙연산 기호를 입력하세요: ");
                char operator = sc.nextLine().charAt(0);

                /* 연산 수행 역할은 Calcuator 클래스가 담당 */
                int result = calculator.calculate(num1, num2, operator);

                System.out.println("결과 : " + result);

            } catch (InputMismatchException e) {
                System.out.println("잘못된 숫자 입력입니다.");
                sc.nextLine(); // nextInt() 입력 후 버퍼의 개행문자(\n) 제거
            } catch (ArithmeticException | IllegalArgumentException e) {
                System.out.println(e.getMessage());
            } finally {
                // 사용자 메뉴: 계산 성공과 예외 발생에 상관 없이 수행되어야 하는 로직
                while(!loopQuit) {
                    System.out.println("더 계산하시겠습니까? (exit: 입력 시 종료 ");
                    System.out.println("remove: 가장 오래된 결과 삭제");
                    System.out.print("그 외: 프로그램을 계속 실행): ");
                    command(sc.nextLine(), calculator);
                }
            }
        }
    }

    public static void command(String input, Calculator calculator) {
        switch (input) {
            case "exit":
                System.out.print("전체 연산 결과: ");
                System.out.println(calculator.getResultQueue().toString());
                System.exit(0);
                break;
            case "remove":
                System.out.println("가장 오래된 연산 결과를 삭제합니다.");
                calculator.resetResult();
                loopQuit = false;
                break;
            default:
                loopQuit = true;
        }
    }
}

💭 예외처리 강의를 수강한 뒤 try-catch-finally 구문을 활용하여 계산기 과제를 개선할 수 있을 것 같아 적용해보았다. 실행해보니 리펙토링전보다 사용자 입장에서 편리한 프로그램이 되었다. (아직은 양의 정수 사칙연산밖에 못하지만...) 다음 과제를 진행하면서 자바를 더 자유자재로 구사할 수 있도록 공부해야겠다.

profile
안녕하세요 :)

0개의 댓글