-
Notifications
You must be signed in to change notification settings - Fork 155
[4기 - 황준호] 1~2주차 과제: 계산기 구현 미션 제출합니다. #191
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
base: juno-junho
Are you sure you want to change the base?
Changes from all commits
cef4f6a
0e5168b
8b786c2
464ee7d
d681ef6
100652e
a152c5f
fcb46be
cdb0b84
747b790
9c5d63c
11f9b35
daaabb9
254d78b
021662f
07b941e
f78d702
04ecda0
a01be32
91358fc
e80fbfc
8b9fef4
faacd78
156e61b
5034d14
f8720b9
ea769f0
d7201e3
eb3763d
8e6ddbe
1cb190f
b1bc8a0
1882786
cab396b
ae83531
37fd625
a610665
c577dd7
c3b3acc
2b3fe4f
2847dc7
e0c42fa
8568748
bedc166
1681a69
f30f052
7026a94
c3469b0
f022143
bba7d3b
fe6b642
b2b4e92
0a1bcd1
49628f5
c422b59
c934956
52b4812
31d0c2b
c2c482a
7b07a10
23f5a67
3b4a132
69bf844
39d5517
64b690d
69bca5d
f2064c9
d5b9315
552bdd3
9df6088
a425b61
37b9706
e1bb1da
235f332
06518a6
665e715
4e39667
7e20296
500eddf
95d0f50
07d518b
64dae33
73da710
de9f0c1
988d8f8
0c6d27b
c210056
ff23b5e
d8beb05
9edbbd7
038ad39
3bd4249
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| .gradle | ||
| build/ | ||
| !gradle/wrapper/gradle-wrapper.jar | ||
| !**/src/main/**/build/ | ||
| !**/src/test/**/build/ | ||
| gradlew.bat | ||
| gradlew | ||
| gradle | ||
|
|
||
| ### IntelliJ IDEA ### | ||
| .idea | ||
| .idea/modules.xml | ||
| .idea/jarRepositories.xml | ||
| .idea/compiler.xml | ||
| .idea/libraries/ | ||
| *.iws | ||
| *.iml | ||
| *.ipr | ||
| out/ | ||
| !**/src/main/**/out/ | ||
| !**/src/test/**/out/ | ||
|
|
||
| ### Eclipse ### | ||
| .apt_generated | ||
| .classpath | ||
| .factorypath | ||
| .project | ||
| .settings | ||
| .springBeans | ||
| .sts4-cache | ||
| bin/ | ||
| !**/src/main/**/bin/ | ||
| !**/src/test/**/bin/ | ||
|
|
||
| ### NetBeans ### | ||
| /nbproject/private/ | ||
| /nbbuild/ | ||
| /dist/ | ||
| /nbdist/ | ||
| /.nb-gradle/ | ||
|
|
||
| ### VS Code ### | ||
| .vscode/ | ||
|
|
||
| ### Mac OS ### | ||
| .DS_Store |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,100 @@ | ||
|
|
||
| ## 자바 계산기 구현 미션 기능목록 작성 | ||
|
|
||
| 동작 예시 | ||
| ``` | ||
| 1. 조회 | ||
| 2. 계산 | ||
|
|
||
| 선택 : 2 | ||
|
|
||
| 1 + 2 | ||
| 3 | ||
|
|
||
| 1. 조회 | ||
| 2. 계산 | ||
|
|
||
| 선택 : 2 | ||
|
|
||
| 1 + 2 * 3 | ||
| 7 | ||
|
|
||
| 1. 조회 | ||
| 2. 계산 | ||
|
|
||
| 선택 : 1 | ||
|
|
||
| 1 + 2 = 3 | ||
| 1 + 2 * 3 = 7 | ||
|
|
||
| 선택 : 2 | ||
|
|
||
| 3 - 2 * 2 | ||
| -1 | ||
| ``` | ||
|
|
||
| - [x] 입력 | ||
| - [x] Scanner를 통한 콘솔 입력 | ||
| - [x] 선택 값 입력 받기 | ||
| - [x] 계산 기능 선택 시 -> 식 입력 받기 | ||
| - [x] BufferedReader로 입력 받는 것 교체 / 확장 가능 하게 추상화 시키기 (OCP) | ||
| - [x] 출력 | ||
| - [x] 조회 기능 선택 시 -> 조회 시 넘겨 받은 결과값 출력하기 | ||
| - [x] 계산 기능 선택 시 -> 계산 후 계산한 결과 출력하기 | ||
| - [x] OutputView 추상화 시키기 | ||
|
|
||
| - [x] 컨트롤러 및 application 생성 | ||
| - 컨트롤러 역할 : view와 domain을 이어 준다 / repository에서 값을 가져온다. | ||
| - 컨트롤러에서 담당 : repository를 결정한다 | ||
| - view는 주입 받는다(사용자가 결정) | ||
| - 게임을 실행하는 `run()`메서드를 가진다. | ||
| - Application 클래스 역할 : 사용자 | ||
| - 컨트롤러를 실행한다. | ||
| - view 객체를 생성해 컨트롤러에 주입시킨다. | ||
|
|
||
| - [x] 조회 기능 구현 | ||
| - [x] 조회시 계산한 값이 없으면 `계산 값이 존재하지 않습니다` 메세지 출력 -> OutputView에서 담당 | ||
| - [x] 계산 후 이력을 List로 저장 -> Repository에서 생성 | ||
| - [x] repository 패키지 안 List 가진 일급 컬렉션으로 구현 | ||
| - [x] 인터페이스로 repository 추상화 | ||
| - [x] 조회 기능 선택 시 계산 이력을 List에서 가져 오기 (repository에서 controller로 직접적으로 가져오기) | ||
|
|
||
|
|
||
| - [x] 계산 기능 구현 | ||
| - [x] 덧셈 | ||
| - [x] 뺄셈 | ||
| - [x] 나눗셈 | ||
| - [x] 곱하기 | ||
| - [x] 우선순위 (사칙연산) | ||
| - [x] 후위 표기식 찾아보기 | ||
| - [x] 나눗셈과 곱셈이 덧셈과 뺄셈보다 우선순위가 높다 | ||
| ``` | ||
| 중위 표현식 -> 후위 표현식 전환 알고리즘 : | ||
| 1. 피연산자는 스택에 넣지 않고 그냥 출력한다. | ||
| 2. 연산자는 스택이 비었으면 스택에 push한다. | ||
| 3. 연산자는 스택이 비어있지 않으면 스택에 있는 연산자와의 우선순위를 비교해 스택에 있는 연산자의 우선순위가 같거나 크다면 스택에 있는 연산자를 pop을 한 후 출력하고 현재 연산자는 스택에 push한다. | ||
| 4. 만약 3번에서 우선순위가 현재 연산자가 더 크면 현재 연산자를 push한다.(스택에서 pop하지 않음) | ||
| 5. 수식이 끝나면 스택이 빌 때 까지 pop을 한 후 출력한다. | ||
|
|
||
| 후위 표현식 -> 계산 알고리즘 | ||
| 1. 피연산자면 스택에 push한다. | ||
| 2. 연산자를 만나면 pop을 두번하고 각각 값을 저장한 후, 연산자에 맞는 계산을 한다. | ||
| 3. 계산을 한 뒤, 결과 값은 다시 스택에 넣는다. 이 과정을 수식이 끝날 때 까지 반복한다. | ||
| 4. 수식이 끝났다면 스택에 마지막 남은 값이 결과 값이 된다. | ||
| ``` | ||
| - [x] 식을 입력 받을 때 계산기에서 수행가능한 연산 범위를 제한 할 수 있다. | ||
| - [x] Regex를 통해서 검증하기. | ||
| - [x] 중위표현식, 후위 표현식에 따른 계산 확장 가능성 기능 구현 | ||
|
|
||
| - [x] 정규식 문제 해결 => \\ 추가해서 해설 | ||
| - [x] 0으로 나눌 경우 문제 해결 | ||
| - [x] var 사용 x -> 정확히 타입 표기를 통한 명시성 증가ㅈ | ||
|
|
||
| - [x] 예외 처리 | ||
| - [x] 조회(1), 계산(2) 이외의 값을 입력 했을 경우 `IllegalArgumentException` 발생 -> controller에서 처리 | ||
| - [x] 형식 (숫자 + 공백 + 기호 + 공백 + 숫자 + 공백 + 기호 + ...)이 잘못된 경우 `IllegalArgumentException` 발생 | ||
| - 공백은 무조건 하나로 처리 -> split시 space 하나로 처리해야 자를 수 있음. split 특성상 delimiter 포함 하지를 못한다. | ||
| - 정규식으로 처리 | ||
| - [x] 식에 int 형 범위 벗어 나 있는 경우 `IllegalArgumentException` 발생 | ||
| - [x] 계산 과정에 있어 int 자료형 overflow / underflow 발생 시 `IllegalArgumentException` 발생 | ||
| - Math 클래스의 `~Exact()` 메서드 사용 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| plugins { | ||
| id 'java' | ||
| } | ||
|
|
||
| group = 'com.programmers' | ||
| version = '1.0-SNAPSHOT' | ||
|
|
||
| repositories { | ||
| mavenCentral() | ||
| } | ||
|
|
||
| dependencies { | ||
| testImplementation 'org.assertj:assertj-core:3.22.0' | ||
| testImplementation platform('org.junit:junit-bom:5.9.1') | ||
| testImplementation 'org.junit.jupiter:junit-jupiter' | ||
| } | ||
|
|
||
| test { | ||
| useJUnitPlatform() | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| rootProject.name = 'java-calculator' |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,15 @@ | ||
| package com.programmers.blackdog; | ||
|
|
||
| import com.programmers.blackdog.controller.CalculatorController; | ||
| import com.programmers.blackdog.view.*; | ||
|
|
||
| public class Application { | ||
| public static void main(String[] args) { | ||
| InputView inputView = new ScannerInputView(); | ||
| OutputView outputView = new PrintStreamOutputView(); | ||
| Console console = new Console(inputView, outputView); | ||
|
|
||
| CalculatorController calculator = new CalculatorController(console); | ||
| calculator.run(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| package com.programmers.blackdog.controller; | ||
|
|
||
| import com.programmers.blackdog.controller.constant.Selection; | ||
| import com.programmers.blackdog.service.CalculatorService; | ||
| import com.programmers.blackdog.service.Service; | ||
| import com.programmers.blackdog.view.Console; | ||
|
|
||
| import java.util.List; | ||
|
|
||
| import static com.programmers.blackdog.controller.constant.Selection.findByCode; | ||
|
|
||
| public class CalculatorController { | ||
|
|
||
| private final Service service; | ||
| private final Console console; | ||
|
|
||
| public CalculatorController(Console console) { | ||
| this.console = console; | ||
| this.service = new CalculatorService(); | ||
|
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. 이 Service는 왜 주입을 안받고 직접 생성하시는지 이유가 궁금합니다. |
||
| } | ||
|
|
||
| public void run() { | ||
| while (true) { | ||
| try { | ||
| switch (getCode()) { | ||
| case CHECK_DATA: | ||
| printAllPreviousData(); | ||
| break; | ||
| case CALCULATE: | ||
| printCalculatedResultAndSave(); | ||
| break; | ||
| case EXIT: | ||
| exitProgram(); | ||
| return; | ||
| } | ||
| } catch (Exception e) { | ||
|
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. 혹시 왜 매우 넓은 범위의 Exception을 통째로 catch하신지 이유가 궁금합니다. |
||
| console.printErrorMessage(e.getMessage()); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| private Selection getCode() { | ||
|
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. getCode() 보다는 조금더 명확한 의미가 좋을거같아요. 일반적으로 저는 get을 프로퍼티나 필드의 값을 가져올때 사용합니다. 사용자로부터 입력을 받아온다면? |
||
| int selectionCode = console.getSelectionCode(); | ||
| return findByCode(selectionCode); | ||
| } | ||
|
|
||
|
|
||
| private void printAllPreviousData() { | ||
| List<String> calculatedData = service.findAll(); | ||
| console.printExpressions(calculatedData); | ||
| } | ||
|
Comment on lines
+48
to
+51
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. 데이터라고 �명명하는 것은 메소드 기준에서는 다소 추상적인것 같아요. 데이터가 어떤 데이턴지 구현명을 붙이는건 어떨까요? 이 코드 내에서 데이터가 아닌 부분이 없듯이 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. 지역변수명도 동일합니당 |
||
|
|
||
| private void printCalculatedResultAndSave() { | ||
| String expression = console.getExpression(); | ||
| int result = service.calculate(expression); | ||
|
|
||
| service.save(expression, result); | ||
|
|
||
| console.printCalculatedResult(result); | ||
| } | ||
|
|
||
| private void exitProgram() { | ||
| console.printEndMessage(); | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,20 @@ | ||
| package com.programmers.blackdog.controller.constant; | ||
|
|
||
| import java.util.Arrays; | ||
|
|
||
| public enum Selection { | ||
| CHECK_DATA(1), CALCULATE(2), EXIT(3); | ||
|
|
||
| private final int code; | ||
|
|
||
| Selection(int code) { | ||
| this.code = code; | ||
| } | ||
|
|
||
| public static Selection findByCode(int code) { | ||
| return Arrays.stream(Selection.values()) | ||
| .filter(selection -> selection.code == code) | ||
| .findAny() | ||
| .orElseThrow(() -> new IllegalArgumentException("해당 값이 없습니다")); | ||
|
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. 해당 값이 없다기보다 |
||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| package com.programmers.blackdog.domain; | ||
|
|
||
| import java.util.Arrays; | ||
|
|
||
| public enum ArithmeticOperators implements Operable { | ||
| ADDITION("+", 0) { | ||
| @Override | ||
| public int apply(int a, int b) { | ||
| return Math.addExact(a, b); | ||
| } | ||
| }, SUBTRACTION("-", 0) { | ||
| @Override | ||
| public int apply(int a, int b) { | ||
| return Math.subtractExact(a, b); | ||
| } | ||
| }, MULTIPLICATION("*", 1) { | ||
| @Override | ||
| public int apply(int a, int b) { | ||
| return Math.multiplyExact(a, b); | ||
| } | ||
| }, DIVISION("/", 1) { | ||
| @Override | ||
| public int apply(int a, int b) { | ||
| validateDivideNumIsZero(b); | ||
| return a / b; | ||
| } | ||
| }; | ||
|
|
||
| private static void validateDivideNumIsZero(int num) { | ||
| if (num == 0) { | ||
| throw new ArithmeticException("0으로 나눌 수 없습니다."); | ||
| } | ||
| } | ||
|
|
||
| private final String operator; | ||
| private final int priority; | ||
|
|
||
| ArithmeticOperators(String operator, int priority) { | ||
| this.operator = operator; | ||
| this.priority = priority; | ||
|
|
||
|
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. 공백 지우면 깔끔할거같아요~ |
||
| } | ||
|
|
||
| public static ArithmeticOperators convertTokenToOperator(String token) { | ||
| return Arrays.stream(values()) | ||
| .filter(operator -> operator.getOperator().equals(token)) | ||
| .findAny() | ||
| .orElseThrow(); | ||
|
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. 메시지를 같이 전달해주면 친절할거 같습니다. |
||
| } | ||
|
|
||
| public static boolean isNotOperator(String token) { | ||
| return Arrays.stream(values()) | ||
| .noneMatch(operator -> operator.getOperator().equals(token)); | ||
| } | ||
|
|
||
| public String getOperator() { | ||
| return operator; | ||
| } | ||
|
|
||
| public int getPriority() { | ||
| return priority; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| package com.programmers.blackdog.domain; | ||
|
|
||
| @FunctionalInterface | ||
| public interface Operable { | ||
|
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. good int만 지원되는건 아쉽네요. 다른 방법이 있지 않을까요? 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. i think so too. |
||
| int apply(int a, int b); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| package com.programmers.blackdog.domain; | ||
|
|
||
| import java.util.Arrays; | ||
| import java.util.stream.Collectors; | ||
|
|
||
| import static com.programmers.blackdog.domain.ArithmeticOperators.values; | ||
|
|
||
| public class RegexGenerator { | ||
|
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. 무엇을 하는 클래스인가요? |
||
|
|
||
| private static final String REGEX_PREFIX = "^\\d+\\s(["; | ||
| private static final String REGEX_SUFFIX = "]\\s\\d+\\s)+$"; | ||
| public static final String PREFIX = "\\"; | ||
| public static final String SUFFIX = ""; | ||
|
|
||
| public String generateWithOperator(ArithmeticOperators... arithmeticOperators) { | ||
|
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. ArithmeticOperators... 는 동작할 때 어떤 차이가 있을까요? |
||
| StringBuilder operators = new StringBuilder(); | ||
| for (ArithmeticOperators arithmeticOperator : arithmeticOperators) { | ||
| operators.append(PREFIX).append(arithmeticOperator.getOperator()); | ||
| } | ||
| return REGEX_PREFIX + operators.append(REGEX_SUFFIX); | ||
| } | ||
|
|
||
| public String generateWithAllOperator() { | ||
| String allOperators = Arrays.stream(values()) | ||
| .map(ArithmeticOperators::getOperator) | ||
| .collect(Collectors.joining(PREFIX, PREFIX, SUFFIX)); | ||
| return REGEX_PREFIX + allOperators + REGEX_SUFFIX; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| package com.programmers.blackdog.domain.calculator; | ||
|
|
||
| import com.programmers.blackdog.domain.expression.Expression; | ||
|
|
||
| public interface AbstractCalculator { | ||
| int calculate(Expression expression); | ||
|
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. 계산 결과가 int만 지원되는건 아쉽네요! 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. 계산 결과가 단순 int value로 리턴되기보다 객체로 바라볼 순 없을까요? |
||
| } | ||
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.
MVC 패턴과 Layered 아키텍처로 설계하신거 같아요!
Controller는 어떤 역할을 할까요? 준호님의 생각이 궁금합니다.