백기선 님의 리팩터링 강의를 들으며 요약한 내용입니다.
18. 데이터 클래스
▶ 데이터 클래스 : public 필드 또는 필드에 대한 게터와 세터만 있는 클래스
- 코드가 적절한 위치에 있지 않기 때문에 이러한 냄새가 생길 수 있다.
- 예외적으로“단계 쪼개기”에서 중간 데이터를 표현하는데 사용할 레코드는 불변 객체로 데이터를 전달하는 용도로 사용할 수 있다.
public 필드를 가지고 있다면 “레코드 캡슐화하기 (Encapsulate Record)”를 사용해 getter/setter를 통해서 접근하 도록 고칠 수 있다.
(여기서 말하는 "레코드"는, public 필드로 구성된 데이터 클래스를 말한다)
변경되지 않아야 할 필드에는“세터 제거하기 (Remove Setting Method)”를 적용할 수 있다.
게터와 세터가 사용되는 메소드를 찾아보고 “함수 옮기기 (Move Function)”을 사용해서 데이터 클래스로 옮길 수 있다.
메소드 전체가 아니라 일부 코드만 옮겨야 한다면 “함수 추출하기 (Extract Function)”을 선행한 뒤에 옮길 수 있다.
19. 유산 포기
서브클래스가 슈퍼클래스에서 제공하는 메소드나 데이터를 잘 활용하지 않는다는 것은 해당 상속 구조에 문제가 있다는 뜻이다.
기존의 서브클래스 또는 새로운 서브클래스를 만들고 슈퍼클래스에서 “메소드와 필드를 내려주면 (Push Down Method / Field)” 슈퍼클래스에 공동으로 사용하는 기능만 남 길 수 있다.
서브클래스가 슈퍼클래스의 기능을 재사용하고 싶지만 인터페이스를 따르고 싶지 않은 경 우에는 “슈퍼클래스 또는 서브클래스를 위임으로 교체하기” 리팩토링을 적용할 수 있다.
20. 주석
모든 주석이 나쁜것이 아니다!, 좋은 냄새에 해당되는 주석 또한 있다.
다만 불필요한 주석은 제거하자는 의미이다.
시스템적으로 어떤 필요한 규칙이 있다면, "Introduce Assertion"을 적용하여 사용할 수 있다.
20 - 1) Introduce Assertion
종종 코드로 표현하지 않았지만 기본적으로 가정하고 있는 조건들이 있다. 그러한 조건을 Assertion을 사용해서 보다 명시적으로 나타낼 수 있다.
Assertion은 if나 swtich 문과 달리 “항상” true이길 기대하는 조건을 표현할 때 사용한다.
- 프로그램이 Assertion에서 실패한다면 프로그래머의 실수로 생각할 수 있다.
- Assertion이 없어도 프로그램이 동작해야 한다. (자바에서는 컴파일 옵션으로 assert 문을 사용하지 않도록 설정할 수도 있다.)
특정 부분에선 특정한 상태를 가정하고 있다는 것을 명시적으로 나타냄로써, 의사소통적인 가치를 지니 고 있다.
다만, 명확한 의사소통을 위해서 사용할뿐 기능적으로 의존하면서 사용하면 안된다!
21. 중첩 조건문을 보호 구문으로 바꾸기
일반적인 if ..(1).. else ..(2).. 문 에서 (1), (2)번은 둘다 동일하게 50:50으로 중요한 정도를 나타낸다.
하지만, 조건문에서 한쪽을 강조해야 하는 경우도 있다.
예를 들어 다음 코드를 살펴보자!
public class GuardClauses {
public int getPoint() {
int result;
if (isVip()) {
result = vipPoint();
} else if (isPlat()) {
result = platPoint();
} else {
result = normalPoint();
}
return result;
}
private boolean isPlat() { ... }
private boolean isVip() { ... }
private int vipPoint() { return 100; }
private int platPoint() { return 50; }
private int normalPoint() { return 10; }
}
getPoint()에서는 Plat인지? Vip인지? 에 따라 나뉘며, 둘다 아니라면 normal에 해당된다.
위 코드를 다음과 같이 변경하자!
public int getPoint() {
if (isVip()) return vipPoint();
if (isPlat()) return platPoint();
return normalPoint();
}
댓글