본문 바로가기
카테고리 없음

Clean Code

by keward 2024. 10. 17.

Getter를 지양한다.

필드를 private으로 숨겨놓고도 Getter를 public으로 하면 정보 은닉의 효과를 볼 수 없다.

 

Getter는 조회로 끝나지 않는 경우가 많다.

public void withdraw(long id, long amount) {
    Account account = accountRepository.findById(id).orElseThrow();
    long newBalance = account.getBalance() - amount;
 
    if (newBalance < 0) {
        throw new IllegalArgumentException("잔액이 부족합니다.");
    }
 
    account.setBalance(newBalance);
}

위의 과정은 계좌 인출을 위해 Account 객체에 잔액을 조회한 뒤 인출할 금액을 따로 계산하는 과정을 진행하고 있다.

그냥 인출할 금액을 전달하고 잔액이 충분한지만 판단하면 되는데 그걸 직접 확인하고 있다.

 

Getter를 통해 조건을 검사하면 변경에 취약해진다.

@Getter
class Customer {
    private long charge;
}
 
@Service
public class CustomerService {
    ...
    
    public void printMembershipGrade(Customer customer) {
        if (customer.getCharge() >= 100000) {
            System.out.println("Gold");
        } else if (customer.getCharge() >= 50000) {
            System.out.println("Silver");
        } else {
            System.out.println("Bronze");
        }
    }
    
    ...
}

 

코드 자체는 문제가 없다.

그런데 만약 요구사항이 변경되어 고객이 요금 대신 사용량과 단가만 갖게 된다면?

@Getter
class Customer {
    private long usages;
    private long unitPrice;
}

고객 객체에서 요금이 사라지고 단가와 사용량에 대한 정보만 남게 되었다.

이때 CustomerService는 고객 객체가 바뀌었다는 사실을 알지 못하게 된다.

위의 코드를 다시 돌리면 존재하지 않는 요금 정보를 조회하므로 컴파일 에러가 발생한다.

 

해결 방안

메서드를 통해 객체에 메시지를 보낸다.

private List<StudyCafePass> findPassCandidatesBy(StudyCafePassType studyCafePassType) {
		List<StudyCafePass> allPasses = studyCafeFileHandler.readStudyCafePasses();
		return allPasses.stream()
			.filter(studyCafePass -> studyCafePass.getPassType() == studyCafePassType)
			.toList();
	}

이 코드는 스터디카페 이용권 리스트에서 각각의 이용권을 Getter를 통해 꺼내서 이용권 종류를 비교하고 있다.

 

StudyCafePass.isSamePassType()

public class StudyCafePass(){

	private String passType;
    
    public boolean isSamePassType(StudyCafePassType passType) {
	return this.passType == passType;
	}

}

해당 클래스에 메서드를 선언하여 필드값을 매개변수로 받아서 지정해주면 

 

private List<StudyCafePass> findPassCandidatesBy(StudyCafePassType studyCafePassType) {
	List<StudyCafePass> allPasses = studyCafeFileHandler.readStudyCafePasses();
	return allPasses.stream()
		.filter(studyCafePass -> studyCafePass.isSamePassType(studyCafePassType))
		.toList();
}

다음과 같이 Getter 없이도 다른 객체에 매개변수를 통해 마치 메시지를 보내듯이 요청하여 private으로 된 필드 값을 가져올 수 있다.