NEXT STEP > 자바 플레이그라운드 with TDD, 클린 코드
자동차 경주 미션 중
해당 강좌의 피드팩 영상을 보면 객체를 객체스럽게 사용하도록 리팩터링 해라 라는 내용이 나오고 getter, setter 사용을 지양하라는 말이 나온다.
이것이 의미하는것은 무엇일까?
만약 자동차 경주 미션 중 Car라는 클래스를 추가한 후 name과 position을 상태 값으로 가지는 객체를 추가했다고 가정해 보자. 이 객체의 로직을 하나도 구현하지 않고, 인스턴스 변수에 대한 getter와 setter 메서드만 있는 경우가 있다.
public class Car {
private String name;
private int position = 1;
public Car(String name){
this.name = name;
}
public int getPosition() {
return position;
}
public void setPosition(int position) {
this.position = position;
}
public String getName() {
return name;
}
public void setName() {
this.name = name;
}
}
그럼 Car 객체를 활용하여 로직을 구현하면 아래와 같다.
public class Racing {
[...]
public int run(Car car) {
int num = random.nextInt(11);
int position = car.getPosition();
if (num >= 4) {
position++;
}
car.setPosition(position);
position = car.getPosition();
return position;
}
}
이 코드를 보면 Car 객체에서 position 데이터를 getter를 이용해 값을 얻고 로직을 처리한 후 setter를 이용해 값을 저장한다. Car 객체를 데이터만 들고다니는 구조체로만 사용하고 있으면 객체의 상태값을 바꾼다는 판단을 외부에서 하고있다.
즉, 객체지향 코드가 아닌 절차지향적인 코드 방식으로 로직을 구현한 것이다.
객체지향적인 코드는 상태데이터를 가진 객체를 본인이 컨트롤할 수 있어야 한다. 즉, 위 코드는 객체지향의 독립적인 객체 설계에 위배되었다고 볼 수 있다.
setter 메서드 사용을 자제한다.
인스턴스를 초기화한 후에는 값을 변경할 수 있는 setter 메서드를 생성하지 않는다. 가능하면 생성자를 이용해 초기화한다.사실 setter는 생성자를 이용해 대체가 가능하므로 아예 안 쓰고 구현하는 것이 크게 어렵지는 않다.
public class Car {
private String name;
private int position = 1;
public Car(String name){
this.name = name;
}
[...]
}
생성자는 필요에 따라 여러 생성자를 만들어 사용하면 된다.
상태 데이터를 get 하지 말고 메시지를 보내라.
public class Car {
[...]
public void moveCar(int ranNum) {
if (ranNum >= FORWARD_NUM) {
this.position++;
}
}
[...]
}
위에 코드처럼 직접 get 하여 로직을 구성하지 말고 상태값을 가진 객체 car가 직접 position의 상태값을 변경하는 로직인 moveCar 메서드를 구성한 후 객체에 메시지를 보냄으로서 로직을 처리해야 한다.
그럼 왜 getter는 직접 데이터를 변경하지 않는데 왜 메시지를 던져 처리해야 할까?
위 코드를 보면 getter메소드만으로 외부에서 객체의 상태를 변경하지는 못하지만, 그 결과값이 객체의 상태를 변경시키는데에 사용될 수 있다.
즉, 직접적으로 바꾸진 않지만 이것이 사용됨에 따라 외부에게 '상태값 변경에 대한 판단권'을 줘버리게 될 수 있다.
그래서 객체에게 메시지를 보내 로직을 처리하는 것은 상태값을 수정할지에 대한 판단을 외부가 아닌 상태값을 가진 객체에게 스스로 부여하는 것이다.
정리
결론적으로 아래와 같은 원칙에 따라 리팩토링을 진행하는 것이 중요하다.
상태를 가지는 객체를 추가했다면 객체가 제대로 된 역할을 하도록 구현해야 한다.
객체가 로직을 구현하도록 해야한다.
상태 데이터를 꺼내 로직을 처리하도록 구현하지 말고 객체에 메시지를 보내 일을 하도록 리팩토링한다.
그리고 상태 데이터를 가진다고 무조건 setter, getter 메서드를 만드는 습관을 버리는 것이 중요하다.
특히 getter에 경우 아예 안쓰는것이 힘들 수도 있다. 하지만 최대한 뒤로 미루고 익숙해진다면 아예 안쓰고 개발하는 연습도 필요하다.
Reference
해당 강의 피드백 강좌
https://tecoble.techcourse.co.kr/post/2020-04-28-ask-instead-of-getter/
'Language > TDD, 클린코드, 리펙토링' 카테고리의 다른 글
[클린코드] 4장. 주석 (0) | 2023.12.14 |
---|---|
[클린코드] 3장. 함수 (with SOLID) (2) | 2023.12.11 |
[클린코드] 1장 깨끗한 코드, 2장 의미있는 이름을 읽고 정리한 내용 (0) | 2023.12.07 |
[TDD] 테스트가 힘든 코드를 테스트 가능한 구조로 변경하기 (0) | 2023.08.29 |