-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* docs: 문자열 덧셈 계산기 기능요구사항 정의 * feat: 컴마(,)구분자로 입력한 경우의 테스트 코드 추가 * refactor(Main): 불필요한 사용자 UI 제거 * refactor: 클래스 이름변경(CalculatorModel > AddCalculatorModel) * refactor: 메소드(calculate) 추출 * feat: “//”와 “\n” 문자 사이에 커스텀 구분자 관련 테스트 코드 추가 * refactor: 메소드 시그니쳐 변수명 변경 * refactor: polishing inline variable * refactor: 테스트 코드 간결하게 수정 * style: 불필요한 개행 문자 제거 * refactor:코드 피드백 반영 - requiredNumber > validateString 수정 - 문자 단위가 아닌, 문자열 단위로 체크되도록 수정 - CustomDelimiterMatcher 이름 변경 및 내부 코드 변경 - AddCalculatorModel 내 불필요한 클래스 변수 제거
- Loading branch information
Showing
7 changed files
with
221 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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 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,27 @@ | ||
package calculator; | ||
|
||
import static calculator.StringUtils.*; | ||
|
||
public final class AddCalculatorModel { | ||
private final static String DEFAULT_DELIMITER_REGEX = ",|:"; | ||
private long sum = 0L; | ||
|
||
public long execute(String userInput) { | ||
if (isBlank(userInput)) { | ||
return sum; | ||
} | ||
|
||
if (CustomDelimiterMatcher.hasDelimiter(userInput)) { | ||
String[] splitTokens = CustomDelimiterMatcher.getSplitTokens(userInput); | ||
return calculate(StringUtils.convertStringToLong(splitTokens)); | ||
} | ||
return calculate(StringUtils.convertStringToLong(userInput.split(DEFAULT_DELIMITER_REGEX))); | ||
} | ||
|
||
private long calculate(Long[] longs) { | ||
for (Long l : longs) { | ||
this.sum += l; | ||
} | ||
return sum; | ||
} | ||
} |
This file contains 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,31 @@ | ||
package calculator; | ||
|
||
import static java.util.Objects.*; | ||
|
||
import java.util.regex.Matcher; | ||
import java.util.regex.Pattern; | ||
|
||
public final class CustomDelimiterMatcher { | ||
|
||
private final Matcher matcher; | ||
private final static Pattern CUSTOM_DELIMITER_PATTERN = Pattern.compile("//(.)\n(.*)"); | ||
|
||
private CustomDelimiterMatcher(Matcher matcher) { | ||
requireNonNull(matcher); | ||
this.matcher = matcher; | ||
} | ||
|
||
public static String[] getSplitTokens(String userInput) { | ||
Matcher matcher = new CustomDelimiterMatcher(CUSTOM_DELIMITER_PATTERN.matcher(userInput)).matcher; | ||
if (matcher.find() == false) { | ||
throw new RuntimeException("커스텀 구분자를 찾을 수 없습니다"); | ||
} | ||
String delimiter = matcher.group(1); | ||
String group = matcher.group(2); | ||
return group.split(delimiter); | ||
} | ||
|
||
public static boolean hasDelimiter(String userInput) { | ||
return CUSTOM_DELIMITER_PATTERN.asPredicate().test(userInput); | ||
} | ||
} |
This file contains 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,12 @@ | ||
package calculator; | ||
|
||
import java.util.Scanner; | ||
|
||
public class Main { | ||
|
||
public static void main(String[] args) { | ||
Scanner sc = new Scanner(System.in); | ||
AddCalculatorModel model = new AddCalculatorModel(); | ||
System.out.println(model.execute(sc.nextLine())); | ||
} | ||
} |
This file contains 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,14 @@ | ||
package calculator; | ||
|
||
import java.util.regex.Pattern; | ||
|
||
public final class NumberUtils { | ||
|
||
private static final Pattern numberPattern = Pattern.compile("[0-9]*"); | ||
|
||
public static void validateString(String string) { | ||
if (numberPattern.matcher(string).matches() == false) { | ||
throw new IllegalArgumentException("유효하지 않은 숫자가 사용되었습니다."); | ||
} | ||
} | ||
} |
This file contains 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,21 @@ | ||
package calculator; | ||
|
||
import static calculator.NumberUtils.*; | ||
import static java.util.Objects.*; | ||
|
||
public final class StringUtils { | ||
|
||
public static boolean isBlank(String s) { | ||
return isNull(s) || s.equals(""); | ||
} | ||
|
||
static Long[] convertStringToLong(String[] strings) { | ||
Long[] result = new Long[strings.length]; | ||
for (int i = 0; i < strings.length; i++) { | ||
String value = strings[i]; | ||
validateString(value); | ||
result[i] = Long.parseLong(value); | ||
} | ||
return result; | ||
} | ||
} |
This file contains 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,65 @@ | ||
package calculator; | ||
|
||
import static org.assertj.core.api.Assertions.*; | ||
|
||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
import org.junit.jupiter.params.provider.NullAndEmptySource; | ||
import org.junit.jupiter.params.provider.ValueSource; | ||
|
||
class AddCalculatorModelTest { | ||
|
||
private AddCalculatorModel sut; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
sut = new AddCalculatorModel(); | ||
} | ||
|
||
@ParameterizedTest(name = "빈 문자열 또는 Null 테스트") | ||
@NullAndEmptySource | ||
void 빈문자열_또는_Null_값을_입력할경우_0을_반환(String userInput) { | ||
assertThat(sut.execute(userInput)).isEqualTo(0); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {"1", "2", "999999999999"}) | ||
void 숫자_하나를_문자열로_입력할_경우_해당_숫자를_반환(String value) { | ||
long expected = Long.parseLong(value); | ||
assertThat(sut.execute(value)).isEqualTo(expected); | ||
} | ||
|
||
@ParameterizedTest | ||
@ValueSource(strings = {"-1", "-1,-1", "-1,2:3"}) | ||
void 마이너스_또는_유효하지_않는_값_입력시_예외호출(String value) { | ||
assertThatThrownBy(() -> sut.execute(value)) | ||
.isInstanceOf(IllegalArgumentException.class) | ||
.hasMessageContaining("유효하지 않은 숫자가 사용되었습니다."); | ||
} | ||
|
||
@ParameterizedTest | ||
@CsvSource(value = {"0,1:1", "1,2:3", "999999999999,999999999999:1999999999998"}, delimiterString = ":") | ||
void 숫자_두개를_컴마구분자로_입력할_경우_두숫자의_합을_반환한다(String userInput, Long expected) { | ||
assertThat(sut.execute(userInput)).isEqualTo(expected); | ||
} | ||
|
||
@ParameterizedTest(name = "구분자를_컴마_뿐만_아니라_콜론도_가능") | ||
@ValueSource(strings = {"1,2:3", "1:2:3"}) | ||
void 구분자를_컴마_뿐만_아니라_콜론도_가능(String value) { | ||
assertThat(sut.execute(value)).isEqualTo(6); | ||
} | ||
|
||
@ParameterizedTest(name = "[{index}]({argumentsWithNames})“//”와 “\\n” 문자 사이에 커스텀 구분자를 지정하면 지정된 커스텀 구분자로 구분된다.") | ||
@ValueSource(strings = {"//;\n1;2;3", "//a\n1a2a3", "//!\n1!2!3"}) | ||
void _1(String value) { | ||
assertThat(sut.execute(value)).isEqualTo(6); | ||
} | ||
|
||
@ParameterizedTest(name = "[{index}] 유효하지 않는 커스텀 구분자({argumentsWithNames})를 지정하면 예외 호출한다.") | ||
@ValueSource(strings = {"//abc\n1abc2abc3", "//;\n1;2:3", "//!\n1!2,3"}) | ||
void _2(String value) { | ||
assertThatThrownBy(() -> sut.execute(value)).isInstanceOf(IllegalArgumentException.class) | ||
.hasMessageContaining("유효하지 않은 숫자가 사용되었습니다."); | ||
} | ||
} |