Codewars 문제풀기 (04/08)
Credit Card Mask
- String을 인수로 받는다.
- 마지막 4문자를 남기고 “#”문자로 치환한 문자열을 리턴한다.
- 입력 인수 길이가 4 이하라면 인수 그대로 리턴한다.
- maskify(“4556364607935616”) –> “############5616”
- maskify(“Nananananananananananananananana Batman!”) –> “####################################man!”
- maskify(“1”) –> “1”
- maskify(“”) –> “”
1. Test와 리팩토링
-
입력 String 인수의 길이가 4이하라면 입력 String 그대로 리턴해야한다.
-
테스트 코드
@Test public void testShouldReturnOriginalStringWhenInputLengthLessThan4() { // Given: Set string length less than 4 String given = "asd"; // When: Call maskify method String actual = Maskify.maskify(given); // Then: Should return input string assertEquals(given, actual); }
-
실제 코드
public class Maskify { public static String maskify(String str) { return str.length() < 5 ? str : ""; } }
-
첫번째 테스트를 만족하는 코드만 작성했다.
-
-
입력 String 인수 길이가 4보다 크면, 마지막 4문자만 남기고 모든 문자를 ‘#’로 치환한다.
-
테스트 코드
@Test public void testShouldReplaceAllCharacterToHashTagExceptLast4Characters() { // Given: Set string length more than 4 String given = "mynameisleejinho"; // When: Call maskify method String actual = Maskify.maskify(given); // Then: Should return Replace # except last 4 string assertEquals("############inho", actual); }
-
실제 코드
public class Maskify { public static String maskify(String str) { if (str.length() < 5) { return str; } StringBuilder result = new StringBuilder(); for (int i = 0; i < str.length() - 4; i++) { result.append("#"); } result.append(str.substring(str.length() - 4)); return result.toString(); } }
- StringBuilder를 선언하여 입력 String length - 4만큼 ‘#’을 붙이고, 뒤에 마지막 문자4개를 붙여 반환했다.
-
리팩토링
-
우선 매직넘버를 상수로 추출 할 수 있을것 같다.
public class Maskify { public static final int UNMASK_STRING_LENGTH = 4; public static String maskify(String str) { if (str.length() <= UNMASK_STRING_LENGTH) { return str; } StringBuilder result = new StringBuilder(); for (int i = 0; i < str.length() - UNMASK_STRING_LENGTH; i++) { result.append("#"); } result.append(str.substring(str.length() - UNMASK_STRING_LENGTH)); return result.toString(); } }
- 매직넘버 4를 UNMASK_STRING_LENGTH로 추출했다.
-
for문을 굳이 쓸 필요가 있을까? 그리고 StringBuilder를 쓰지않아도 될 것 같다.
public class Maskify { public static final int UNMASK_STRING_LENGTH = 4; public static String maskify(String str) { if (str.length() <= UNMASK_STRING_LENGTH) { return str; } String unMaskString = str.substring(str.length() - UNMASK_STRING_LENGTH); String maskString = str.substring(0, str.length() - UNMASK_STRING_LENGTH) .replaceAll(".", "#"); return maskString + unMaskString; } }
- 구글링을해보니 모든 문자에 대한 정규표현식이 “.”이었다. 그래서 replaceAll()메서드를 이용하여 모든 문자들을 #문자로 바꾸었다.
- mask, unmask string을 지역변수로 따로 만들었다.
- 더 리팩토링할 요소가 없다고 판단하여 제출했다.(리팩토링 제외 문제풀기만 15분정도 소요)
-
-
2. 답 비교, 느낀점
Best Practice 가장 많이 받은 코드
public class Maskify {
public static String maskify(String str) {
if (str.length() <= 4) return str;
String result = "";
for (int i = 0; i < str.length()-4; i++) {
result += "#";
}
return result + str.substring(str.length()-4);
}
}
- 처음에 작성한 코드와 크게 다르지 않다 다른점은 StringBuilder를 사용하지않고 String을 사용한것.
3. 알게된 것
- 모든 문자에 대한 정규표현식 –> “.”
- 모든 문자를 ‘!’문자로 바꾸려면 –> replaceAll(“.”, “!”);
댓글남기기