-
Notifications
You must be signed in to change notification settings - Fork 4
Hyunje #3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
HyunjeLee
wants to merge
13
commits into
LikeLion-Study:main
Choose a base branch
from
HyunjeLee:hyunje
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Hyunje #3
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
5255b65
docs: README.md 작성
HyunjeLee 33a318a
feat: Console 클래스 초기화
HyunjeLee 0c00d64
feat: readInput() 구현
HyunjeLee 96f54f9
refactor: printResult()의 시그니처 변경 (결과값 매개변수 추가)
HyunjeLee dda7b83
feat: printResult() 구현
HyunjeLee 27fa767
feat(Console.java): 에러 메세지 추가
HyunjeLee b2e910c
feat: Validator 클래스 구현
HyunjeLee 27cc1fc
feat: Calculator 클래스 구현
HyunjeLee 847f8e1
feat: Application 클래스 구현
HyunjeLee 445cbb5
test(ApplicationTest.java): Application 코드에 맞게 테스트코드 수정
HyunjeLee 9a04f07
test: ValidatorTest 작성
HyunjeLee 23212aa
refactor: 연산자 위치에 대한 메서드 및 에러메세지명 변경
HyunjeLee 0fd697c
test: CalculatorTest 작성
HyunjeLee File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,38 @@ | ||
| # Calculator | ||
|
|
||
| ## 📌 구현 기능 목록 | ||
|
|
||
| ### 입력받기 | ||
|
|
||
| "수식을 입력해주세요." ← 사용자에게 문구 출력 | ||
|
|
||
| 입력 받기 | ||
|
|
||
| ### 로직 | ||
|
|
||
| #### 입력 검사 | ||
|
|
||
| ##### 통과 | ||
|
|
||
| - 공백은 0 | ||
| - 연산방향은 왼쪽에서 오른쪽 | ||
| - (연산자 우선순위) | ||
|
|
||
| ##### 에러 | ||
|
|
||
| `IllegalArgumentException` | ||
|
|
||
| - 연속된 연산자 | ||
| - 타입 에러 | ||
|
|
||
|
|
||
|
|
||
| ### 출력 | ||
|
|
||
| #### 정상 출력 | ||
|
|
||
| "결과 : ?" | ||
|
|
||
| #### 에러 발생 | ||
|
|
||
| "[ERROR] 잘못된 수식입니다. 입력 형식을 확인해 주세요." |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,35 @@ | ||
| package calculator; | ||
|
|
||
| import java.util.ArrayList; | ||
|
|
||
| public class Application { | ||
|
|
||
| private static final Console console = new Console(); | ||
|
|
||
| public static void main(String[] args) { | ||
| // TODO: 코드 작성 | ||
| String inputString = console.readInput(); | ||
|
|
||
| run(inputString); | ||
| } | ||
|
|
||
| // 예시 코드 | ||
| public static int run(String inputString) { | ||
| Validator validator = new Validator(); | ||
| Calculator calculator = new Calculator(); | ||
| calculator.calculate(""); | ||
|
|
||
| ArrayList<String> inputArrayList; | ||
| int result = 0; | ||
|
|
||
| try { | ||
| inputArrayList = validator.divideInput(inputString); | ||
| result = calculator.calculate(inputArrayList); | ||
| } catch (IllegalStateException e) { | ||
| // 입력값이 공백값 또는 비어있는 경우 | ||
| } catch (IllegalArgumentException illegalArgumentException) { | ||
| System.out.println(illegalArgumentException.getMessage()); | ||
| return -1; | ||
| } | ||
|
|
||
| console.printResult(result); | ||
| return result; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,13 +1,55 @@ | ||
| package calculator; | ||
|
|
||
| /* | ||
| 1주차에만 제공되는 예시 코드입니다. | ||
| 코드는 그대로 사용해도 되고 수정해도 됩니다. | ||
| */ | ||
| import java.util.*; | ||
|
|
||
| // 연산 책임 | ||
| public class Calculator { | ||
| public int calculate(String input) { | ||
| // TODO: 코드 구현 | ||
| throw new IllegalArgumentException("아직 구현되지 않았습니다."); | ||
|
|
||
| private int result = 0; | ||
|
|
||
| public int calculate(ArrayList<String> inputArrayList) { | ||
|
|
||
| // 단일 원소인 경우 그대로 return | ||
| if (isSingleElement(inputArrayList)) { | ||
| return Integer.parseInt(inputArrayList.get(0)); | ||
| } | ||
|
|
||
| // 큐 선언 | ||
| LinkedList<String> stringQueue = toQueue(inputArrayList); | ||
|
|
||
| while (stringQueue.size() > 1) { | ||
|
|
||
| result = operate( | ||
| stringQueue.poll(), | ||
| stringQueue.poll(), | ||
| stringQueue.poll() | ||
| ); | ||
|
|
||
| stringQueue.addFirst(String.valueOf(result)); | ||
| } | ||
|
|
||
| return result; | ||
| } | ||
|
|
||
|
|
||
| private boolean isSingleElement(ArrayList<String> inputArrayList) { | ||
| return inputArrayList.size() == 1; | ||
| } | ||
|
|
||
| private LinkedList<String> toQueue(ArrayList<String> inputArrayList) { | ||
| return new LinkedList<>(inputArrayList); | ||
| } | ||
|
|
||
| private int operate(String num1String, String operator, String num2String) { | ||
| int num1 = Integer.parseInt(num1String); | ||
| int num2 = Integer.parseInt(num2String); | ||
|
|
||
| return switch (operator) { | ||
| case "+" -> num1 + num2; | ||
| case "-" -> num1 - num2; | ||
| case "*" -> num1 * num2; | ||
| case "/" -> num1 / num2; | ||
| default -> throw new IllegalStateException("Unexpected value: " + operator); | ||
| }; | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,26 @@ | ||
| package calculator; | ||
|
|
||
| import java.util.Scanner; | ||
|
|
||
| // TODO: SINGLETON? | ||
| // 입출력 책임 | ||
| public class Console { | ||
| private static final String MESSAGE_INPUT_GUIDE = "수식을 입력해주세요."; | ||
| private static final String MESSAGE_OUTPUT_FORMATTED = "결과 : %d"; | ||
|
|
||
| public static final String MESSAGE_ERROR_FORMAT = "[ERROR] 잘못된 수식입니다. 입력 형식을 확인해 주세요."; | ||
| public static final String MESSAGE_ERROR_WRONG_POSITION_OPERATORS = "[ERROR] 잘못된 연산자 위치입니다. 입력 형식을 확인해 주세요."; | ||
| public static final String MESSAGE_ERROR_EMPTY_OR_BLANK = "[ERROR] 입력값이 없거나 공백입니다. 입력 형식을 확인해 주세요."; | ||
|
|
||
|
|
||
| private static final Scanner scanner = new Scanner(System.in); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Console을 따로 만들어서 입출력을 담당해 책임 분리가 좋은 것 같아요. |
||
|
|
||
| public String readInput() { | ||
| System.out.println(MESSAGE_INPUT_GUIDE); | ||
| return scanner.nextLine(); | ||
| } | ||
|
|
||
| public void printResult(int result) { | ||
| System.out.println(String.format(MESSAGE_OUTPUT_FORMATTED, result)); | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| package calculator; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.Set; | ||
|
|
||
| // 검사 책임 | ||
|
|
||
| public class Validator { | ||
|
|
||
| // 검사를 위한 배열 생성 | ||
| private final ArrayList<String> inputArrayList = new ArrayList<>(); | ||
| // 검사를 위한 연산자 set | ||
| private static final Set<Character> OPERATORS = Set.of('+', '-', '*', '/'); | ||
|
|
||
| // 검사 이후 숫자와 연산자로 쪼개어 배열로 return | ||
| public ArrayList<String> divideInput(String input) { | ||
| String currentNumber = ""; | ||
|
|
||
| validateEmptyOrBlank(input); | ||
|
|
||
| for (int i = 0; i < input.length(); i++) { | ||
| char ch = input.charAt(i); | ||
|
|
||
| if (Character.isDigit(ch)) { | ||
| currentNumber += ch; | ||
|
|
||
| validateLastNumber(i, input.length() - 1, currentNumber); | ||
|
|
||
| } else if (OPERATORS.contains(ch)) { | ||
| validateOperatorPosition(currentNumber); | ||
|
|
||
| inputArrayList.add(currentNumber); | ||
| inputArrayList.add(String.valueOf(ch)); | ||
|
|
||
| currentNumber = ""; | ||
|
|
||
| } else { // 숫자나 문자열이 아닌 경우 | ||
| throw new IllegalArgumentException(Console.MESSAGE_ERROR_FORMAT); | ||
| } | ||
| } | ||
|
|
||
| return inputArrayList; | ||
| } | ||
|
|
||
| private void validateLastNumber(int position, int length, String currentNumber) { | ||
| if (position == length) { | ||
| inputArrayList.add(currentNumber); | ||
| } | ||
| } | ||
|
|
||
| private void validateEmptyOrBlank(String input) { | ||
| if (input.isBlank()) { | ||
| throw new IllegalStateException(Console.MESSAGE_ERROR_EMPTY_OR_BLANK); | ||
| } | ||
| } | ||
|
|
||
| private void validateOperatorPosition(String currentNumber) { | ||
| if (currentNumber.isEmpty()) { | ||
| throw new IllegalArgumentException(Console.MESSAGE_ERROR_WRONG_POSITION_OPERATORS); | ||
| } | ||
| } | ||
|
|
||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| package calculator; | ||
|
|
||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import java.util.ArrayList; | ||
| import java.util.List; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
|
||
| class CalculatorTest { | ||
|
|
||
| Calculator calculator = new Calculator(); | ||
|
|
||
| @Test | ||
| void calculate_test_single() { | ||
| ArrayList<String> input = new ArrayList<>(List.of("12")); | ||
| int result = calculator.calculate(input); | ||
|
|
||
| assertThat(result).isEqualTo(12); | ||
| } | ||
|
|
||
| @Test | ||
| void calculate_test_simple() { | ||
| ArrayList<String> input = new ArrayList<>(List.of("1", "+", "2")); | ||
| int result = calculator.calculate(input); | ||
|
|
||
| assertThat(result).isEqualTo(3); | ||
| } | ||
|
|
||
| @Test | ||
| void calculate_test_divide() { | ||
| ArrayList<String> input = new ArrayList<>(List.of("4", "/", "2")); | ||
| int result = calculator.calculate(input); | ||
|
|
||
| assertThat(result).isEqualTo(2); | ||
| } | ||
|
|
||
| @Test | ||
| void calculate_test_complex() { | ||
| ArrayList<String> input = new ArrayList<>(List.of("2", "+", "3", "*", "4")); | ||
| int result = calculator.calculate(input); | ||
|
|
||
| assertThat(result).isEqualTo(20); | ||
| } | ||
|
|
||
| @Test | ||
| void calculate_test_wrong_operator() { | ||
| ArrayList<String> input = new ArrayList<>(List.of("1", "&", "2")); | ||
|
|
||
| assertThrows(IllegalStateException.class, () -> calculator.calculate(input)); | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package calculator; | ||
|
|
||
| import org.junit.jupiter.api.Test; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import static org.assertj.core.api.Assertions.assertThat; | ||
| import static org.junit.jupiter.api.Assertions.assertThrows; | ||
|
|
||
| class ValidatorTest { | ||
|
|
||
| Validator validator = new Validator(); | ||
|
|
||
| @Test | ||
| void split_test() { | ||
| String input = "3+5*2"; | ||
| List<String> result = validator.divideInput(input); | ||
|
|
||
| assertThat(result).containsExactly("3", "+", "5", "*", "2"); | ||
| } | ||
|
|
||
| @Test | ||
| void exception_test_for_blank() { | ||
| String input = " "; | ||
| Exception e = assertThrows(IllegalStateException.class, () -> validator.divideInput(input)); | ||
|
|
||
| assertThat(e.getMessage()).isEqualTo(Console.MESSAGE_ERROR_EMPTY_OR_BLANK); | ||
| } | ||
|
|
||
| @Test | ||
| void exception_test_for_operators() { | ||
| String input = "3++2"; | ||
| Exception e = assertThrows(IllegalArgumentException.class, () -> validator.divideInput(input)); | ||
|
|
||
| assertThat(e.getMessage()).isEqualTo(Console.MESSAGE_ERROR_WRONG_POSITION_OPERATORS); | ||
| } | ||
|
|
||
| @Test | ||
| void exception_test_for_input_format() { | ||
| String input = "5+a"; | ||
| Exception e = assertThrows(IllegalArgumentException.class, () -> validator.divideInput(input)); | ||
|
|
||
| assertThat(e.getMessage()).isEqualTo(Console.MESSAGE_ERROR_FORMAT); | ||
| } | ||
|
|
||
| @Test | ||
| void exception_test_for_first_starts_with_operator() { | ||
| String input = "+12+3-5"; | ||
| Exception e = assertThrows(IllegalArgumentException.class, () -> validator.divideInput(input)); | ||
|
|
||
| assertThat(e.getMessage()).isEqualTo(Console.MESSAGE_ERROR_WRONG_POSITION_OPERATORS); | ||
|
|
||
| } | ||
|
|
||
| } |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Application 클래스가 프로그램의 진입점을 담당하는데, run 까지 넣으면 책임이 조금 과중된다 생각합니다!
ApplicationTest를 통합 테스트로 구현하고 싶어 하신 것 같은데, run 또한 객체이기 때문에 따로 분리하고 main 함수 호출을 통해 테스트를 진행하는 것이 조금 더 좋은 방향이라고 생각해요.
또한, run이 static으로 선언되었고, 다른 클래스를 의존성을 주입받는 것이 아니라 내부에 선언함으로써 유지보수 및 테스트가 어려워진다고 알고있어요.
예를 들어, 현재 calculator가 아닌 연산자 우선순위를 고려한 클래스를 따로 만든다면, 이를 의존성만 바꾸면 되는 것이 아닌 내부 코드를 바꿔야 합니다.
조금 길어졌지만 OOP의 SRP와 OCP에 대해 조금 찾아보시면 현제님이라면 금방 익숙해지실 것 같아요!