4. 리팩토링 배경:
: Bad Code가 야기시키는 문제점
Broken Window Theory
나쁜코드에 의한 생산성 저하는 계속 악화됨
5. 리팩토링 정의
명사형 정의
“소프트웨어를 보다 쉽게 이해할 수 있고, 적은 비용으로 수정할 수 있도록 겉으로 보이는 동작의 변화 없이 내부 구조를 변
경하는 것”
동사형 정의
“일련의 리팩토링을 적용하여 겉으로 보이는 동작의 변화 없이 소프트웨어의 구조를 바꾼다.”
다음 방법으로 동작의 변경 여부 검증
테스팅
최대한 개발 Tool의 지원 기능 사용
아주 조심히 진행
Refactoring의 예
public int getCharge(int quantity) { public int getCharge(int quantity) {
int charge = 0; int charge = 0;
Date now = new Date(); Date now = new Date();
// 현재 Summer타임 기간이라면 if (isSummerTime(now)) {
if (now.before(SUMMER_START)|| now.after(SUMMER_END)) { charge = quantity * WINTER_RATE +
charge = quantity * WINTER_RATE + WINTER_SERVICEC_CHARGE;
WINTER_SERVICEC_CHARGE; } else {
} else { charge = quantity * SUMMER_RATE;
charge = quantity * SUMMER_RATE; }
} return charge;
return charge }
}
private boolean isSummerTime(Date now) {
return now.before(SUMMER_START) || now.after(SUMMER_END);
}
6. 리팩토링 원리
: 왜 리팩토링을 해야 하는가?
프로그램을 빨리 작성하도록 도와줌
어떻게?
리팩토링은 디자인을 개선시켜 줌
디자인이 나쁜 코드는?
같은 작업을 위해 더 많은 코드 사용
중복이 많고 이해하기 어려움
수정 시 어려움으로 나타남
리팩토링은 소프트웨어를 더 이해하기 쉽게 만듬
리팩토링된 코드는 숨겨진 사용자인 유지보수자의 이해를 도움
낮선 코드에 대해 리팩토링 하면서 코드에 대해 이해하기도 함
7. 리팩토링 원리
: 언제 리팩토링을 해야 하는가?
틈틈이 계속
리팩토링 자체가 목적이 아니라, 다른 것을 하기 위해 리팩토링
을 하는 것이고, 리팩토링은 그 다른 것을 하는데 도움을 준다.
삼진 규칙
세 번째로 비슷한 것을 하게 되면 리팩토링을 한다
기능을 추가할 때, 버그를 수정할 때
코드에 대한 이해를 돕기 위해서
코드 검토 시
고수준의 의견을 얻을 수 있음
준비가 많이 필요함
8. 리팩토링 원리
: 두 개의 모자
기능 추가 리팩토링
기존 코드 수정 없이 새로운 기능 추가 기능 추가 없이 코드 구조 수정
테스트 추가 테스트 추가하지 않아야 함
테스트 정상 동작 확인 테스트 정상 동작 확인
개발할 때에는 모자를 자주 바꿔 쓰고(10분~30분),
한 시점에는 하나의 모자만 써야 한다.
9. 리팩토링 원리
: 리팩토링을 할 때의 문제
데이터 베이스와 연관된 코드의 리팩토링
인터페이스의 변경
Publish 된 인터페이스의 이름 및 파라미터에 대한 리팩토링
Ex) Android의 Service.onStart() 메소드
새로운 I/F를 만들고 Delegation 사용
예방책 : 애매한 메소드는 API에 넣지 말자
Publish 된 인터페이스의 Throw절의 변경
이 경우 Delegation 사용 불가
예방책 : Super Exception 사용
리팩토링이 어려운 디자인 변경
디자인에 실수가 있어 마음대로 리팩토링 할 수 없을 때
어떤 디자인 결정 사항이 너무 중요해서 리팩토링을 기대할 수 없는 경우
보안 문제, 퍼포먼스 문제
언제 리팩토링을 하지 말아야 하는가?
코드를 처음부터 작성 하는 게 나을 정도로 엉망인 경우
현재의 코드가 작동하지 않을 경우
마감일에 가까울 경우
10. 리팩토링 원리
: 사전 디자인과 리팩토링의 효용성 관계
“디자인으로는 생각을 아주 빨리 할 수 있지만, 그 생각에는 여
기저기 작은 구멍이 뚫려있다.”
“With design I can think very fast, but my thinking is full of little
holes” – Alistair Cockburn
리팩토링에 의해 사전 디자인의 Role이 변경됨
완벽한 사전 디자인이 아닌 적절한 솔루션을 제공하는 디자인이면
충분
리팩토링을 통해 변경에 많은 비용이 들지 않기 때문
따라서, 디자인이 단순화 됨
디자인 중심의 단점
설계 비용이 많이 든다.
복잡해 진다.
유지보수 비용이 상대적으로 많이 든다.
중복에 의한게 아닌 Complexity 때문
11. 리팩토링 원리
: 리팩토링과 퍼포먼스
리팩토링은 장기적으로 최적화 단계에 소프트웨어의
튜닝을 돕는다.
리팩토링을 통해 퍼포먼스 튜닝에 할당할 수 있는 시간을
얻을 수 있음.
프로그램이 잘 분해되어 있으면, 튜닝을 위한 분석 시 좀
더 세밀한 분석이 가능하다.
12. 냄새
냄새(코드냄새)는 코드에 잠재된 문제에 대한 경고 표
시
리팩토링을 해야 하는 문제점 표시
대표적 냄새
중복코드
부적절한 이름
기능에 대한 욕심
부적절한 친밀
주석
긴 메소드
긴 파라미터 리스트
Switch문
13. 냄새
: 중복 코드
가장 많이 발생하는 냄새
두 가지 중복이 있음
Obvious 중복
보통 Copy & Paste에 의해 발생
Unobvious 중복
계층구조의 병렬적 구현
비슷한 알고리즘(ex, 문자열, 도메인 특화 로직)
해결책
하나의 클래스에서 중복
ExtractMethod
두 형제 클래스에서 중복
ExtractMethod -> Pull Up Field or Pull Up Method -> Form
Template Method
14. 냄새
: 부적절한 이름
잘못된 이름은 코드의 이해를 방해한다.
“People often make assumptions based on the object
names alone” – Word Cunningham
해결책
Rename Method
Rename Field
Rename Constants
Tip !
일관성 없는 상세이름 보다는 일관성 있는 광의의 이름이 적합
add, register, put, create -> add
일관성 있는 이름을 위해서 용어 사전은 필수적
15. 냄새
: 기능에 대한 욕심
특정 클래스 내의 메소드가 동 PriceCalculator Product
작을 위해 다른 클래스에 있는 ..
calculate()
..
getQuantity()
정보를 많이 필요로 하는 경우 bmethod() getDiscountRate()
해결책
Move Method
16. 냄새
: 부적절한 친밀
특정 클래스 내의 메소드가 다른 Class A Class B
클래스에 있는 메소드(private 이 .. ..
어야 할)를 더 많이 사용하는 경우
amethod() xmethod()
bmethod() ymethod()
해결책
두 개의 독립적인 클래스가 엉켜 있다
면
Move Method
서로를 가리키고 있다면
Change Bidirectional Reference to
Unidirectional
중재하는 클래스가 없기 때문에 엉켜
있다면
Extract Hierarchy-> Hide Delegate
17. 냄새
: 주석
주석은 대부분 코드가 명확 치 않다고 판단될 때 쓰임
주석은 나쁜 코드를 유도함
해결책
코드의 일정 블록 설명
Extract Method
메소드가 하는 일 설명
Rename Method
선 조건 설명
Introduce Assertion
18. 냄새
: 긴 메소드
긴 메소드는 코드를 이해하기 힘들게 만든다.
주석을 달아야 할 필요를 느낄 때 마다 메소드로 분리
해결책
Extract Method
주의점
코드의 이해를 돕기 위해서는 코드의 의도를 잘 나타내는
이름 지어야
부적절한 이름을 가진 짧은 메소드 집합은 긴 메소드보다 이해하
기 힘들다.
19. 냄새
: 긴 파라미터 리스트
객체지향 코드에서는 파라미터가 많을 필요 없다.
문제점
이해하기 어려움
일관성 없음
변경이 많이 됨
해결책
이미 알고 있는 다른 객체로부터 값 얻어올 수 있음
Replace Parameter with Method
매개변수가 하나의 Object로 부터 나오면
Preserve Whole Object
매개변수 데이터가 하나의 논리 객체로 부터 얻어지는게 아닐 경우
Introduce Parameter Object
주의점
Caller와 Callee간의 데이터 종속성을 만들고 싶지 않을 경우 리팩토링을 피해야함
20. 냄새
: Switch 문
Switch문은 본질적으로 중복의 문제를 발생
타입 추가 시, 관련된 모든 Switch문을 수정해야 함
좋은 OOP코드의 특징은 Switch문이 비교적 적음
해결책
동일한 조건에 대한 Switch문이 여러 곳에서 사용됨
Step 1: Extract Method를 통해 각 조건 절에서 코드 추출
Step 2: Move Method를 통해 연관된 코드를 옳바른 클래스로 옮김
Step 3: Replace Type Code with Subclass or
Replace Type Code with State/Strategy 를 통해 상속구조 만듬
주의
Switch문의 중복이 많지 않다면 바꿀 필요 없음
20 Confidential 12/13/2011
21. 결론
리팩토링은 코드를 이해하기 쉽게 만든다.
리팩토링은 목표가 아니라, 다른 작업을 하기 위한 과
정이다.
리팩토링은 틈틈히 계속 해야 한다.
21 Confidential 12/13/2011