From 1f3473b05849f6561e32215ed0c46d41d3f1e6c4 Mon Sep 17 00:00:00 2001 From: Jaemin Kim Date: Tue, 25 Jan 2022 22:36:34 +0900 Subject: [PATCH 1/7] commit test --- README.md | 26 +------------------------- 1 file changed, 1 insertion(+), 25 deletions(-) diff --git a/README.md b/README.md index 8fe7112..77597e4 100644 --- a/README.md +++ b/README.md @@ -1,26 +1,2 @@ -## [NEXTSTEP 플레이그라운드의 미션 진행 과정](https://github.com/next-step/nextstep-docs/blob/master/playground/README.md) +# 문자열 계산기 ---- -## 학습 효과를 높이기 위해 추천하는 미션 진행 방법 - ---- -1. 피드백 강의 전까지 미션 진행 -> 피드백 강의 전까지 혼자 힘으로 미션 진행. 미션을 진행하면서 하나의 작업이 끝날 때 마다 add, commit -> 예를 들어 다음 숫자 야구 게임의 경우 0, 1, 2단계까지 구현을 완료한 후 push - -![mission baseball](https://raw.githubusercontent.com/next-step/nextstep-docs/master/playground/images/mission_baseball.png) - ---- -2. 피드백 앞 단계까지 미션 구현을 완료한 후 피드백 강의를 학습한다. - ---- -3. Git 브랜치를 master 또는 main으로 변경한 후 피드백을 반영하기 위한 새로운 브랜치를 생성한 후 처음부터 다시 미션 구현을 도전한다. - -``` -git branch -a // 모든 로컬 브랜치 확인 -git checkout master // 기본 브랜치가 master인 경우 -git checkout main // 기본 브랜치가 main인 경우 - -git checkout -b 브랜치이름 -ex) git checkout -b apply-feedback -``` From 8ce571571d2a55d9f84f1a04c718ae12b2192ca9 Mon Sep 17 00:00:00 2001 From: Jaemin Kim Date: Fri, 28 Jan 2022 20:35:16 +0900 Subject: [PATCH 2/7] =?UTF-8?q?=EB=AC=B8=EC=9E=90=EC=97=B4=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=EA=B8=B0=20=EA=B5=AC=ED=98=84=20=EC=99=84=EB=A3=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 26 ++++++++ src/main/java/.gitkeep | 0 src/main/java/step1/Calculator.java | 50 +++++++++++++++ src/main/java/step1/CalculatorResource.java | 64 +++++++++++++++++++ src/main/java/step1/Print.java | 14 ++++ src/main/java/step1/main.java | 11 ++++ .../java/step1/CalculatorResourceTest.java | 48 ++++++++++++++ src/test/java/step1/CalculatorTest.java | 29 +++++++++ src/test/java/study/StringTest.java | 13 ---- 9 files changed, 242 insertions(+), 13 deletions(-) delete mode 100644 src/main/java/.gitkeep create mode 100644 src/main/java/step1/Calculator.java create mode 100644 src/main/java/step1/CalculatorResource.java create mode 100644 src/main/java/step1/Print.java create mode 100644 src/main/java/step1/main.java create mode 100644 src/test/java/step1/CalculatorResourceTest.java create mode 100644 src/test/java/step1/CalculatorTest.java delete mode 100644 src/test/java/study/StringTest.java diff --git a/README.md b/README.md index 77597e4..b5987b0 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,28 @@ # 문자열 계산기 +--- +## 기능 요구 사항 + +1. 문자열 입력받기 + 1. main에서 수동을 입력 + 2. 문자 분리 + 3. 숫자 분리 + 4. 연산자 분리 + +2. 계산하기 + 1. 연산기호 확인하여 앞, 뒤 숫자 계산 + +3. 출력하기 + + +--- +## 야구게임에서 받은 피드백 메모 + +- 적절한 객체를 도출하여 객체지향적 구현을 고민해 볼 것 +- 핵심 로직과 UI 로직 분리하여 구현 +- indent depth를 1로 맞출 것(메서드 분리 활용) +- 객체는 상태와 기능을 모두 가질 것 +- 파일 저장시 마지막줄 개행 옵션 체크 +- 의미없는 공백 두지 말 것 +- 지역변수 초기화 시 가급적 inline 사용 +- 불필요한 주석 달지 말 것 diff --git a/src/main/java/.gitkeep b/src/main/java/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/src/main/java/step1/Calculator.java b/src/main/java/step1/Calculator.java new file mode 100644 index 0000000..49b35ec --- /dev/null +++ b/src/main/java/step1/Calculator.java @@ -0,0 +1,50 @@ +package step1; + +import java.util.List; + +public class Calculator { + + private CalculatorResource calculatorResource; + + public Calculator(String stringCalculatorSentence) { + this.calculatorResource = new CalculatorResource(stringCalculatorSentence); + } + + public int calculate() { + + List numberList = calculatorResource.getNumberArray(); + List operatorList = calculatorResource.getOperatorArray(); + + int operatorListIndex = 0; + int result = 0; + + for (int i = 1; i < numberList.size(); i++) { + + result = calcualteInit(numberList, result, i); + + result = getResult(numberList, operatorList, operatorListIndex, result, i); + operatorListIndex++; + } + return result; + } + + private int calcualteInit(List numberList, int result, int i) { + if (i == 1) { + result = (numberList.get(i - 1)); + } + return result; + } + + private int getResult(List numberList, List operatorList, int operatorListIndex, int result, int i) { + if (operatorList.get(operatorListIndex).equals("+")) { + result = result + (numberList.get(i)); + } else if (operatorList.get(operatorListIndex).equals("-")) { + result = result - (numberList.get(i)); + } else if (operatorList.get(operatorListIndex).equals("*")) { + result = result * (numberList.get(i)); + } else if (operatorList.get(operatorListIndex).equals("/")) { + result = result / (numberList.get(i)); + } + return result; + } +} diff --git a/src/main/java/step1/CalculatorResource.java b/src/main/java/step1/CalculatorResource.java new file mode 100644 index 0000000..414ebca --- /dev/null +++ b/src/main/java/step1/CalculatorResource.java @@ -0,0 +1,64 @@ +package step1; + +import java.util.ArrayList; +import java.util.List; + +public class CalculatorResource { + + private String sentence; + private String[] sentenceArray; + private List numberArray; + private List operatorArray; + + public List getNumberArray() { + return numberArray; + } + + public List getOperatorArray() { + return operatorArray; + } + + public CalculatorResource(String sentence) { + this.sentence = sentence; + splitSentence(); + creatNumberList(); + creatOperatorList(); + } + + private void splitSentence() { + this.sentenceArray = this.sentence.split(" "); + } + + public void creatNumberList() { + this.numberArray = new ArrayList<>(); + + for (String s : sentenceArray) { + char numberCheck = s.charAt(0); + validateNumber(numberArray, s, numberCheck); + } + this.numberArray = numberArray; + } + + private void validateNumber(List numberArray, String s, char numberCheck) { + if (numberCheck > 48 && numberCheck < 58) { + this.numberArray.add(Integer.parseInt(s)); + } + } + + public void creatOperatorList() { + this.operatorArray = new ArrayList<>(); + + for (String s : sentenceArray) { + char operatorCheck = s.charAt(0); + validateOperator(operatorArray, s, operatorCheck); + } + } + + private void validateOperator(List operatorArray, String s, char operatorCheck) { + if (operatorCheck < 48 || operatorCheck > 58) { + this.operatorArray.add(s); + } + } + + +} diff --git a/src/main/java/step1/Print.java b/src/main/java/step1/Print.java new file mode 100644 index 0000000..4079eec --- /dev/null +++ b/src/main/java/step1/Print.java @@ -0,0 +1,14 @@ +package step1; + +public class Print { + + private int calculateResult; + + public Print(int calculateResult) { + this.calculateResult = calculateResult; + } + + public void printResult() { + System.out.println("calculateResult = " + calculateResult); + } +} diff --git a/src/main/java/step1/main.java b/src/main/java/step1/main.java new file mode 100644 index 0000000..159a29a --- /dev/null +++ b/src/main/java/step1/main.java @@ -0,0 +1,11 @@ +package step1; + +public class main { + + public static void main(String[] args) { + String stringCalculatorSentence = "1 * 2 - 3 + 4 * 5"; + Calculator calculator = new Calculator(stringCalculatorSentence); + Print print = new Print(calculator.calculate()); + print.printResult(); + } +} diff --git a/src/test/java/step1/CalculatorResourceTest.java b/src/test/java/step1/CalculatorResourceTest.java new file mode 100644 index 0000000..6b1de5f --- /dev/null +++ b/src/test/java/step1/CalculatorResourceTest.java @@ -0,0 +1,48 @@ +package step1; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +class CalculatorResourceTest { + + @Test + @DisplayName("빈칸으로 구분된 문자열을 받아 숫자만 반환하는 테스트") + void creatNumberListTest() throws Exception { + + // given + String sentence = "51 + 2 + 100"; + CalculatorResource calculatorResource = new CalculatorResource(sentence); + + // when + List numberList = calculatorResource.getNumberArray(); + + // then + List expectList = new ArrayList(Arrays.asList(51, 2, 100)); + Assertions.assertThat(numberList).isEqualTo(expectList); + + } + + @Test + @DisplayName("빈칸으로 구분된 문자열을 받아 연산자만 반환하는 테스트") + void creatOperatorList() { + + // given + String sentence = "1 + 2 - 3 * 100 / 5"; + CalculatorResource calculatorResource = new CalculatorResource(sentence); + + // when + List operatorList = calculatorResource.getOperatorArray(); + + // then + List expectList = new ArrayList(Arrays.asList("+", "-" , "*" , "/")); + Assertions.assertThat(operatorList).isEqualTo(expectList); + } +} diff --git a/src/test/java/step1/CalculatorTest.java b/src/test/java/step1/CalculatorTest.java new file mode 100644 index 0000000..f759c21 --- /dev/null +++ b/src/test/java/step1/CalculatorTest.java @@ -0,0 +1,29 @@ +package step1; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.jupiter.api.Assertions.*; + +class CalculatorTest { + + @Test + @DisplayName("숫자 리스트와 연산자 리스트로 계산을 실행하는 테스트") + void calculateTest () throws Exception{ + + // given + String sentence = "1 + 2 + 3 - 6 * 100 + 5 / 5"; + + // when + Calculator calculator = new Calculator(sentence); + int result = calculator.calculate(); + + // then + Assertions.assertThat(result).isEqualTo(1); + } +} diff --git a/src/test/java/study/StringTest.java b/src/test/java/study/StringTest.java deleted file mode 100644 index 43e47d9..0000000 --- a/src/test/java/study/StringTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package study; - -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -public class StringTest { - @Test - void replace() { - String actual = "abc".replace("b", "d"); - assertThat(actual).isEqualTo("adc"); - } -} From d5c24e8bc94e044946f39d9c5193d83d63262f90 Mon Sep 17 00:00:00 2001 From: Jaemin Kim Date: Mon, 14 Feb 2022 17:40:13 +0900 Subject: [PATCH 3/7] =?UTF-8?q?FEAT:=20=EC=97=B0=EC=82=B0=EC=9E=90?= =?UTF-8?q?=EB=A5=BC=20=EC=B0=BE=EA=B3=A0,=20=EB=91=90=20=EC=A0=95?= =?UTF-8?q?=EC=88=98=EC=9D=98=20=EC=97=B0=EC=82=B0=EC=9D=84=20=EB=8B=B4?= =?UTF-8?q?=EB=8B=B9=ED=95=98=EB=8A=94=20Operator=20Enum=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 ++-- .../casepractice/calculator/Operator.java | 30 ++++ src/main/java/step1/{main.java => Main.java} | 2 +- src/main/java/step2/Operator.java | 37 +++++ src/test/java/step2/OperatorTest.java | 155 ++++++++++++++++++ 5 files changed, 241 insertions(+), 12 deletions(-) create mode 100644 src/main/java/casepractice/calculator/Operator.java rename src/main/java/step1/{main.java => Main.java} (93%) create mode 100644 src/main/java/step2/Operator.java create mode 100644 src/test/java/step2/OperatorTest.java diff --git a/README.md b/README.md index b5987b0..99f2753 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,26 @@ -# 문자열 계산기 +# 문자열 계산기 2번째 구현 --- -## 기능 요구 사항 +## step2. 기능 요구 사항 -1. 문자열 입력받기 - 1. main에서 수동을 입력 - 2. 문자 분리 - 3. 숫자 분리 - 4. 연산자 분리 - -2. 계산하기 - 1. 연산기호 확인하여 앞, 뒤 숫자 계산 +1. 연산자(Operator) +- [X] 연산자 기호에 해당하는 연산 담당 객체를 찾아 반환한다. +- [X] 연산자 객체에 두 정수가 전달되면 계산 결과를 반환한다. -3. 출력하기 +2. 계산기(Calculator) +- [] 여러개의 연산자 객체와 정수들의 전체 계산 결과를 반환한다. +3. 계산 내용 준비(PrepareCalculationContents) +- [] 문자열 타입의 수식을 받아, 계산기가 사용할 수 있는 형태로 데이터를 가공하여 반환한다. + +4. 계산기 프로그램 화면(CalculatorDisplay) +- [] 안내에 따라 문자열 수식을 입력하면, 계산 결과를 반환한다. 실제 계산은 내부적으로 다른 객체의 도움을 받는다. + +5. 프로그램 실행 장치(Main) +- [] 계산기 프로그램을 실행한다 --- + ## 야구게임에서 받은 피드백 메모 - 적절한 객체를 도출하여 객체지향적 구현을 고민해 볼 것 @@ -26,3 +31,5 @@ - 의미없는 공백 두지 말 것 - 지역변수 초기화 시 가급적 inline 사용 - 불필요한 주석 달지 말 것 + + --- diff --git a/src/main/java/casepractice/calculator/Operator.java b/src/main/java/casepractice/calculator/Operator.java new file mode 100644 index 0000000..f2b17ac --- /dev/null +++ b/src/main/java/casepractice/calculator/Operator.java @@ -0,0 +1,30 @@ +package casepractice.calculator; + +import java.util.Arrays; +import java.util.function.IntBinaryOperator; + +public enum Operator { + SUM("+", Integer::sum), + SUBTRACTION("-", (a, b) -> a - b), + MULTIPLICATION("*", (a, b) -> a * b), + DIVISION("/", (a, b) -> a / b); + + private final String symbol; + private final IntBinaryOperator calculation; + + Operator(String symbol, IntBinaryOperator calculation) { + this.symbol = symbol; + this.calculation = calculation; + } + + static Operator from(String symbol) { + return Arrays.stream(Operator.values()) + .filter(operator -> symbol.equals(operator.symbol)) + .findFirst() + .orElseThrow(IllegalArgumentException::new); + } + + public int calculate(int a, int b) { + return calculation.applyAsInt(a, b); + } +} diff --git a/src/main/java/step1/main.java b/src/main/java/step1/Main.java similarity index 93% rename from src/main/java/step1/main.java rename to src/main/java/step1/Main.java index 159a29a..71d0933 100644 --- a/src/main/java/step1/main.java +++ b/src/main/java/step1/Main.java @@ -1,6 +1,6 @@ package step1; -public class main { +public class Main { public static void main(String[] args) { String stringCalculatorSentence = "1 * 2 - 3 + 4 * 5"; diff --git a/src/main/java/step2/Operator.java b/src/main/java/step2/Operator.java new file mode 100644 index 0000000..0ed7214 --- /dev/null +++ b/src/main/java/step2/Operator.java @@ -0,0 +1,37 @@ +package step2; + +import java.util.function.BiFunction; + +import static java.util.Arrays.stream; + +public enum Operator { + + SUM("+", (a, b) -> a + b), + SUBTRACTION("-", (a, b) -> a - b), + MULTIPLICATION("*", (a, b) -> a * b), + DIVISION("/", (a, b) -> a / b); + + // 4개의 enum 객체는 operatorSymbol에 따라 서로 다른 연산 로직을 수행한다. + private final String operatorSymbol; + private final BiFunction biFunction; // 두 개의 Integer 타입을 받아 Integer 타입을 반환 + + // 4개의 enum 객체 생성자 + Operator(String operatorSymbol, BiFunction biFunction) { + this.operatorSymbol = operatorSymbol; + this.biFunction = biFunction; + } + + // enum 객체가 가지고 있는 BiFunction 인터페이스 구현 로직에 따라 계산 결과를 반환한다. + public int calculate(int a, int b) { + return this.biFunction.apply(a,b); + } + + // 문자 형태의 연산자를 operatorSymbol로 가지고 있는 enum 객체를 찾아 반환한다. + static Operator matchOperator(String symbol) { + return stream(Operator.values()) // Operator의 모든 값을 순환한다. + .filter(operator -> symbol.equals(operator.operatorSymbol))// 파라미터로 넘어온 symbol과 enum 객체의 operatorSymbol이 일치하면 통과 + .findFirst() // enum 객체를 찾으면 반환한다. + .orElseThrow(IllegalArgumentException::new); // 일치하는 객체가 없다면 예외 발생 + } + +} diff --git a/src/test/java/step2/OperatorTest.java b/src/test/java/step2/OperatorTest.java new file mode 100644 index 0000000..7659fb3 --- /dev/null +++ b/src/test/java/step2/OperatorTest.java @@ -0,0 +1,155 @@ +package step2; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +// BDD 테스트 코드 작성 패턴 +// Describe : 테스트 대상을 명사로 작성 +// Context : ~인 경우, ~ 할 때, 만약 ~ 한다면과 같이 상황 또는 조건을 기술한다 +// It : 위에서 명사로 작성한 테스트 대상의 행동을 ~이다, ~한다, ~를 갖는다 등으로 작성한다 +@DisplayName(" Operator 클래스 동작 시나리오 테스트") +class OperatorTest { + + @Nested // 테스트 클래스의 하위 구조로 선언한다 + @DisplayName("Describe: matchOperator 메소드는") + class Describe_matchOperator { + + // subject를 이용해 테스트 대상이 되는 메서드를 분리한다. + // 문자 타입의 operatorSymbol을 받아, 일치하는 enum 객체를 반환한다. + Operator subject(String symbol) { + return Operator.matchOperator(symbol); + } + + @Nested + @DisplayName("Context: + 문자열이 파라미터로 넘어올 경우") + class Context_with_add_symbol { + + @Test + @DisplayName("It: SUM을 반환한다") + void it_returns_a_sum() { + assertThat(subject("+")).isEqualTo(Operator.SUM); + } + } + + @Nested + @DisplayName("Context: - 문자열이 파라미터로 넘어올 경우") + class Context_with_subtraction_symbol { + @Test + @DisplayName("It: SUBTRACTION을 반환한다") + void it_returns_a_subtraction() { + assertThat(subject("-")).isEqualTo(Operator.SUBTRACTION); + } + } + + @Nested + @DisplayName("Context: * 문자열이 파라미터로 넘어올 경우") + class Context_with_multiplication_symbol { + @Test + @DisplayName("It: MULTIPLICATION을 반환한다") + void it_returns_a_multiplication() { + assertThat(subject("*")).isEqualTo(Operator.MULTIPLICATION); + } + } + + @Nested + @DisplayName("Context: / 문자열이 파라미터로 넘어올 경우") + class Context_with_division_symbol { + @Test + @DisplayName("It: DIVISION을 반환한다") + void it_returns_a_division() { + assertThat(subject("/")).isEqualTo(Operator.DIVISION); + } + } + + @Nested + @DisplayName("Context: 파라미터로 넘어온 문자와 일치하는 operatorSymbol이 없을 경우") + class Context_with_other_symbol { + @ParameterizedTest // 메서드 파라미터에 여러개의 인수를 전달하는 방식으로 테스트 진행 + @ValueSource(strings = {",", ":"}) // 메서드 실행 당 파라미터로 인수(argument)를 하나씩 전달 + @DisplayName("It: 예외가 발생한다.") + void it_throws_exception(String symbol) { + assertThrows(IllegalArgumentException.class, () -> { + subject(symbol); + }); + } + } + } + + @Nested + @DisplayName("Describe: calculate 메소드는") + class Describe_calculate { + private int a, b; + + // 임의의 테스트 값 세팅 + @BeforeEach + void prepareNumbers() { + a = 10; + b = 5; + } + + // subject를 이용해 테스트 대상이 되는 메서드를 분리한다. + // Enum 객체와 두 수를 받아 계산 결과를 반환한다. + int subject(Operator operator, int a, int b) { + return operator.calculate(a, b); + } + + @Nested + @DisplayName("Context: 덧셈을 담당하는 SUM이 두 정수 a와 b를 받을 경우") + class Context_with_add_and_numbers { + @Test + @DisplayName("It: a+b의 결과를 반환한다") + void it_returns_a_sum() { + assertThat(subject(Operator.SUM, a, b)).isEqualTo(15); + } + } + + @Nested + @DisplayName("Context: 뺄셈을 담당하는 SUBTRACTION이 두 정수 a와 b를 받을 경우") + class Context_with_subtract_and_numbers { + @Test + @DisplayName("It: a-b의 결과를 반환한다") + void it_returns_a_subtraction() { + assertThat(subject(Operator.SUBTRACTION, a, b)).isEqualTo(5); + } + } + + @Nested + @DisplayName("Context: 곱셈을 담당하는 SUBTRACTION이 두 정수 a와 b를 받을 경우") + class Context_with_multiply_and_numbers { + @Test + @DisplayName("It: a*b의 결과를 반환한다") + void it_returns_a_multiplication() { + assertThat(subject(Operator.MULTIPLICATION, a, b)).isEqualTo(50); + } + } + + @Nested + @DisplayName("Context: 나눗셈을 담당하는 DIVISION이 두 정수 a와 b를 받을 경우") + class Context_with_divide_and_numbers { + @Test + @DisplayName("It: a/b의 결과를 반환하고, 나머지 있을 경우 생략한다.") + void it_returns_a_division() { + assertThat(subject(Operator.DIVISION, a, b)).isEqualTo(2); + } + } + + @Nested + @DisplayName("Context: 나눗셈을 담당하는 DIVISION이 받은 수에 0이 있을 경우") + class Context_with_divide_and_numbers_with_zero { + @Test + @DisplayName("It: ArithmeticException 예외가 발생한다") + void it_throws_exception() { + assertThrows(ArithmeticException.class, () -> { + subject(Operator.DIVISION, 0, 0); + }); + } + } + } +} From 9f7d37bb5a267657ee016321a2c33759e42a0d80 Mon Sep 17 00:00:00 2001 From: Jaemin Kim Date: Mon, 14 Feb 2022 18:36:01 +0900 Subject: [PATCH 4/7] =?UTF-8?q?FEAT:=20=EA=B3=84=EC=82=B0=EC=9D=98=20?= =?UTF-8?q?=EC=9E=AC=EB=A3=8C=EA=B0=80=20=EB=90=98=EB=8A=94=20=EC=88=AB?= =?UTF-8?q?=EC=9E=90=EC=99=80=20=EC=97=B0=EC=82=B0=EC=9E=90=EB=A5=BC=20?= =?UTF-8?q?=EB=84=98=EA=B8=B0=EB=A9=B4=20=EC=A0=84=EC=B2=B4=20=EA=B3=84?= =?UTF-8?q?=EC=82=B0=20=EA=B2=B0=EA=B3=BC=EB=A5=BC=20=EB=B0=98=ED=99=98?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EA=B3=84=EC=82=B0=EA=B8=B0=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 +- src/main/java/step2/Calculator.java | 55 +++++++++++++ src/test/java/step2/CalculatorTest.java | 104 ++++++++++++++++++++++++ 3 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 src/main/java/step2/Calculator.java create mode 100644 src/test/java/step2/CalculatorTest.java diff --git a/README.md b/README.md index 99f2753..b47461b 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ # 문자열 계산기 2번째 구현 --- -## step2. 기능 요구 사항 +## step2. 기능 요구 맟 구현 순서 1. 연산자(Operator) - [X] 연산자 기호에 해당하는 연산 담당 객체를 찾아 반환한다. - [X] 연산자 객체에 두 정수가 전달되면 계산 결과를 반환한다. 2. 계산기(Calculator) -- [] 여러개의 연산자 객체와 정수들의 전체 계산 결과를 반환한다. +- [X] 여러개의 연산자 객체와 정수를 받아 전체 계산 결과를 반환한다. 3. 계산 내용 준비(PrepareCalculationContents) - [] 문자열 타입의 수식을 받아, 계산기가 사용할 수 있는 형태로 데이터를 가공하여 반환한다. diff --git a/src/main/java/step2/Calculator.java b/src/main/java/step2/Calculator.java new file mode 100644 index 0000000..f741d2c --- /dev/null +++ b/src/main/java/step2/Calculator.java @@ -0,0 +1,55 @@ +package step2; + +import java.util.Collections; +import java.util.List; + +public class Calculator { + + private static final int NUMBERS_MIN_SIZE = 2; + private static final int OPERATORS_MIN_SIZE = 1; + private static final int NUMBERS_AND_OPERATORS_INTERVAL = 1; + + private final List numbers; // 숫자만 모아놓은 List + private final List operators; // 연산자만 모아놓은 List + + // 계산기 인스턴스는 생성자를 이용해 계산의 재료가 되는 숫자와 연산자 모음을 필수로 전달 받는다. + public Calculator(List numbers, List operators) { + validateMinSize(numbers, operators); // 연산에 필요한 최소 조건을 검증 + validateFormat(numbers, operators); // 연산자의 갯수가 숫자의 갯수보다 1개 작은지 검증 + this.numbers = Collections.unmodifiableList(numbers); // Read-Only 처리하여 필드로 넘긴다. + this.operators = Collections.unmodifiableList(operators); // Read-Only 처리하여 필드로 넘긴다. + } + + // 계산을 수행할 수 있는 정수와 연산자의 최소 조건(갯수) 검증 + private void validateMinSize(List numbers, List operators) { + if (numbers.size() < NUMBERS_MIN_SIZE) { + // 계산의 대상이 되는 숫자가 2개보다 작을 경우 예외 발생 + throw new IllegalArgumentException(String.format("방정식의 숫자의 수는 %d개 이상이어야 합니다.", NUMBERS_MIN_SIZE)); + } + + if (operators.size() < OPERATORS_MIN_SIZE) { + // 계산에 사용되는 연산자가 없을 경우 예외 발생 + throw new IllegalArgumentException(String.format("방정식의 연산자의 수는 %d개 이상이어야 합니다.", OPERATORS_MIN_SIZE)); + } + } + + // 숫자와 연산자의 갯수 차이를 통해 정상적인 계산이 가능한지 검증 + private void validateFormat(List numbers, List operators) { + int interval = numbers.size() - operators.size(); + if (interval != NUMBERS_AND_OPERATORS_INTERVAL) { + // (숫자 - 연산자)의 수가 1이 아닐 경우 예외 발생 + throw new IllegalArgumentException("방정식의 올바른 형식이 아닙니다."); + } + } + + // Calculator 클래스가 상태로 가지고 있는 숫자와 연산자의 통합 계산을 수행하고, 결과를 반환한다. + public int calculate() { + int result = numbers.get(0); // 첫번째 숫자를 result에 넣어 계산 초기값을 준비한다 + for (int i = 0; i < operators.size(); i++) { // 연산자의 갯수만큼 연산을 반복한다 + Operator operator = operators.get(i);// 순차적으로 연산자 enum 객체를 찾는다 + Integer number = numbers.get(i + 1); // 연산의 대상이 되는 숫자를 number에 셋팅한다 + result = operator.calculate(result, number); // 두 수를 계산하여 중간 계산 결과를 result에 담는다 + } + return result; + } +} diff --git a/src/test/java/step2/CalculatorTest.java b/src/test/java/step2/CalculatorTest.java new file mode 100644 index 0000000..6e802f4 --- /dev/null +++ b/src/test/java/step2/CalculatorTest.java @@ -0,0 +1,104 @@ +package step2; + +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +// BDD 테스트 코드 작성 패턴 +// Describe : 테스트 대상을 명사로 작성 +// Context : ~인 경우, ~ 할 때, 만약 ~ 한다면과 같이 상황 또는 조건을 기술한다 +// It : 위에서 명사로 작성한 테스트 대상의 행동을 ~이다, ~한다, ~를 갖는다 등으로 작성한다 +@DisplayName("Calculator 클래스 동작 시나리오 테스트") +class CalculatorTest { + + @Nested + @DisplayName("Describe: Calculator 생성자는") + class Describe_constructor { + + // subject를 이용해 테스트 대상이 되는 메서드를 분리한다. + // Calculator 생성자는 숫자와 연산자 모음을 받아, 상태로 가지고 있는 인스턴스를 만든다. + private Calculator subject(List numbers, List operators) { + return new Calculator(numbers, operators); + } + + @Nested + @DisplayName("Context: 최소 두 개의 숫자와 하나의 연산자가 넘어올 경우") + class Context_two_number_and_one_operator { + @Test + @DisplayName("It: 계산기 객체를 반환한다.") + void it_returns_a_equation() { + assertNotNull(subject(Arrays.asList(1, 2), Arrays.asList(Operator.SUM))); + assertThat(subject(Arrays.asList(1, 2), Arrays.asList(Operator.SUM))).isInstanceOf(Calculator.class); + } + } + + @Nested + @DisplayName("Context: 한 개의 숫자와 한 개의 연산자만 넘어올 경우") + class Context_one_number { + @Test + @DisplayName("It: 예외가 발생한다") + void it_throws_exception() { + assertThrows(IllegalArgumentException.class, () -> { + subject(Collections.singletonList(1), Collections.singletonList(Operator.SUM)); + }); + } + } + + @Nested + @DisplayName("Context: 연산자가 넘어오지 않을 경우") + class Context_empty_operator { + @Test + @DisplayName("It: 예외가 발생한다") + void it_throws_exception() { + assertThrows(IllegalArgumentException.class, () -> { + subject(Arrays.asList(1, 2), Collections.emptyList()); + }); + } + } + + @Nested + @DisplayName("Context: 숫자 모음과 연산자 모음의 갯수 차이가 1이 아닐 경우") + class Context_wrong_format { + @Test + @DisplayName("It: 예외가 발생한다") + void it_throws_exception() { + assertThrows(IllegalArgumentException.class, () -> { + subject(Arrays.asList(1, 2, 3), Collections.singletonList(Operator.SUM)); + }); + } + } + } + + @Nested + @DisplayName("Describe: calculate 메소드는") + class Describe_calculate { + + // subject를 이용해 테스트 대상이 되는 메서드를 분리한다. + // Calculator 인스턴스의 calculate()를 실행한다. + private int subject(List numbers, List operators) { + Calculator calculator = new Calculator(numbers, operators); + return calculator.calculate(); + } + + @Nested + @DisplayName("Context: 정상적인 숫자 List와 연산자 List가 필드에 있을 경우") + class Context_with_numbers_and_operators { + + @Test + @DisplayName("It: calculator를 이용해 전체 계산 결과를 반환한다") + void it_returns_a_result() { + int calculateResult = subject(Arrays.asList(1, 2, 3), Arrays.asList(Operator.SUM, Operator.DIVISION)); + assertThat(calculateResult).isEqualTo(1); + } + } + } +} + + From 3a6065f9e1c902ba2f94669550d977b32895689e Mon Sep 17 00:00:00 2001 From: Jaemin Kim Date: Mon, 14 Feb 2022 18:57:43 +0900 Subject: [PATCH 5/7] =?UTF-8?q?FEAT:=EA=B3=84=EC=82=B0=EA=B8=B0=EC=9D=98?= =?UTF-8?q?=20=EA=B3=84=EC=82=B0=20=EC=9E=AC=EB=A3=8C=EB=A5=BC=20=EC=A4=80?= =?UTF-8?q?=EB=B9=84=ED=95=B4=EC=A3=BC=EA=B3=A0,=20=EA=B3=84=EC=82=B0?= =?UTF-8?q?=EA=B8=B0=20=EA=B0=9D=EC=B2=B4=EB=A5=BC=20=EB=A7=8C=EB=93=A4?= =?UTF-8?q?=EC=96=B4=20=EC=A0=84=EB=8B=AC=ED=95=98=EB=8A=94=20PrepareCalcu?= =?UTF-8?q?lationContents=20=ED=81=B4=EB=9E=98=EC=8A=A4=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 3 +- .../step2/PrepareCalculationContents.java | 41 +++++++++++++++++ src/test/java/step2/OperatorTest.java | 2 +- .../step2/PrepareCalculationContentsTest.java | 46 +++++++++++++++++++ 4 files changed, 90 insertions(+), 2 deletions(-) create mode 100644 src/main/java/step2/PrepareCalculationContents.java create mode 100644 src/test/java/step2/PrepareCalculationContentsTest.java diff --git a/README.md b/README.md index b47461b..9dab34c 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,8 @@ - [X] 여러개의 연산자 객체와 정수를 받아 전체 계산 결과를 반환한다. 3. 계산 내용 준비(PrepareCalculationContents) -- [] 문자열 타입의 수식을 받아, 계산기가 사용할 수 있는 형태로 데이터를 가공하여 반환한다. +- [X] 문자열 타입의 수식을 받아, 계산기가 사용할 수 있는 형태로 데이터를 가공하여 반환한다. +- [X] 계산기 객체를 반환한다. 4. 계산기 프로그램 화면(CalculatorDisplay) - [] 안내에 따라 문자열 수식을 입력하면, 계산 결과를 반환한다. 실제 계산은 내부적으로 다른 객체의 도움을 받는다. diff --git a/src/main/java/step2/PrepareCalculationContents.java b/src/main/java/step2/PrepareCalculationContents.java new file mode 100644 index 0000000..572a37f --- /dev/null +++ b/src/main/java/step2/PrepareCalculationContents.java @@ -0,0 +1,41 @@ +package step2; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; + +public class PrepareCalculationContents { + private static final String SEPARATOR = " "; // 문자열 분리의 기준이 되는 상수(공백) + private static final int INTERVAL = 2; // 문자 배열에서 숫자와 연산자의 위치가 구분되는 인덱스 간격 + + // 계산 재료를 준비하는 메서드: 문자열을 수식을 숫자 List와 연산자 List로 분리하고, 계산기 객체를 생성한다. + public Calculator create(String stringExpression) { + List strings = Arrays.asList(stringExpression.split(SEPARATOR));// Arrays.asList()는 Arrays의 private 정적 클래스인 ArrayList를 리턴 + List numbers = createNumbers(strings); // 문자열 수식에서 숫자 부분을 분리한다 + List operators = createOperators(strings); // 문자열 수식에서 연산자 부분을 분리한다. + return new Calculator(numbers, operators); // 숫자와 연산자 List 이용해 방정식 객체를 만든다 + } + + // 문자열의 짝수 위치 문자를 이용해 숫자 List를 만드는 메서드 + private List createNumbers(List strings) { + List evenPositions = new ArrayList<>(); // 문자열 수식에서 짝수에 해당하는 숫자를 분리한다 + for (int i = 0; i < strings.size(); i = i + INTERVAL) { + // INTERVAL 상수를 이용해 문자열 수식의 짝수만 담는다. + evenPositions.add(strings.get(i)); + } + return evenPositions.stream() // 짝수 위치에 해당하는 숫자 List 전체를 순환한다 + .map(Integer::valueOf) // 문자를 숫자로 변환한 stream을 반환 + .collect(Collectors.toList()); // 변환된 숫자들을 List로 모은다 + } + // 문자열의 홀수 위치 문자를 이용해 연산자 List를 만드는 메서드 + private List createOperators(List strings) { + List oddPositions = new ArrayList<>(); // 홀수 문자열을 담을 List + for (int i = 1; i < strings.size(); i = i + INTERVAL) { + oddPositions.add(strings.get(i)); // 홀수 위치에 해당하는 문자만 담는다. + } + return oddPositions.stream()// 홀수 문자를 순환한다. + .map(Operator::matchOperator) // matchOperator를 참조하여 연산자기호가 일치하는 Enum 객체를 찾아 반환한다 + .collect(Collectors.toList()); // 반환되는 enum 객체를 List로 담는다 + } +} diff --git a/src/test/java/step2/OperatorTest.java b/src/test/java/step2/OperatorTest.java index 7659fb3..902b25e 100644 --- a/src/test/java/step2/OperatorTest.java +++ b/src/test/java/step2/OperatorTest.java @@ -14,7 +14,7 @@ // Describe : 테스트 대상을 명사로 작성 // Context : ~인 경우, ~ 할 때, 만약 ~ 한다면과 같이 상황 또는 조건을 기술한다 // It : 위에서 명사로 작성한 테스트 대상의 행동을 ~이다, ~한다, ~를 갖는다 등으로 작성한다 -@DisplayName(" Operator 클래스 동작 시나리오 테스트") +@DisplayName("Operator 클래스 동작 시나리오 테스트") class OperatorTest { @Nested // 테스트 클래스의 하위 구조로 선언한다 diff --git a/src/test/java/step2/PrepareCalculationContentsTest.java b/src/test/java/step2/PrepareCalculationContentsTest.java new file mode 100644 index 0000000..41849a4 --- /dev/null +++ b/src/test/java/step2/PrepareCalculationContentsTest.java @@ -0,0 +1,46 @@ +package step2; + +import org.assertj.core.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +@DisplayName("PrepareCalculationContentsTest 클래스 동작 시나리오 테스트") +class PrepareCalculationContentsTest { + + @Nested // 테스트 클래스의 하위 구조로 선언한다 + @DisplayName("Describe: create 메소드는") + class Describe_constructor { + + // subject를 이용해 테스트 대상이 되는 메서드를 분리한다. + // create()는 문자열 식을 숫자와 연산자로 가공하고, 전체 계산을 담당하는 Calculator 객체를 반환한다. + private Calculator subject(String stringExpression) { + return new PrepareCalculationContents().create(stringExpression); + } + + @Nested // 테스트 클래스의 하위 구조로 선언한다 + @DisplayName("Context: 규격에 맞는 방정식 문자열이 주어진다면") + class Context_right_input { + @Test + @DisplayName("It: 계산기 객체를 반환한다") + void it_returns_a_equation() { + assertNotNull(subject("1 + 2 / 3 + 5")); + Assertions.assertThat(subject("1 + 2 / 3 + 5")).isInstanceOf(Calculator.class); + } + } + + @Nested + @DisplayName("Context: 규격에 맞지 않는 방정식 문자열이 주어진다면") + class Context_wrong_input { + @Test + @DisplayName("It: 예외가 발생한다") + void it_throws_exception() { + assertThrows(IllegalArgumentException.class, () -> { + subject(" 1 ! 2 - 3"); + }); + } + } + } +} From ebac18efd805d8b0cb2b49c339b0cc3e4bcf084e Mon Sep 17 00:00:00 2001 From: Jaemin Kim Date: Mon, 14 Feb 2022 19:41:54 +0900 Subject: [PATCH 6/7] =?UTF-8?q?FEAT:=20=EA=B3=84=EC=82=B0=EA=B8=B0=20?= =?UTF-8?q?=EC=A1=B0=EC=9E=91=EC=9D=84=20=ED=95=A0=20=EC=88=98=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=EA=B3=84=EC=82=B0=EA=B8=B0=20=ED=99=94=EB=A9=B4=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=EC=99=80=20=ED=94=84=EB=A1=9C?= =?UTF-8?q?=EA=B7=B8=EB=9E=A8=20=EC=8B=A4=ED=96=89=EC=9A=A9=20main=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- src/main/java/step2/CalculatePreparator.java | 5 +++ src/main/java/step2/CalculatorDisplay.java | 35 ++++++++++++++++++ src/main/java/step2/Main.java | 10 ++++++ ...ts.java => StringCalculatePreparator.java} | 2 +- .../java/step2/CalculatorDisplayTest.java | 36 +++++++++++++++++++ .../step2/PrepareCalculationContentsTest.java | 2 +- 7 files changed, 89 insertions(+), 3 deletions(-) create mode 100644 src/main/java/step2/CalculatePreparator.java create mode 100644 src/main/java/step2/CalculatorDisplay.java create mode 100644 src/main/java/step2/Main.java rename src/main/java/step2/{PrepareCalculationContents.java => StringCalculatePreparator.java} (97%) create mode 100644 src/test/java/step2/CalculatorDisplayTest.java diff --git a/README.md b/README.md index 9dab34c..e9f2a20 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ - [X] 계산기 객체를 반환한다. 4. 계산기 프로그램 화면(CalculatorDisplay) -- [] 안내에 따라 문자열 수식을 입력하면, 계산 결과를 반환한다. 실제 계산은 내부적으로 다른 객체의 도움을 받는다. +- [X] 안내에 따라 문자열 수식을 입력하면, 계산 결과를 반환한다. 실제 계산은 내부적으로 다른 객체의 도움을 받는다. 5. 프로그램 실행 장치(Main) - [] 계산기 프로그램을 실행한다 diff --git a/src/main/java/step2/CalculatePreparator.java b/src/main/java/step2/CalculatePreparator.java new file mode 100644 index 0000000..0ff609a --- /dev/null +++ b/src/main/java/step2/CalculatePreparator.java @@ -0,0 +1,5 @@ +package step2; + +public interface CalculatePreparator { + Calculator create(String stringExpression); +} diff --git a/src/main/java/step2/CalculatorDisplay.java b/src/main/java/step2/CalculatorDisplay.java new file mode 100644 index 0000000..7a33b9f --- /dev/null +++ b/src/main/java/step2/CalculatorDisplay.java @@ -0,0 +1,35 @@ +package step2; + +import java.util.Scanner; + +public class CalculatorDisplay { + + private final CalculatePreparator calculatePreparator; + + + // 계산기 재료를 준비해주는 인터페이스를 의존 관계로 받는다. + // 구현체를 변경하는 방식으로 계산기 기능을 다르게 사용할 수 있다. + public CalculatorDisplay(CalculatePreparator calculatePreparator) { + this.calculatePreparator = calculatePreparator; + + } + + // 양식에 맞는 문자열 수식을 넣으면 전체 계산 결과를 반환한다 + // test + private int calculate(String userInputExpression) { + Calculator calculator = calculatePreparator.create(userInputExpression); // 계산 준비 객체에서 계산기 객체를 만든다. + return calculator.calculate(); // 계산기 객체가 계산 결과를 반환한다. + } + + public int calculateForTest(String userInputExpression) { + Calculator calculator = calculatePreparator.create(userInputExpression); // 계산 준비 객체에서 계산기 객체를 만든다. + return calculator.calculate(); // 계산기 객체가 계산 결과를 반환한다. + } + + public void displayConsole() { + Scanner scanner = new Scanner(System.in); + System.out.println("문자열 계산식을 입력하면 계산 결과를 반환합니다."); + int calculateResult = calculate(scanner.nextLine()); + System.out.println("calculateResult = " + calculateResult); + } +} diff --git a/src/main/java/step2/Main.java b/src/main/java/step2/Main.java new file mode 100644 index 0000000..1191f3c --- /dev/null +++ b/src/main/java/step2/Main.java @@ -0,0 +1,10 @@ +package step2; + +public class Main { + + // 프로그램 실행 + public static void main(String[] args) { + CalculatorDisplay calculatorDisplay = new CalculatorDisplay(new StringCalculatePreparator()); + calculatorDisplay.displayConsole(); + } +} diff --git a/src/main/java/step2/PrepareCalculationContents.java b/src/main/java/step2/StringCalculatePreparator.java similarity index 97% rename from src/main/java/step2/PrepareCalculationContents.java rename to src/main/java/step2/StringCalculatePreparator.java index 572a37f..00e1fd1 100644 --- a/src/main/java/step2/PrepareCalculationContents.java +++ b/src/main/java/step2/StringCalculatePreparator.java @@ -5,7 +5,7 @@ import java.util.List; import java.util.stream.Collectors; -public class PrepareCalculationContents { +public class StringCalculatePreparator implements CalculatePreparator { private static final String SEPARATOR = " "; // 문자열 분리의 기준이 되는 상수(공백) private static final int INTERVAL = 2; // 문자 배열에서 숫자와 연산자의 위치가 구분되는 인덱스 간격 diff --git a/src/test/java/step2/CalculatorDisplayTest.java b/src/test/java/step2/CalculatorDisplayTest.java new file mode 100644 index 0000000..9904f6e --- /dev/null +++ b/src/test/java/step2/CalculatorDisplayTest.java @@ -0,0 +1,36 @@ +package step2; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.*; + +@DisplayName("CalculatorDisplay 클래스 동작 시나리오 테스트") +class CalculatorDisplayTest { + + @Nested + @DisplayName("Describe: calculate 메소드는") + class Describe_calculate { + + // subject를 이용해 테스트 대상이 되는 메서드를 분리한다. + // 계산기 준비 장치를 의존 관계로 주입받은 CalculatorDisplay 객체를 반환한다. + private int subject(String stringExpression) { + CalculatorDisplay calculatorDisplay = new CalculatorDisplay(new StringCalculatePreparator()); + return calculatorDisplay.calculateForTest(stringExpression); + } + + @Nested + @DisplayName("Context: 문자열 방정식이 주어진다면") + class Context_with_input { + @Test + @DisplayName("It: 계산 결과를 반환한다") + void it_returns_a_result() { + assertThat(subject("2 + 3 * 4 / 2")).isEqualTo(10); + } + } + + } +} diff --git a/src/test/java/step2/PrepareCalculationContentsTest.java b/src/test/java/step2/PrepareCalculationContentsTest.java index 41849a4..09cfd6b 100644 --- a/src/test/java/step2/PrepareCalculationContentsTest.java +++ b/src/test/java/step2/PrepareCalculationContentsTest.java @@ -17,7 +17,7 @@ class Describe_constructor { // subject를 이용해 테스트 대상이 되는 메서드를 분리한다. // create()는 문자열 식을 숫자와 연산자로 가공하고, 전체 계산을 담당하는 Calculator 객체를 반환한다. private Calculator subject(String stringExpression) { - return new PrepareCalculationContents().create(stringExpression); + return new StringCalculatePreparator().create(stringExpression); } @Nested // 테스트 클래스의 하위 구조로 선언한다 From 66cee3888d969c5246a6c88b41850fd9bdbe0f00 Mon Sep 17 00:00:00 2001 From: Jaemin Kim Date: Mon, 14 Feb 2022 19:47:33 +0900 Subject: [PATCH 7/7] =?UTF-8?q?STYLE:=20=EB=A7=88=EC=A7=80=EB=A7=89=20?= =?UTF-8?q?=EC=A4=84=20=ED=95=9C=EC=A4=84=20=EB=9D=84=EA=B8=B0=20=ED=99=95?= =?UTF-8?q?=EC=9D=B8=20=EB=B0=8F=20=EC=A0=84=EC=B2=B4=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=20=EC=A0=95=EB=A0=AC=20=ED=99=95=EC=9D=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/step2/CalculatePreparator.java | 1 + src/main/java/step2/Calculator.java | 1 + src/main/java/step2/CalculatorDisplay.java | 3 ++- src/main/java/step2/Main.java | 1 + src/main/java/step2/Operator.java | 4 ++-- src/main/java/step2/StringCalculatePreparator.java | 2 ++ src/test/java/step2/CalculatorDisplayTest.java | 1 + src/test/java/step2/CalculatorTest.java | 2 +- src/test/java/step2/OperatorTest.java | 1 + src/test/java/step2/PrepareCalculationContentsTest.java | 1 + 10 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/step2/CalculatePreparator.java b/src/main/java/step2/CalculatePreparator.java index 0ff609a..d421281 100644 --- a/src/main/java/step2/CalculatePreparator.java +++ b/src/main/java/step2/CalculatePreparator.java @@ -3,3 +3,4 @@ public interface CalculatePreparator { Calculator create(String stringExpression); } + diff --git a/src/main/java/step2/Calculator.java b/src/main/java/step2/Calculator.java index f741d2c..63c5132 100644 --- a/src/main/java/step2/Calculator.java +++ b/src/main/java/step2/Calculator.java @@ -53,3 +53,4 @@ public int calculate() { return result; } } + diff --git a/src/main/java/step2/CalculatorDisplay.java b/src/main/java/step2/CalculatorDisplay.java index 7a33b9f..7f7c80c 100644 --- a/src/main/java/step2/CalculatorDisplay.java +++ b/src/main/java/step2/CalculatorDisplay.java @@ -15,12 +15,12 @@ public CalculatorDisplay(CalculatePreparator calculatePreparator) { } // 양식에 맞는 문자열 수식을 넣으면 전체 계산 결과를 반환한다 - // test private int calculate(String userInputExpression) { Calculator calculator = calculatePreparator.create(userInputExpression); // 계산 준비 객체에서 계산기 객체를 만든다. return calculator.calculate(); // 계산기 객체가 계산 결과를 반환한다. } + // 테스트 코드 실행용 메서드(scanner 사용 제한) public int calculateForTest(String userInputExpression) { Calculator calculator = calculatePreparator.create(userInputExpression); // 계산 준비 객체에서 계산기 객체를 만든다. return calculator.calculate(); // 계산기 객체가 계산 결과를 반환한다. @@ -33,3 +33,4 @@ public void displayConsole() { System.out.println("calculateResult = " + calculateResult); } } + diff --git a/src/main/java/step2/Main.java b/src/main/java/step2/Main.java index 1191f3c..f9bc822 100644 --- a/src/main/java/step2/Main.java +++ b/src/main/java/step2/Main.java @@ -8,3 +8,4 @@ public static void main(String[] args) { calculatorDisplay.displayConsole(); } } + diff --git a/src/main/java/step2/Operator.java b/src/main/java/step2/Operator.java index 0ed7214..5f677aa 100644 --- a/src/main/java/step2/Operator.java +++ b/src/main/java/step2/Operator.java @@ -23,7 +23,7 @@ public enum Operator { // enum 객체가 가지고 있는 BiFunction 인터페이스 구현 로직에 따라 계산 결과를 반환한다. public int calculate(int a, int b) { - return this.biFunction.apply(a,b); + return this.biFunction.apply(a, b); } // 문자 형태의 연산자를 operatorSymbol로 가지고 있는 enum 객체를 찾아 반환한다. @@ -33,5 +33,5 @@ static Operator matchOperator(String symbol) { .findFirst() // enum 객체를 찾으면 반환한다. .orElseThrow(IllegalArgumentException::new); // 일치하는 객체가 없다면 예외 발생 } - } + diff --git a/src/main/java/step2/StringCalculatePreparator.java b/src/main/java/step2/StringCalculatePreparator.java index 00e1fd1..2f8bafd 100644 --- a/src/main/java/step2/StringCalculatePreparator.java +++ b/src/main/java/step2/StringCalculatePreparator.java @@ -28,6 +28,7 @@ private List createNumbers(List strings) { .map(Integer::valueOf) // 문자를 숫자로 변환한 stream을 반환 .collect(Collectors.toList()); // 변환된 숫자들을 List로 모은다 } + // 문자열의 홀수 위치 문자를 이용해 연산자 List를 만드는 메서드 private List createOperators(List strings) { List oddPositions = new ArrayList<>(); // 홀수 문자열을 담을 List @@ -39,3 +40,4 @@ private List createOperators(List strings) { .collect(Collectors.toList()); // 반환되는 enum 객체를 List로 담는다 } } + diff --git a/src/test/java/step2/CalculatorDisplayTest.java b/src/test/java/step2/CalculatorDisplayTest.java index 9904f6e..0b05518 100644 --- a/src/test/java/step2/CalculatorDisplayTest.java +++ b/src/test/java/step2/CalculatorDisplayTest.java @@ -34,3 +34,4 @@ void it_returns_a_result() { } } + diff --git a/src/test/java/step2/CalculatorTest.java b/src/test/java/step2/CalculatorTest.java index 6e802f4..a66dbcf 100644 --- a/src/test/java/step2/CalculatorTest.java +++ b/src/test/java/step2/CalculatorTest.java @@ -46,7 +46,7 @@ class Context_one_number { @DisplayName("It: 예외가 발생한다") void it_throws_exception() { assertThrows(IllegalArgumentException.class, () -> { - subject(Collections.singletonList(1), Collections.singletonList(Operator.SUM)); + subject(Collections.singletonList(1), Collections.singletonList(Operator.SUM)); }); } } diff --git a/src/test/java/step2/OperatorTest.java b/src/test/java/step2/OperatorTest.java index 902b25e..b44e021 100644 --- a/src/test/java/step2/OperatorTest.java +++ b/src/test/java/step2/OperatorTest.java @@ -153,3 +153,4 @@ void it_throws_exception() { } } } + diff --git a/src/test/java/step2/PrepareCalculationContentsTest.java b/src/test/java/step2/PrepareCalculationContentsTest.java index 09cfd6b..d77c256 100644 --- a/src/test/java/step2/PrepareCalculationContentsTest.java +++ b/src/test/java/step2/PrepareCalculationContentsTest.java @@ -44,3 +44,4 @@ void it_throws_exception() { } } } +