Weitere ähnliche Inhalte Ähnlich wie Clean code ch15 Ähnlich wie Clean code ch15 (20) Mehr von HyeonSeok Choi (20) Kürzlich hochgeladen (20) Clean code ch152. JUnit 프레임워크
• JUnit 소개
• Java 언어용 테스트 프레임워크
• 저자: 켄트벡, 에릭감마 등
• v3.x 구조
• 모든 테스트 클래스는 testCase를 상속 받음
• 테스트 메소드의 이름은 test로 시작해야 함
import junit.framework.TestCase;
public class ComparisoncompactorTest extends TestCase{
public void testMessage() {
String failure = new ComparisonCompactor(0, "b", "c").compact("a");
assertTrue("a expected:<[b]> but was:<[c]>".equals(failure));
}
}
• But, 이 장에서는 JUnit에서 가져온 예제 코드 ComparisonCompactor.java 를 평가
12년 9월 3일 월요일
3. ComparisonCompactor Class
• 두 문자열을 받아 차이를 반환
• ex) ABCDE, ABXDE => ...B[X]D...
public class ComparisonCompactor {
private static final String ELLIPSIS = "...";
private static final String DELTA_END = "]";
private static final String DELTA_START= "[";
private int fContextLength;
private String fExpected;
private String fActual;
private int fPrefix;
private int fSuffix;
public ComparisonCompactor(int contextLength, String expected, String actual) {
fContextLength = contextLength;
fExpected = expected;
fActual = actual;
}
public String compact(String message) {
if(fExpected == null || fActual == null || areStringEqual())
return assertFormat(message, fExpected, fActual);
findCommonPrefix();
findCommonSuffix();
String expected = compactString(fExpected);
String actual = compactString(fActual);
return assertFormat(message, expected, actual);
}
12년 9월 3일 월요일
4. ComparisonCompactor Class
private String compactString(String source) {
String result = DELTA_START + source.substring(fPrefix, source.length() -
fSuffix + 1) + DELTA_END;
if(fPrefix > 0) {
result = computeCommonPrefix() + result;
}
if(fSuffix > 0) {
result = result + computeCommonSuffix();
}
return result;
}
private void findCommonSuffix() {
int expectedSuffix = fExpected.length() - 1;
int actualSuffix = fActual.length() - 1;
for(; actualSuffix >= fPrefix && expectedSuffix >= fPrefix;
actualSuffix--, expectedSuffix--) {
if(fExpected.charAt(expectedSuffix) != fActual.charAt(actualSuffix))
break;
}
fSuffix = fExpected.length() - expectedSuffix;
}
private void findCommonPrefix() {
fPrefix = 0;
int end = Math.min(fExpected.length(), fActual.length());
for(; fPrefix < end; fPrefix++) {
if(fExpected.charAt(fPrefix) != fActual.charAt(fPrefix))
break;
}
}
12년 9월 3일 월요일
5. ComparisonCompactor Class
private String computeCommonPrefix() {
return (fPrefix > fContextLength? ELLIPSIS: "") +
fExpected.substring(Math.max(0, fPrefix - fContextLength), fPrefix);
}
private String computeCommonSuffix() {
int end = Math.min(fExpected.length() - fSuffix + 1 + fContextLength,
fExpected.length());
return fExpected.substring(fExpected.length() - fSuffix + 1, end) +
(fExpected.length() - fSuffix + 1 < fExpected.length() -
fContextLength? ELLIPSIS: "");
}
private boolean areStringEqual() {
return fExpected.equals(fActual);
}
private String assertFormat(String message, String fExpected,
String fActual) {
return message + “expected: <” + fExpected + “> but was: <” + fActual + “>”;
}
}
12년 9월 3일 월요일
6. Clean Code 적용
• 접두어 제거
private static final String ELLIPSIS = "..."; private static final String ELLIPSIS = "...";
private static final String DELTA_END = "]"; private static final String DELTA_END = "]";
private static final String DELTA_START= "["; private static final String DELTA_START= "[";
private int fContextLength; private int contextLength;
private String fExpected; private String expected;
private String fActual; private String actual;
private int fPrefix; private int prefix;
private int fSuffix; private int suffix;
• 접두어 제거로 인한 충돌
public String compact(String message) {
public String compact(String message) {
if(expected == null || actual == null || areStringEqual())
if(expected == null || actual == null || areStringEqual())
return assertFormat(message, expected, actual);
return assertFormat(message, expected, actual);
findCommonPrefix();
findCommonPrefix();
findCommonSuffix();
findCommonSuffix();
String compactExpected = compactString(expected);
String expected = compactString(expected);
String compactActual = compactString(actual);
String actual = compactString(actual);
return assertFormat(message, compactExpected,
return assertFormat(message, expected, actual);
compactActual);;
}
}
12년 9월 3일 월요일
7. Clean Code 적용
• 조건문 캡슐화 public String compact(String message) {
if(shouldNotCompact())
public String compact(String message) { return assertFormat(message, expected, actual);
if(expected == null || actual == null || areStringEqual()) findCommonPrefix();
return assertFormat(message, expected, actual); findCommonSuffix();
findCommonPrefix(); compactExpected = compactString(expected);
findCommonSuffix(); compactActual = compactString(actual);
compactExpected = compactString(expected); return assertFormat(message, compactExpected,
compactActual = compactString(actual); compactActual);
return assertFormat(message, compactExpected, }
compactActual); private boolean shouldNotCompact() {
} return expected == null || actual == null ||
areStringEqual();
}
public String compact(String message) {
• 긍정 표현으로 변경 if(canBeCompacted()) {
findCommonPrefix();
public String compact(String message) { findCommonSuffix();
if(shouldNotCompact()) compactExpected = compactString(expected);
return assertFormat(message, expected, actual); compactActual = compactString(actual);
findCommonPrefix(); return assertFormat(message, compactExpected,
findCommonSuffix(); compactActual);
compactExpected = compactString(expected); } else {
compactActual = compactString(actual); return assertFormat(message, expected, actual);
return assertFormat(message, compactExpected, }
compactActual); }
}
private boolean canBeCompacted() {
private boolean shouldNotCompact() {
return expected != null && actual != null &&
return expected == null || actual == null ||
areStringEqual();
areStringEqual();
}
}
12년 9월 3일 월요일
8. Clean Code 적용
• 함수의 의미를 명확하게 변경, Extract Method 적용
public String compact(String message) { private String compactExpected;
if(canBeCompacted()) { private String compactActual;
findCommonPrefix();
findCommonSuffix(); public String formatCompactedComparison(String message) {
compactExpected = compactString(expected); if(canBeCompacted()) {
compactActual = compactString(actual); compactExpectedAndActual();
return assertFormat(message, compactExpected, return assertFormat(message, compactExpected,
compactActual); compactActual);
} else { }
return assertFormat(message, expected, actual); return assertFormat(message, expected, actual);
} }
}
private void compactExpectedAndActual() {
findCommonPrefix();
findCommonSuffix();
compactExpected = compactString(expected);
compactActual = compactString(actual);
}
12년 9월 3일 월요일
9. Clean Code 적용
• 함수 내부의 사용 방식 통일
private void compactExpectedAndActual() {
private void compactExpectedAndActual() { prefixIndex = findCommonPrefix();
findCommonPrefix();
suffixIndex = findCommonSuffix();
findCommonSuffix();
compactExpected = compactString(expected);
compactExpected = compactString(expected);
compactActual = compactString(actual);
compactActual = compactString(actual);
}
}
private int findCommonPrefix() {
private void findCommonPrefix() {
int prefixIndex = 0;
prefix = 0;
int end = Math.min(expected.length(), actual.length()); int end = Math.min(expected.length(), actual.length());
for(; prefix < end; prefix++) { for(; prefixIndex < end; prefixIndex ++) {
if(expected.charAt(prefix) if(expected.charAt(prefixIndex)
!= actual.charAt(prefix)) != actual.charAt(prefixIndex))
break; break;
} }
} return prefixIndex;
}
private void findCommonSuffix() {
int expectedSuffix = expected.length() - 1; private int findCommonSuffix() {
int actualSuffix = actual.length() - 1; int expectedSuffix = expected.length() - 1;
for(; actualSuffix >= prefix int actualSuffix = actual.length() - 1;
&& expectedSuffix >= prefix; for(; actualSuffix >= prefixIndex
actualSuffix--, expectedSuffix--) { && expectedSuffix >= prefixIndex;
if( expected.charAt(expectedSuffix) actualSuffix--, expectedSuffix--) {
!= actual.charAt(actualSuffix)) if( expected.charAt(expectedSuffix)
break; != actual.charAt(actualSuffix))
} break;
suffix = expected.length() - expectedSuffix; }
} return expected.length() - expectedSuffix;
}
12년 9월 3일 월요일
10. Clean Code 적용
• 시간 결합 제거
private void compactExpectedAndActual() { private void compactExpectedAndActual() {
prefixIndex = findCommonPrefix(); prefixIndex = findCommonPrefix();
suffixIndex = findCommonSuffix(); suffixIndex = findCommonSuffix(prefixIndex);
compactExpected = compactString(expected); compactExpected = compactString(expected);
compactActual = compactString(actual); compactActual = compactString(actual);
} }
private int findCommonSuffix() { private int findCommonSuffix(int prefixIndex) {
int expectedSuffix = expected.length() - 1; int expectedSuffix = expected.length() - 1;
int actualSuffix = actual.length() - 1; int actualSuffix = actual.length() - 1;
for(; actualSuffix >= prefixIndex for(; actualSuffix >= prefixIndex
&& expectedSuffix >= prefixIndex; && expectedSuffix >= prefixIndex;
actualSuffix--, expectedSuffix--) { actualSuffix--, expectedSuffix--) {
if( expected.charAt(expectedSuffix) if( expected.charAt(expectedSuffix)
!= actual.charAt(actualSuffix)) != actual.charAt(actualSuffix))
break; break;
} }
return expected.length() - expectedSuffix; return expected.length() - expectedSuffix;
} }
적절하지 못하다
12년 9월 3일 월요일
11. Clean Code 적용
• 시간 결합 제거 ver2
private void compactExpectedAndActual() {
private void compactExpectedAndActual() {
prefixIndex = findCommonPrefix(); findCommonPrefixAndSuffix();
suffixIndex = findCommonSuffix(prefixIndex); compactExpected = compactString(expected);
compactExpected = compactString(expected); compactActual = compactString(actual);
compactActual = compactString(actual); }
}
private void findCommonPrefixAndSuffix() {
private int findCommonSuffix(int prefixIndex) { findCommonPrefix();
int expectedSuffix = expected.length() - 1; int expectedSuffix = expected.length() - 1;
int actualSuffix = actual.length() - 1; int actualSuffix = actual.length() - 1;
for(; actualSuffix >= prefixIndex for(; actualSuffix >= prefixIndex
&& expectedSuffix >= prefixIndex; && expectedSuffix >= prefixIndex;
actualSuffix--, expectedSuffix--) { actualSuffix--, expectedSuffix--) {
if( expected.charAt(expectedSuffix) if( expected.charAt(expectedSuffix)
!= actual.charAt(actualSuffix)) != actual.charAt(actualSuffix))
break; break;
} }
return expected.length() - expectedSuffix; return expected.length() - expectedSuffix;
} }
private void findCommonPrefix() {
prefixIndex = 0;
int end = Math.min(expected.length(),
actual.length());
시간 결합을
for(; prefix < end; prefix++) {
if(expected.charAt(prefix)
!= actual.charAt(prefix))
하나의 함수에 표현
}
}
break;
12년 9월 3일 월요일
12. Clean Code 적용
• 지저분해진 findCommonPrefixAndSuffix를 개선
private void findCommonPrefixAndSuffix() {
private void findCommonPrefixAndSuffix() { findCommonPrefix();
findCommonPrefix(); int suffixLength = 1;
int expectedSuffix = expected.length() - 1; for(; !suffixOverlapsPerfix(suffixLength);
int actualSuffix = actual.length() - 1; suffixLength++) {
for(; actualSuffix >= prefixIndex if( charFromEnd(expected, suffixLength)
&& expectedSuffix >= prefixIndex;
!= charFromEnd(actual, suffixLength))
actualSuffix--, expectedSuffix--) {
break;
if( expected.charAt(expectedSuffix)
}
!= actual.charAt(actualSuffix))
suffixIndex = suffixLength
break;
}
}
return expected.length() - expectedSuffix;
private char charFromEnd(String s, int i) {
}
return s.charAt(s.length() - i);
}
private boolean suffixOverlapsPerfix(int suffixLength) {
return actual.length() - suffixLength < prefixLength ||
expected.length() - suffixLength < prefixLength;
}
suffixIndex가 실제로는
접미어의 길이
12년 9월 3일 월요일
13. Clean Code 적용
• suffixIndex를 suffixLength로 변경
private int suffixLength = 0;
private String compactString(String source) {
private String compactString(String source) {
String result = DELTA_START + source.substring(
String result = DELTA_START + source.substring(
prefixIndex, source.length() - suffixIndex + 1 )
prefixLength, source.length() - suffixLength ) +
+ DELTA_END;
DELTA_END;
if(prefixIndex > 0) {
if(prefixLength > 0) {
result = computeCommonPrefix() + result;
result = computeCommonPrefix() + result;
}
}
if(suffixIndex > 0) {
if(suffixLength > 0) {
result = result + computeCommonSuffix();
result = result + computeCommonSuffix();
}
}
return result;
return result;
}
}
• suffixLength로 인한 이슈 발생 (suffixLength > 0)
private int suffixLength = 0;
private String compactString(String source) {
String result = DELTA_START + source.substring(
prefixLength, source.length() - suffixLength )
private String compactString(String source) {
+ DELTA_END;
return computeCommonPrefix() + DELTA_START
if(prefixLength > 0) {
+ source.subString source.substring(prefixLength,
result = computeCommonPrefix() + result;
source.length() - suffixLength ) + DELTA_END
}
+ computeCommonSuffix();
}
if(suffixLength > 0) {
result = result + computeCommonSuffix();
}
return result;
}
12년 9월 3일 월요일