https://github.com/euuns/CalculatorProject
프로젝트 수정 → 포스트 실시간 수정
Lv 1: 기본 사칙연산을 수행하는 일반 계산기
25-01-02
- 객체 지향 프로그래밍을 적용하지 않고 생성한 프로젝트
- 하나의 클래스에 여러 메서드를 생성해서 사용할 수 있다.
- + inputNumber(): int
입력한 숫자 반환 - + inputOperator(): String
입력한 연산자 반환 - + checkOperator(String): Boolean
사칙연산 입력 확인 - + getResult(int, int, String): int
연산 결과 반환 - + arithmeticError(): void
0으로 나누는 경우
- 가장 기본적인 절차지향 방법으로 작성하는 프로그램으로 구현하는데 어려움은 없었다. 필요한 기능 등 요구사항도 그냥 사칙연산을 계산하는 것 뿐이며, 0으로 나눌 때 에러가 나오지 않게 제어문을 추가하는 게 전부였다.
Lv 2: 객체를 활용한 계산
25-01-03
- 클래스로 나누어 프로젝트 작성. → 동작하는 클래스와 실행하는 main 구분
- Calculaotr이름으로 연산을 동작하는 클래스를 생성. main이 들어가는 클래스는 App
- 연산 클래스에서 사칙연산을 수행하고 결과를 반환한다.
- 사용한 필드는 Getter/Setter를 사용해 직접 접근할 수 없도록 한다.
- 결과를 하나의 리스트에 넣어 먼저 저장된 데이터를 먼저 삭제하는 메서드(FIFO) 구현
- 1레벨과 달라진 것은 실행과 동작을 나누는 것, 결과를 저장하고 삭제하는 메서드를 구현하는 것
private Queue<Integer> result = new LinkedList<>();
public Integer getResult(){
return result.peek();
}
public void setResult(int updateValue){
result.add(updateValue);
}
public void removeResult(){
result.poll();
}
- 사칙연산 동작은 1레벨과 같은 방식인 switch를 활용해 입력받은 연산자 String을 구분했다.
-result:Queue<Integer>
+calculate(int, int, String):int
+getFirstResult:Integer
+checkOperator(String):Boolean
+getResult():String
+removeResult():void
+arithmeticError():void
25-01-09 14:50
- 지금 확인하니 0으로 나누었을 때 제어하는 구문이 빠졌다. 레벨1의 기능을 모두 가지고 있는 채로 레벨2로 확장이 이루어져야 한다. 메서드를 추가하고 main에서 사용하는 방법을 변경하였다.
Lv 3: 객체 지향 특징을 적용해 여러 기능을 추가한 계산기
25-01-06
25-01-06 22:30
- enum 사용법을 정확히 모름
- ADD("+"), MULTI("*"), ....
- 잘못된 입력은 예외 처리
- 제대로 입력할 때까지 반복
- 추상클래스 - 연산 클래스
- Java 문법 종합반 4주차 과제 이용
- 입력 정보만 처리하는 클래스
- 문자열을 숫자, 연산자로 나누기
- 숫자는 firstNumber, secondNumber로 나누기
- Generic으로 +, - 등 기본 연산이 안 돼서 일단 int로 작성
25-01-07
25-01-07 10:00
계획
BiFunction
인터페이스를 활용하면Generic
타입의 연산 가능?Enum
에Lambda
를 활용해서 연산 정보와 계산을 한 클래스에 모아두기- 후위표기법을 이용하면 더 구체적인 연산이 가능하지 않을까 → 자료구조
25-01-07 14:02
진행
- 4주차 과제에서 가져와 사용했던
AbstractOperation
과 구현 클래스를 삭제 Enum
클래스가 상속받을 인터페이스Operation<T, U, R> - apply(T,U):R
생성Enum
에서 연산 처리Generic
타입 사용- 계산은 더 큰
Double
로 하고, 결과 출력 할 때 정수형이면int
→Number
- Number 타입으로 반환 →
ArithmeticCalculator.calculate:Number
- Enum클래스에서 apply를 오버라이딩 할 때 a + b 로 하는 걸 a + a로 하고 있었다. 매개변수를 a와 b 두개를 받았지만 ADD, SUBTRACT, MULTIPLY, DIVIDE에서 모두 a 와 a를 연산하고 있어서 내부 로직이 다른 줄 알았다. 오타에 주의
계획
- 문자열로 받았던 계산식에서 숫자와 연산자만 분류 → "."을 이용해 정수와 실수 분류
- '실수-실수', '실수-정수', '정수-정수': 제대로 계산되는지 동작 확인
- 입력받는 정보 InputInfo클래스 리팩터링
- 기능 분리
- 중복 코드 제거
- 입력 클래스 정리가 끝나면 후위표기법 구현
25-01-07 20:13
진행
InputInfo
는 입력에 대한 정보를 관리하고, 연산은 담당하지 않음.InputInfo
안에 있던Pattern
을 사용해 숫자와 연산자를 구분하는 메서드 →CheckValue.java
생성- 사용자가 입력한 정보를 후위표기법으로 변경하기 위한
Postfix.java
생성stack
을 이용해 입력받은 문자열 리스트를 중위표기에서 후위표기로 변경precedence()
메서드를 만들어 연산자는 우선순위 부여- 숫자는 stack에 push
- 연산자는 우선순위를 비교하여, 지금 입력할 연산자의 우선순위가 더 낮으면 제일 뒤로
formula.add(stack.pop())
→ 제일 뒤로 보내기 위해 앞에 있는 우선순위가 높은 연산자를 pop
- 입력 형태는 "12.5/6+3", "123*2/4+5.5" 처럼 정수와 실수로 이루어져 한 줄로 적은 식
- stack으로 postfix를 구현하기 위해 오랜만에 자료구조 책을 보았다.
symbol==")": print(pop(stack));
생각도 못한 괄호 연산으로 더 큰 우선순위를 고려해야 했다. !!수정 필요!! 일단 더하기, 빼기 보다 더 높은 곱하기, 나누기 우선순위를 먼저 해결했다. - 입력을 좀 더 깔끔하게 받기 위해 전체적으로 수정을 했다.
InputInfo
를 바꾸는 과정에서main이 있는 CalculatorApp
과 연산을 진행하는ArithmeticCalculator
모두 수정이 필요했다. 처음엔 CaclculatorApp에서 InputInfo만 사용했지만, InputInfo는 입력된 정보만 관리하도록 기능을 분리시켜 main에서는 InputInfo에 접근하지 못하게 됐다.- 만약 사용자가 직접 입력한 내용이 main에서 접근할 수 있으면 보안 문제가 생길 것이라 생각
- 숫자와 연산자를 따로따로 입력하는 건 개발자 입장에서 편한 방법이지만, 사용자 입장에서 불편할 거라고 생각했다. 사용자 입장에서 계산이 필요한 식을 한번에 입력하고, 그 정보를 받아올 수 있게 만들고 싶었다.
계획
- Lv3의 마지막 도전과제 ArithmeticCalculator에서 조회 메서드 구현
- Lambda & Stream 활용
- 괄호를 입력받았을 경우를 대비한 postfix 수정
25-01-08
25-01-08 12:20
진행
CheckValue.java
에PARENTHESES_REG = "[()]"
추가InputInfo.java
에서 괄호를 입력받을 수 있도록 수정Postifx.java
에서 괄호 연산 추가- 여는 괄호를 만나면, stack.push
- 닫는 괄호를 만나면, stack.peek이 여는 괄호가 나올 때까지 stack.pop
- stack에서 pop한 값은 후위 표기된 리스트 formula에 add
- 후위표기법은 표기식 그대로 우선순위가 적용되어 있어 괄호가 없어도 계산 가능 → 괄호는 formula.add연산 x
- 계산 테스트 - 계산식 입력: (3+5)*2.7/3 결과: 7.2 → True
- 괄호와 곱하기, 나누기에 따라 우선 연산 가능, 실수와 정수 연산 가능
계획
- Lambda와 Stream을 활용한 조회 메서드
- OOP와 SOLID를 이룰 수 있게 리팩터링
25-01-08 14:38
진행
- exit를 입력받을 때 까지 계산을 반복, 계산 결과는 Queue에 저장
- stream().filter()를 이용해 Queue에서 특정 값보다 큰 값을 List에 저장
- 비교할 값은 Scanner를 통해 받아온다.
- 도전과제를 모두 끝냈다. 도전 과제 외에 계산식을 한 줄로 입력받거나, 후위연산으로 변환, 곱하기와 나누기 함께 입력 시 우선 순위, 괄호를 사용한 계산을 추가했다.
- 검색을 하고 여러 시도와 디버깅을 통해 원하는 대로 동작이 되는 건 확인했지만 코드가 너무 복잡해 보인다. 특히나 InputInfo와 Postfix에서 for와 if가 여러번 중첩된다. 한 연산에서 while과 for문이, 그리고 이어지는 다음 연산에서 또 while, for가 여러번 들어가니 계산 시간이 느린 것 같다.
- 좀 더 효율적으로 구현할 수 있는 방법을 알아보자. 코드를 수정할 때 어떤 관점에서 봐야하는지 공부해야 할 것 같다.
계획
- TIL, ReadMe 수정
- 트러블슈팅 작성
25-01-09
25-01-09 16:20
진행
- 클래스 다이어그램 제작
- 2레벨에서 제외된 기능 다시 생성
- stack을 이용했던 부분을 Deque로 다시 구성
- ReadMe 작성
- 조금 더 효율적인 코드를 만들 수 있도록 공부하고 최종 수정을 진행해보자!!
PPT로 제작하려고 했는데 intelliJ에서 제공하는 이미지 파일을 저장했다 🤗
포함관계와 실체화관계가 같은 클래스끼리 두번이나 적용되고 있다(ArithmeticCalculator - InputInfo // ArithmeticCalculator - CalculatorApp)
25-01-10
25-01-10 09:50
- ArithmeticCalculator에서 CheckValue를 받아올 때 사용하는 필드에 넣어주었다.
- CalculatorApp에서도 ArithmeticCalculator를 main 안에 넣어주었다.
- 관계가 하나로 줄은 모습이 보였다.
- 하지만 InputInfo에 대해서는 처리할 방법이 없어 관계 정리를 하지 못 했다.
단순히 기능을 구현하기만 하고 끝날 게 아니라 효율적인 코드를 짜는 것을 평소에도 습관화 시키고 싶었다. 그러지 못한 것 같아 매우 아쉽지만, 3레벨을 막 구현했던 6일과 목적에 따라 기능을 분리했던 7일에서 도전이 도움이 되었다. 다음에는 구현 도중에 다른 기능을 추가하여 수정을 하는 것보다 처음부터 제대로 요구사항을 작성하고 설계를 하는 것이 더 좋을 것 같다.
'내일배움캠프' 카테고리의 다른 글
일정 관리를 위한 서버를 간단하게 만들어보자 (0) | 2025.01.24 |
---|---|
키오스크 프로젝트 개발 트러블 슈팅 정리 (0) | 2025.01.17 |
[TIL/WIL] 4주차 과제: 키오스크 만들기 (0) | 2025.01.14 |
스타터 노트 (1) | 2024.11.25 |
STEP 1. 시작하기 (0) | 2024.11.25 |