본문 바로가기
Programming/Java, Spring

getter/setter 없이 구현했는가? - 우아한테크코스 우테코 클린코드 #7

by Renechoi 2022. 10. 31.

3개 이상의 인스턴스 변수를 가진 클래스를 구현하지 않았는가? - 우아한테크코스 우테코 클린코드 #7

 

이전글에 이어 우아한테크코스에서 요구하는 클린코드 원칙들을 살펴본다. 

 


핵심 로직을 구현하는 도메인 객체에 getter/setter 사용을 지양해 캡슐화의 개념을 실현하라는 의미로 해석된다. 

 

이 지침은 DTO(Data Transfer Object)인 데이터 전달을 목적으로 설계되는 객체에 있어서는 적용하지 않는다. 이는 앞의 언급된 '핵심 로직을 구현하는 도메인 객체' 조건과 부합하는 내용이다. 당연히 데이터 전달을 위해서는 속성을 꺼내고 수정할 수 있는 getter와 setter가 필요할 것이기 때문이다. 

 

즉, 비즈니스 로직의 구현에 있어서는 필요한 내용을 해당 객체들이 착실히 구현하라는 객체 지향의 원리와 같은 맥락의 짗미이라 할 수 있다. 다른 말로, 객체의 정보는 다른 데서 처리될 것이 아니라 스스로 처리해야 하며, 그렇게 되도록 객체를 구현해야 한다는 것이다. 

 


프리코스를 하면서 이와 같은 코드를 작성하였다. 

 

if (pobiFirstNumber + 1 != pobiSecondNumber || crongFirstNumber + 1 != crongSecondNumber) {
   return -1;
}

 

이 코드의 문제점은 로직을 메인 메서드에서 구현하면서 동시에 리턴값도 설정해주고 있다는 뜻이다. 

 

이 문장의 의미의 해석은 간단하지만 문제는 이것을 별도의 객체가 아닌 메인 메서드에서 실행하고 있다는 점이다. 

 

	...

	if ( !doesPageContinue(pobiFirstNumber, pobiSecondNumber) || !doesPageContinue(crongFirstNumber, crongSecondNumber)) {
   		return -1;
   
   ...
}

private static boolean doesPageContinue(int FirstNumber, int SecondNumber) {
		return FirstNumber + 1 == SecondNumber;
	}

 

 

위와 같이 수정해보았다. 

 

이렇게 함으로써 나아지는 것은 page의 continuation을 판별하는 새로운 객체를 형성함으로써 역할을 분담하였고, 

호출 방식을 통함으로써 메인 메서드에서 if문을 굳이 해석할 필요가 없어졌다는 점이다. 

 

두번째는 변화에 쉽게 반응할 수 있다는 점이다. 

 

추후 continuation을 판단하는 별도의 기준이 생기더라도 이를 주도적으로 관리하는 메서드가 생겼기 때문에 이 부분의 메서드를 수정해주기만 하면 되며, 조건문의 코드에서는 해당 메서드에서 리턴하는 값만 받아 처리해주면 된다. 

 

 

객체의 정보를 객체가 직접 처리하는 로직을 구현하는 것과 관련해서 포비 캡틴님의 지침을 살펴보자. 

 

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

 

 

한편 getter는 필요에 따라 적절히 사용될 수도 있는데 객체의 값을 외부로 표현해주는 경우 getter 사용이 필요할 수 있다. 

 

컬렉션의 변조를 막기 위해 변조불가컬렉션으로 정의한다면 외부에서의 변조로부터 보호할 수 있으며 객체 지향 설계에 부합할 것이다. 

 

Collections.unmodifiableCollection(Collection<? extends T> c)

 

 

 

 

 

 

 

 

반응형