[하루기록] 22.12.15

지찬우·2022년 12월 15일
0

하루기록

목록 보기
2/10
post-thumbnail

Getter

오늘은 getter/setter에 대한 글을 봤다. 정확히는 getter에 대한 글이다.

Tecoble - getter를 사용하는 대신 객체에 메시지를 보내자

“객체에 메시지를 보내 객체가 로직을 수행하도록 하자”
Tecoble

객체 지향 프로그래밍은 객체가 스스로 일을 하도록 하는 프로그래밍이다. 객체는 다른 객체와 메시지를 주고받으며 협력한다. 객체는 메시지를 받으면 객체 그에 따른 로직을 수행하고, 필요하다면 객체 스스로 내부 상태값을 변경하기도 한다.

모든 멤버 변수에 getter를 생성하고 상태값을 꺼내 그 값으로 객체 외부에서 로직을 수행한다면, 객체가 로직을 갖고 있는 형태도 아니고 메시지를 주고받는 형태도 아니다. 또한 객체 스스로가 상태값을 변경하는 것이 아닌, 외부에서 상태값을 변경할 수 있는 위험성도 생길 수 있다. (나 : 캡슐화에 위반되는 행위라고 생각한다. 맞나..?)

이에 대한 예시를 하나 들어보자. (우테코 프리코스 3주 차 웹 백엔드 공통 피드백에서 가져왔다.)

public class Lotto {
    private final List<Integer> numbers;

    public Lotto(List<Integer> numbers) {
        this.numbers = numbers;
		}

    public List<Integer> getNumbers() {
        return numbers;
		} 
}

public class LottoGame {
    public void play() {
				Lotto lotto = new Lotto(...);

				// 숫자가 포함되어 있는지 확인한다.
        lotto.getNumbers().contains(number);

				// 당첨 번호와 몇 개가 일치하는지 확인한다.
        lotto.getNumbers().stream()...
    }
}

위의 코드는 객체가 로직을 갖고 있는 것이 아닌, 멤버 변수에 대한 get 메서드만을 가지고 있다.

데이터를 꺼내지 말고 메시지를 던져 로직이 수행되도록 구조를 바꿔 객체가 일하도록 바꿔보자.

public class Lotto {
		private final List<Integer> numbers;

		public boolean contains(int number) {
				// 숫자가 포함되어 있는지 확인한다.
				...
		}

		public int matchCount(Lotto other) {
				// 당첨 번호와 몇 개가 일치하는지 확인한다.
				...
		}
}

public class LottoGame {
		public void play() {
				Lotto lotto = new Lotto(...);
				lotto.contains(number);
				lotto.matchCount(...);
		}
}

상태를 가지는 객체를 추가했다면 객체가 제대로 된 역할을 하도록 구현해야 한다.
객체가 로직을 구현하도록 해야 한다.
상태 데이터를 꺼내 로직을 처리하도록 구현하지 말고 객체에 메시지를 보내 일을 하도록 리팩토링한다.

박재성 님

getter를 무조건 사용하지 말라는 말이 아니다. 출력을 위한 값 등 순수 값 프로퍼티를 가져오기 위해 어느 정도 getter는 허용된다.

하지만 Collection 인터페이스를 사용하면 외부에서 getter로 얻은 값을 통해 상태값을 변경할 수 있기 때문에 다음과 같이 UnmodifiableCollection을 사용해 외부에서 변경하지 못하도록 하는 것이 좋다.

public List<Integer> getNumbers() {
		return numbers; // X
}

public List<Integer> getNumbers() {
		return Collections.unmodifiableList(numbers); // O
}

그동안 코드를 짤 때 ‘getter는 무조건! setter는 되도록 사용하지 않도록!’이라고 생각하며 개발을 했었다. 하지만 오늘 이 글을 보고 한 번 더 생각해 보는 기회가 되었다. 적용을 잘 할 수 있을지 모르겠지만… 최대한 지키려고 노력해 봐야지

📎 “상태를 갖는 객체는 메시지를 받아 자신의 내부에서 로직을 수행해야 한다.”

profile
좋은 개발자가 되자.

0개의 댓글