문자열 덧셈 계산기를 통한 TDD 실습
기능 요구사항
•
쉼표(,) 또는 콜론(:)을 구분자로 가지는 문자열을 전달하는 경우 구분자를 기준으로 분리한 각 숫자의 합을 반환 (예: “” => 0, "1,2" => 3, "1,2,3" => 6, “1,2:3” => 6)
•
앞의 기본 구분자(쉼표, 콜론)외에 커스텀 구분자를 지정할 수 있다. 커스텀 구분자는 문자열 앞부분의 “//”와 “\n” 사이에 위치하는 문자를 커스텀 구분자로 사용한다. 예를 들어 “//;\n1;2;3”과 같이 값을 입력할 경우 커스텀 구분자는 세미콜론(;)이며, 결과 값은 6이 반환되어야 한다.
•
문자열 계산기에 숫자 이외의 값 또는 음수를 전달하는 경우 RuntimeException 예외를 throw한다.
프로그래밍 요구사항
•
메소드가 너무 많은 일을 하지 않도록 분리하기 위해 노력해 본다.
코드 구성
작성코드
피드백
1) static final 키워드를 붙여서 상수로
2) 숫자를 구분하는 ‘구분 문자’라는 것을 좀 더 명확하게
import java.util.regex.Pattern;
public class StringAddCalculator {
private String regex = ",|:";
Java
복사
•
다음과 같이 변경
public class StringAddCalculator {
private static final String DELIMITER = ",|:";
private static final String CUSTOM_DELIMITER = "//(.)\n(.*)";
Java
복사
3) 매번 계산할 때마다 Pattern 인스턴스를 생성하는 대신에, 미리 하나의 인스턴스를 생성해놓고 이를 재사용
if (Objects.isNull(input)) {
return;
}
matcher = Pattern.compile("//(.)\n(.*)").matcher(input);
Java
복사
•
다음과 같이 변경
public class StringAddCalculator {
private static final String DELIMITER = ",|:";
private static final String CUSTOM_DELIMITER = "//(.)\n(.*)";
private static final Pattern CUSTOM_DELIMITER_PATTERN = Pattern.compile(CUSTOM_DELIMITER);
private String[] splitString(String input) {
String delimiter = DELIMITER;
Matcher matcher = CUSTOM_DELIMITER_PATTERN.matcher(input);
if (isPatternMatch(matcher)) {
delimiter = changeDelimiter(matcher);
input = changeInput(matcher);
}
return input.split(delimiter);
}
Java
복사
4) 상수 변경 및 멤버변수 지역변수로 변경
•
숫자 1 와 2 는 상수로 선언해서 의미를 부여해보자.
•
멤버 변수를 → 지역변수로 변경
private void changeRegex(Matcher matcher) {
regex = matcher.group(1);
}
// 입력값 변경하기
private void changeStringInput(Matcher matcher) {
StringInput = matcher.group(2);
}
Java
복사
•
다음과 같이 변경
public class StringAddCalculator {
private static final int ZERO = 0;
private static final int FIRST = 1;
private String changeDelimiter(Matcher matcher) {
return matcher.group(FIRST);
}
// 입력값 변경하기
private String changeInput(Matcher matcher) {
return matcher.group(SECOND);
}
Java
복사
5)객체지향 생활 체조 원칙의 규칙 1: 한 메서드에 오직 한 단계의 들여쓰기만 한다.
for (int i = 0; i < strings.length; i++) {
arr[i] = Integer.parseInt(strings[i]);
if (arr[i] < 0) {
throw new RuntimeException("음수가 입력되었습니다. 입력숫자를 확인해주세요.");
}
}
Java
복사
•
다음과 같이 변경
private int[] convertToNumberArray(String[] strings) {
int [] arr = new int[strings.length];
for (int i = 0; i < strings.length; i++) {
arr[i] = Integer.parseInt(strings[i]);
throwExceptionIfNegative(arr[i]);
}
return arr;
}
private void throwExceptionIfNegative(int input) {
if (input < 0) {
throw new RuntimeException("음수가 입력되었습니다. 입력숫자를 확인해주세요.");
}
}
Java
복사
6)null 또는 빈 문자열을 테스트할 경우, @NullAndEmptySource 라는 어노테이션을 활용해보는 걸 추천
@Test
@DisplayName("null 또는 빈 문자열 입력시 splitAndSum 체크")
public void splitAndSum_null_또는_빈문자() {
int result = stringAddCalculator.splitAndSum(null);
assertThat(result).isEqualTo(0);
result = stringAddCalculator.splitAndSum("");
assertThat(result).isEqualTo(0);
}
Java
복사
•
다음과 같이 변경
@ParameterizedTest
@DisplayName("null 또는 빈 문자열 입력시 splitAndSum 체크")
@NullAndEmptySource
public void splitAndSum_null_또는_빈문자(String text) {
int result = stringAddCalculator.splitAndSum(text);
assertThat(result).isEqualTo(0);
}
Java
복사
7) 파일 끝에는 개행을 해야된다.
8) 다음과 같이 줄일 수 있다.
if (Objects.isNull(input) || "".equals(input)) {
return true;
}
return false;
Java
복사
•
다음과 같이 변경
private boolean isNotValidValue(String input) {
return Objects.isNull(input) || "".equals(input);
}
Java
복사
피드백 이후 소스코드
소스코드
후기
오늘은 문자열 덧셈 계산기를 이용한 소스코드를 작성하였다.
기존의 소스코드의 습관이란, 고치기 힘든것 같다. 습관을 고치기위해서는 항상 인지하고, 이해하고 고치려고 노력해야 되는 것 같다. 위에 보여주는 예시를 항상 기억하고, 고치려고 마음 먹어보자.
깃허브 링크
출처