리팩토링 - 22, 23, 24

김상운(개발둥이)·2022년 8월 26일
1

리팩토링

목록 보기
17/17
post-thumbnail

들어가기

해당 포스팅은 인프런 백기선님의 '리팩토링'을 학습 후 정리한 내용입니다.



냄새 22. 데이터 클래스

Data Class

• 데이터 클래스: public 필드 또는 필드에 대한 게터와 세터만 있는 클래스.
• 코드가 적절한 위치에 있지 않기 때문에 이러한 냄새가 생길 수 있다.
• 예외적으로“단계 쪼개기”에서 중간 데이터를 표현하는데 사용할 레코드는 불변 객체로 데이터를 전달하는 용도로 사용할 수 있다.
• public 필드를 가지고 있다면 “레코드 캡슐화하기 (Encapsulate Record)”를 사용해 게터나 세터를 통해서 접근하
도록 고칠 수 있다.
• 변경되지 않아야 할 필드에는“세터 제거하기 (Remove Setting Method)”를 적용할 수 있다.
• 게터와 세터가 사용되는 메소드를 찾아보고 “함수 옮기기 (Move Function)”을 사용해서 데이터 클래스로 옮길 수 있다.
• 메소드 전체가 아니라 일부 코드만 옮겨야 한다면 “함수 추출하기 (Extract Function)”을 선행한 뒤에 옮길 수 있다.

냄새 23. 상속 포기

Refused Bequest

• 서브클래스가 슈퍼클래스에서 제공하는 메소드나 데이터를 잘 활용하지 않는다는 것은 해당 상속 구조에 문제가 있다는 뜻이다.
• 기존의 서브클래스 또는 새로운 서브클래스를 만들고 슈퍼클래스에서 “메소드와 필드를 내려주면 (Push Down Method / Field)” 슈퍼클래스에 공동으로 사용하는 기능만 남길 수 있다.
• 서브클래스가 슈퍼클래스의 기능을 재사용하고 싶지만 인터페이스를 따르고 싶지 않은 경우에는 “슈퍼클래스 또는 서브클래스를 위임으로 교체하기” 리팩토링을 적용할 수 있다

예제 코드

Employee

public class Employee {

    protected Quota quota;

    protected Quota getQuota() {
        return new Quota();
    }

}

Salesman

public class Salesman extends Employee {

}

Engineer

public class Engineer extends Employee {
}

설명

Engineer 클래스는 Employee 를 상속 받고 있다.

변경 사항

할당량을 의미하는 Quota 는 Engineer 클래스에서 의미 없고 Salesman 클래스에서만 사용하고 싶다.

리팩토링

Employee 클래스의 quota 필드를 우클릭 -> refactor -> pull members down... 을 눌러 서브 클래스로 필드를 내린다.

주의사항

서브 클래스가 Salesman, Engineer 두개 이므로 기계적으로 Engineer 에도 quota 필드가 작성되므로 삭제해주자.

냄새 24. 주석

Comments

• 주석을 남겨야 할 것 같다면 먼저 코드를 리팩토링하라. 불필요한 주석을 줄일 수 있다.
• 모든 주석이 나쁘다는 것도 아니고, 주석을 쓰지 말자는 것도 아니다.
• 주석은 좋은 냄새에 해당하기도 한다.
• 관련 리팩토링
• “함수 추출하기”를 사용해 설명이 필요한 부분을 별도의 메소드로 빼낸다.
• “함수 선언부 변경하기”를 사용해 함수 이름을 재정의할 수 있다.
• 시스템적으로 어떤 필요한 규칙이 있다면, “어서션 추가하기 (Introduce Assertion)”을 적용할 수 있다

리팩토링 43. 어서션 추가하기

Introduce Assertion

• 종종 코드로 표현하지 않았지만 기본적으로 가정하고 있는 조건들이 있다. 그런 조건을 알고리듬을 파악 하거나 주석을 읽으면서 확인할 수 있다.
• 그러한 조건을 Assertion을 사용해서 보다 명시적으로 나타낼 수 있다.
• Assertion은 if나 swtich 문과 달리 “항상” true이길 기대하는 조건을 표현할 때 사용한다.
• 프로그램이 Assertion에서 실패한다면 프로그래머의 실수로 생각할 수 있다.
• Assertion이 없어도 프로그램이 동작해야 한다. (자바에서는 컴파일 옵션으로 assert 문을 사용하지않도록 설정할 수도 있다.)
• 특정 부분에선 특정한 상태를 가정하고 있다는 것을 명시적으로 나타냄로써, 의사소통적인 가치를 지니고 있다.

예제 코드

public class Customer {

    private Double discountRate;

    public double applyDiscount(double amount) {
        return (this.discountRate != null) ? amount - (this.discountRate * amount) : amount;
    }

    public Double getDiscountRate() {
        return discountRate;
    }

    public void setDiscountRate(Double discountRate) {
        this.discountRate = discountRate;
    }
}

냄새

setDiscountRate() 메서드의 파라미터는 음수 값이 오면 안되기 때문에 주석을 작성하기 보단 assertion 을 사용해 표현하자

리팩토링

public class Customer {
....

    public void setDiscountRate(Double discountRate) {
        assert discountRate != null && discountRate > 0;
        this.discountRate = discountRate;
    }
}

notice!!

assertion 은 자바 컴파일 시 무시된다.
하지만 테스트코드 junit 과 같은 라이브러리 사용 시 코드를 확인하여 성공 여부를 파악한다.

profile
공부한 것을 잊지 않기 위해, 고민했던 흔적을 남겨 성장하기 위해 글을 씁니다.

0개의 댓글