상태와 행위를 한 곳에서 관리하라
객체지향을 접한 뒤로, 나는 상태와 행위를 한 곳에서 관리 하라는 이야기를 많이 들었다.
상태와 행위가 한 곳에 없으면 어떻게 되길래 안된다고 하는걸까?
직접 실험해보자.
주관적인 내용이 많이 포함되어 있습니다.
오늘도 역시 자동차 경주 게임이 예시다.
public class Car {
private int position;
public Car(final int position) {
this.position = position;
}
public void setPosition(final int position) {
this.position = position;
}
public int getPosition() {
return position;
}
}
위와 같은 자동차 객체가 있다고 해보자.
의외로 위 코드는 아무런 문제가 없다.
즉, setter와 getter가 정의되었다고 해서 항상 문제인 건 아니다.
문제는 행위가 정의되었을 때다.
public class Driver {
public void move(final Car car) {
int position = car.getPosition() + 1;
car.setPosition(position);
}
}
자동차를 움직이는 행위가 생겼다고 해보자.
이 책임은 Driver 객체가 가지도록 코드를 짰다.
그리고 main에서는 다음과 같이 실행이 잘 되는 것을 확인할 수 있다.
public class Main {
public static void main(String[] args) {
Driver driver = new Driver();
Car car = new Car(0);
driver.move(car);
System.out.println(car.getPosition()); // 1
}
}
이렇게 자동차 이동에 대한 행위가 Driver가 가지는 것이 왜 문제일까?
변경을 격리시키지 못한다
시간이 흐르고, 자동차 경주 게임에 대한 요구사항이 변경되어 자동차가 1칸이 아닌 2칸씩 이동한다고 가정해보자.
음.. 자동차에 대한 제약조건이 변경되었으니까, Car 클래스를 수정하면 되겠구나!
라고 생각할 수 있지만, 위 코드에서는 해당사항이 아니다.
Car 객체의 행위(move)를 Driver가 관리하고 있기에, Driver 객체가 수정되어야 한다.
즉, 변경을 격리시키지 못한다. 변경에 취약하다는 것은 객체지향 프로그램에서 큰 문제다.
public class Car {
private int position;
public Car(final int position) {
this.position = position;
}
public void setPosition(final int position) {
this.position = position;
}
public int getPosition() {
return position;
}
}
public class Driver {
public void move(final Car car) {
int position = car.getPosition() + 2; // 여기가 수정되어야 한다.
car.setPosition(position);
}
}
위 코드처럼, 상태와 행위를 한 곳에서 관리하지 못하면 변경가능성이 새어나가게 된다.
변경을 격리시키도록 개선해보기
그렇다면 Car 객체를 보다 변경에도 강한 내성을 가지도록 개선해보자.
public class Car {
private int position;
public Car(final int position) {
this.position = position;
}
public void move() {
this.position += 1; // 여기만 2로 수정해주면 된다.
}
}
위와 같이 상태와 행위를 한 곳에서 관리하는 경우, 더 이상 변경에 취약하지 않다.
Car 움직임에 대한 요구사항이 변경되더라도 오로지 Car 클래스만 변경하면 된다.
심지어는 아래처럼 position의 타입이 double로 바뀌는 경우더라도 변경가능성을 내부로 억제할 수 있다.
public class Car {
private double position;
public Car(final double position) {
this.position = position;
}
public void move() {
this.position += 1.5;
}
}
상태와 행위의 관계
상태와 행위는 한 곳에서 관리되어야 한다.
이 말은 변경을 격리하라는 말과 같다.
그렇다면 상태와 행위는 어떤 관계이길래, 한 곳에서 관리되면 변경을 격리하게 되는걸까?
내 나름의 결론부터 이야기하자면, 상태는 행위를 구현하기 위한 수단이기 때문이다.
객체가 중요한 이유는 행위를 가지고 있기 때문이다.
앞서 개선한 코드에서 Car 객체는 '이동한다'는 행위를 가진다.
이 '이동한다'는 행위를 가지기에 Car 객체는 의미가 있다.
만약 '이동한다'는 기능이 없는 Car 객체가 존재한다면, 자동차 경주 게임에서 의미가 있을까?
이처럼 객체에게서 중요한 것은 행위다.
그리고 자동차 객체에서 '이동한다'는 행위를 구현하기 위해서는 'position'이라는 상태가 필요하다.
즉, 상태는 행위를 구현하기 위한 수단이고, 행위와 행위를 구현하기 위한 수단이 나뉜다면, 당연히 변경을 격리시킬 수 없다.
결론
'상태와 행위를 한 곳에서 관리하라'라는 말이 존재하는 이유는 변경을 격리시키기 위함이다.
상태는 행위를 구현하기 위한 수단에 지나지 않음을 기억하자!
협력 속에서 객체는 행위로써 그 존재 의의를 인정받는다.
자동차 경주 게임에서 자동차가 '움직인다'는 기능을 가졌기 때문에 자동차 객체가 될 수 있듯이 말이다.
'객체지향' 카테고리의 다른 글
Layered Architecture란 (0) | 2023.04.21 |
---|---|
우아한 객체지향 정리 (조영호님) (2) | 2023.04.07 |
[객체지향의 사실과 오해] 6장: 객체 지도 (0) | 2023.02.23 |
[객체지향의 사실과 오해] 5장: 책임과 메세지 (0) | 2023.01.14 |
[객체지향의 사실과 오해] 4장: 역할, 책임, 협력 (0) | 2023.01.13 |