2019-05-09 [java-study] 문자열 덧셈 계산기 스터디
09 May 2019 | java stream TDD문자열 덧셈 계산기
요구사항
-
쉼표(,) 또는 콜론(:)을 구분자로 가지는 문자열을 전달하는 경우 구분자를 기준으로 분리한 각 숫자의 합을 반환 (예: “” => 0, “1,2” => 3, “1,2,3” => 6, “1,2:3” => 6)
-
앞의 기본 구분자(쉼표, 콜론)외에 커스텀 구분자를 지정할 수 있다. 커스텀 구분자는 문자열 앞부분의 “//”와 “\n” 사이에 위치하는 문자를 커스텀 구분자로 사용한다. 예를 들어 “//;\n1;2;3”과 같이 값을 입력할 경우 커스텀 구분자는 세미콜론(;)이며, 결과 값은 6이 반환되어야 한다.
-
문자열 계산기에 숫자 이외의 값 또는 음수를 전달하는 경우 RuntimeException 예외를 throw한다
프로그래밍 요구사항
- indent(들여쓰기) depth를 2단계에서 1단계로 줄여라.
- depth의 경우 if문을 사용하는 경우 1단계의 depth가 증가한다. if문 안에 while문을 사용한다면 depth가 2단계가 된다.
- 메소드의 크기가 최대 10라인을 넘지 않도록 구현한다.
- method가 한 가지 일만 하도록 최대한 작게 만들어라.
- else를 사용하지 마라.
요구사항 힌트
-
빈 문자열 또는 null 값을 입력할 경우 0을 반환해야 한다.(예 : “” => 0, null => 0)
-
숫자 하나를 문자열로 입력할 경우 해당 숫자를 반환한다.(예 : “1”)
-
숫자 두개를 컴마(,) 구분자로 입력할 경우 두 숫자의 합을 반환한다.(예 : “1,2”)
-
구분자를 컴마(,) 이외에 콜론(:)을 사용할 수 있다. (예 : “1,2:3” => 6)
-
“//”와 “\n” 문자 사이에 커스텀 구분자를 지정할 수 있다. (예 : “//;\n1;2;3” => 6)
-
음수를 전달할 경우 RuntimeException 예외가 발생해야 한다. (예 : “-1,2,3”)
목표
- 리팩토링 시간을 줄이자! (정해진 시간안에 구현)
- Test -> 구현 순서
- stream or 람다식 사용
공부한 내용
Pattern, Matcher 클래스
Pattern p = Pattern.compile('정규식');
Matcher matcher = p.matcher("문자열");
- find()
- Pattern에 일치하는 텍스트가 발견 되면 true
- group()
- 패턴과 일치하는 텍스트를 반환
정규식
표현식 | 설명 |
---|---|
^ | 문자열의 시작 |
$ | 문자열의 종료 |
. | 임의의 한 문자 (줄바꿈 제외) |
[…] | [] 사이에 있는 문자 혹은 문자집합 (ex A-Z) |
[^…] | [] 사이에 있는 문자 혹은 문자집합 제외 |
* | 앞문자가 문자열일 많을수도 없을수도 |
+ | 앞 문자가 하나 이상 |
? | 앞 문자가 없거나 하나 |
{} | 횟수 또는 범위 |
\d | [0-9] |
더 많은 표현 : https://jamesdreaming.tistory.com/179
자주 사용하는 거
-
숫자만 :
^[0-9]*$
-
영문자만 :
^[a-zA-Z]*$
-
한글만 :
^[가-힣]*$
-
영어 & 숫자만 :
^[a-zA-Z0-9]*$
-
E-Mail :
^[a-zA-Z0-9]+@[a-zA-Z0-9]+$
-
휴대폰 :
^01(?:0|1|[6-9]) - (?:\d{3}|\d{4}) - \d{4}$
-
일반전화 :
^\d{2.3} - \d{3,4} - \d{4}$
-
주민등록번호 :
\d{6} \- [1-4]\d{6}
-
IP 주소 :
([0-9]{1,3}) \. ([0-9]{1,3}) \. ([0-9]{1,3}) \. ([0-9]{1,3})
"//;\n1;2;3"
Matcher matcher = Pattern.compile("//(.)\n(.*)").matcher(string);
=> //
와 \n
사이의 문자가 식의 구분자
matcher.group(2), matcher.group(1) //group(2)는 1;2;3 group(1)은 ;
Stream
-
mapToInt() : 객체 스트림을 기본 타입 스트림으로 변환 (Stream -> IntStream)
-
allMatch() : 모든 파라미터가 조건에 중촉되는지
String[] str = {"1", "2", "3"};
Arrays.stream(str).mapToInt(num -> Integer.parseInt(num)).allMatch(num -> num > 0);
assertThat
=> 가독성 UP
- isEqualTo = 동등
assertThat(stringAddCalculator.calculate(null)).isEqualTo(0);
-
contains
-
startWith
-
…
더 많은 정보 : https://joel-costigliola.github.io/assertj/
##리뷰 받은 내용
- 변수를 줄여쓰지 않는다.
StringAddCalculator cal;
-
assertThat() 사용하기 (참고 https://joel-costigliola.github.io/assertj/ )
-
java Stream stream = Arrays.stream(str); stream.mapToInt(num -> Integer.parseInt(num)).allMatch(num -> num > 0);
stream을 선언하지 않고 한줄에 끝낼수있다.
-
무조건 stream을 사용하지말고 장점이 있는 경우에만 사용 => 이번엔 stream을 사용해 보고싶었음 다음부턴 효율적으로 적용
-
Test 작성 -> Test Fail -> Test 통과할만큼의 간단한 구현 -> 중복제거 리팩토링 -> 다른 요구사항 test 작성 -> … 무한반복
-
Scanner 생성 비용이 높아 메소드에서 생성하는 것보단 매개변수로 받는게 좋음 => threadSafe문제
-
변수명에 자료형 이름이 오지 않는다.
힘든점
- 정규식 표현을 읽기 힘들었다.
- 정규식 사용 이유 : 코딩 시간절약, 특정 문자나 문자열 검색등등
- 단점 : 가독성 떨어짐.
- 저번보다 리팩토링 시간을 줄였음.
- test 작성 -> 구현 -> 리팩토링 순서
- 추가 요구 사항 (선택)
- 1번 (positive 객체 사용) => stream 사용할 아이디어가 생각이안남
- 2번 (Inteface를 사용하여 Splitter 구현) => interface 사용시 오버라이딩 때문에 static 메소드 사용할 수 없어서 더 복잡해졌음.
- 3번 (람다식 사용) => 이번 과제는 람다식 (Stream) 중심으로 구현
소스 코드 : https://github.com/sproutt/spring-study-lotto/pull/11/files
Comments