Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/main/java/calculator/CalculatorService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package calculator;

import java.util.List;

public class CalculatorService {

public int calculate(String expression) {
List<Number> numbers = Splitter.getSplitNumbers(expression);

Number result = numbers.stream()
.reduce(Number::sum)
.orElseThrow(() -> new ArithmeticException());

return result.getValue();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

stream 구문 이후 그 결과값을 받은뒤 return 하는거보다
return 에서 stream 구문을 끝내도록 하는게 좀 더 가독성이 좋을거같습니다. 아직 익숙하지 않아서 적절한 예시를 알려주진 못하지만 ..ㅠㅠ
찬인이형이 잘 했놧다고 생각합니당

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그냥 Number객체를 리턴하는게 좋아보이네요

}
}
38 changes: 38 additions & 0 deletions src/main/java/calculator/Number.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package calculator;

public class Number {
private final int value;

public Number(String value) {
this.value = parseString(value);
}

public Number(int value) {
this.value = value;
}

public int getValue() {
return value;
}

public static Number sum(Number a, Number b) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

클래스 메서드보단 number.sum(number)가 더 좋은 객체관계일거같아요

return new Number(a.getValue() + b.getValue());
}

private int parseString(String value) {
validateNumber(value);
int result = Integer.parseInt(value);

if (result < 0) {
throw new RuntimeException(String.format("음수가 입력되었습니다. : %s ", result));
}

return result;
}

private void validateNumber(String value) {
if (value == null || value.isEmpty()) {
throw new RuntimeException("빈 문자열 입니다.");
Copy link

@csbsjy csbsjy Mar 4, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이거 RunTimeException 을 구현한 애로 쓰는게 더 좋지않낭?
RuntimeException 을 catch 하면 모든 그 하위 Exception 이랑 같이 다 잡혀서 디버그하기 힘들것도같은뎅 !
흠 에러메시지 있어서 괜찮으려낭 ..

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

조금 헷갈리는게 요구사항엔 단순하게 RuntimeException을 던지라고 나와있어서 이렇게 했는데 조금 더 고민해보고 수정해볼께!

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오호 요구사항이 그랬구나 난 바보야

}
}
}
42 changes: 42 additions & 0 deletions src/main/java/calculator/Splitter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package calculator;

import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class Splitter {
private static final String COMMON_DELIMITER = "[,:]";
private static final Pattern CUSTOM_DELIMITER_PATTERN = Pattern.compile("//(.)\n(.*)");
private static final String DEFAULT_NUMBER = "0";
private static final int DELIMITER_GROUP = 1;
private static final int FORMULA_GROUP = 2;

public static List<Number> getSplitNumbers(String expression) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아하 여기서 Number 로 꺼내주는방법이있었구나 ..

if (expression == null || expression.isEmpty()) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

매번 추가 DELIMITER가 추가될때마다 if문이 하나씩 추가될꺼같은데 이런 구조보단 Splitter를 인터페이스로 빼고 여러 Splitter를 구현해서 다른 방식으로 해결하는게 좋을듯

return commonSplit(DEFAULT_NUMBER);
}

Matcher matcher = CUSTOM_DELIMITER_PATTERN.matcher(expression);
if (matcher.find()) {
return customSplit(matcher);
}

return commonSplit(expression);
}

private static List<Number> customSplit(Matcher matcher) {
String delimiter = matcher.group(DELIMITER_GROUP);
String formula = matcher.group(FORMULA_GROUP);
return Arrays.stream(formula.split(delimiter))
.map(Number::new)
.collect(Collectors.toList());
}

private static List<Number> commonSplit(String expression) {
return Arrays.stream(expression.split(COMMON_DELIMITER))
.map(Number::new)
.collect(Collectors.toList());
}
}
Empty file removed src/main/java/calculator/empty.txt
Empty file.
60 changes: 60 additions & 0 deletions src/test/java/calculator/CalculatorServiceTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package calculator;

import org.assertj.core.api.ThrowableAssert;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.NullAndEmptySource;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.*;

class CalculatorServiceTest {

@DisplayName("기본 구분자로 식 입력시 결과 반환")
@Test
void name() {
String expression = "1,2:3";
CalculatorService calculatorService = new CalculatorService();
int result = calculatorService.calculate(expression);
assertThat(result).isEqualTo(6);
}

@DisplayName("커스텀 구분자로 식 입력시 결과 반환")
@Test
void name1() {
String expression = "//h\n1h2h3";
CalculatorService calculatorService = new CalculatorService();
int result = calculatorService.calculate(expression);
assertThat(result).isEqualTo(6);
}

@DisplayName("1 입력시 1 반환")
@Test
void name4() {
String expression = "1";
CalculatorService calculatorService = new CalculatorService();
int result = calculatorService.calculate(expression);
assertThat(result).isEqualTo(1);
}

@DisplayName("빈 문자열, null 입력시 0")
@ParameterizedTest
@NullAndEmptySource
void name2(String expression) {
CalculatorService calculatorService = new CalculatorService();
int result = calculatorService.calculate(expression);
assertThat(result).isEqualTo(0);
}

@DisplayName("음수 값 있을때 RuntimeExcetion Throw")
@Test
void name3() {
String expression = "1,-2:3";
CalculatorService calculatorService = new CalculatorService();
assertThatThrownBy(() -> calculatorService.calculate(expression))
.isInstanceOf(RuntimeException.class)
.hasMessage(String.format("음수가 입력되었습니다. : %s ", -2));
}
}
31 changes: 31 additions & 0 deletions src/test/java/calculator/NumberTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package calculator;

import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.EmptySource;
import org.junit.jupiter.params.provider.NullAndEmptySource;
import org.junit.jupiter.params.provider.ValueSource;

import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.jupiter.api.Assertions.*;

class NumberTest {
@DisplayName("빈 문자열 또는 null일시 RuntimeException Throw")
@ParameterizedTest
@NullAndEmptySource
void name1(String expression) {
assertThatThrownBy(() -> new Number(expression))
.isInstanceOf(RuntimeException.class)
.hasMessage("빈 문자열 입니다.");
}

@DisplayName("음수일시 RuntimeException Throw")
@Test
void name() {
assertThatThrownBy(() -> new Number("-1"))
.isInstanceOf(RuntimeException.class)
.hasMessage(String.format("음수가 입력되었습니다. : %s ", -1));
}
}
28 changes: 28 additions & 0 deletions src/test/java/calculator/SplitterTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package calculator;

import jdk.nashorn.internal.ir.annotations.Ignore;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;

class SplitterTest {

@DisplayName("일반적인 식 입력시 분리된 숫자 List가 반환")
@Test
void name() {
String expression = "1,2:3,4";
List<Number> numbers = Splitter.getSplitNumbers(expression);
assertThat(numbers.size()).isEqualTo(4);
}

@DisplayName("커스텀 구분자로 입력시 분리된 숫자 List가 반환")
@Test
void name1() {
String expression = "///\n1/2/3/6";
List<Number> numbers = Splitter.getSplitNumbers(expression);
assertThat(numbers.size()).isEqualTo(4);
}
}
Empty file removed src/test/java/calculator/empty.txt
Empty file.