[Chapter 17] 널 오브젝트 패턴

Seungjae·2022년 2월 19일
0

널 오브젝트 패턴


데이터베이스에 "A"라는 이름의 Employee객체를 요청했을 때, 있는 경우는 그 객체를, 없는 경우는 null을 리턴한다. 하지만 우린 null 테스트를 자주 잊어버리고 그로 인해 다양한 에러를 맞이한다.

그렇다면 null을 반한하지 않고 예외를 발생시키게 하면 에러 발생 위험을 감소시킬 수 있을 것이다. 하지만 try/catch 블록은 null을 검사하는 것보다 보기 싫을 수 있다. 또한 기존 어플리케이션에 적용하기도 까다로울 수 있다.

이럴 때, 널 오브젝트 패턴을 고려할 수 있다. 이 패턴을 사용하면 null 검사의 필요를 제거하고, 코드를 단순화할 수 있다. 예를 들어 Employee 인터페이스의 2개의 구현을 둘 수 있다. 해당된 Employee가 존재하면 일반적인 구현인 EmployeeImplementation을, DB에 없다면 모든 메서드가 아무 일도 하지 않는 NullEmployee를 반환하는 것이다.

before

Employee e = DB.getEmployee("A");
if (e != null && e.isTimeToPay(today)) {
	e.pay();
}

after

Employee e = DB.getEmployee("A");
if (e.isTimeToPay(today)) { // NullEmployee라면 당연히 임금 지급할 시기가 없을 것!
	e.pay();
}

또한 NullEmployee의 유일한 인스턴스를 저장하는 Employee의 정적 final 변수를 만들 수도 있다. 이때 익명 구현을 사용할 수 있다. 없는 직원을 익명 내부 클래스로 만드는 것은 인스턴스가 오직 하나임을 보장하는 방법일 것이다. 이렇게 되면 본질적으로 NullEmployee 클래스는 존재하지 않는다.

public interface Employee {
	public boolean isTimeToPay(Date payDate);
    
    public void pay();
    
    public static final Employee NULL = new Employee() {
    	public boolean isTimeToPay(Date payDate) {
        	return false;
        }
        
        public void pay() {}
    }
}

결론


이 패턴은 null이나 0을 반환할 수 있는 반환 값들을 검사해야한다는 생각을 전환시킬 수 있다. 이 패턴을 사용하면, 함수가 실패해도 항상 유효한 객체를 반환하도록 보장할 수 있다. 그리고 이때 실패를 나타내는 객체들을 아무일도 하지 않을 것이다.

책 외적으로...


그렇다. 널 오브젝트는 안티 패턴이다.

널 오브젝트 패턴은 안티 패턴으로 알려져있다. 이유는 단순하다. 이 패턴은 문제를 숨길 수 있다! 실제로 스펙상 존재해야하는 객체인데 null object가 되었다면? 이 상황에서 프로그램은 중지 되지않고 아무 예외도 안 던질 수 있다. 그리고 그 객체가 필요한 순간 갑자기 어디선가 문제가 발생할 수 있다. 그렇기에 이 패턴은 안티 패턴으로 알려져있다.

profile
코드 품질의 중요성을 아는 개발자 👋🏻

0개의 댓글