독서이야기/엘레강트 오브젝트 - 새로운 관점에서 바라본 객체지향
[엘레강트 오브젝트] 3.3 인자의 값으로 NULL을 절대 허용하지 마세요
사랑꾼이야
2023. 3. 22. 23:41
반응형
이 내용은 엘레강트 오브젝트
를 읽으면서 정리한 내용을 포함하고 있습니다.
- NULL
- NULL 처리 방법
- 정리
- 관련해서 참고해볼 내용
코드 어딘가에 NULL이 존재한다면 커다란 실수를 저지르고 있는 것이라고 말한다. 사실, 전달할 객체가 없으므로 값이 없는 것으로 간주하세요
라는 의사를 표현할 수 있도록 사용자에게 진짜 객체 대신 NULL을 전달하도록 허용하는 것은 일반적인 방법이다.
NULL
NULL을 허용하는 find() 메서드를 구현하기 위해서는 다음과 같이 분기를 처리할 필요가 있습니다.
public Iterable<File> find(String mask) {
if (mask == NULL) {
// 모든 파일을 찾는다
} else {
// 마스크를 사용해서 파일을 찾는다
}
}
객체를 존중한다면 다음과 같이 변경해야 한다.
public Iterable<File> find(Mask mask {
if (mask.empty()) {
// 모든 파일을 찾는다
} else {
// 마스크를 사용해서 파일을 찾는다
}
}
더 개선한 코드는 다음과 같다.
public Iterable<File> find(Mask mask) {
Collection<File> files = new LinkedList<>();
for (File file : /* 모든 파일 */) {
if (mask.matches(file)) {
files.add(file);
}
}
return files;
}
- mask 객체를 존중했다면 조건의 존재 여부를 객체 스스로 결정하게 해야 한다.
인자의 값으로 NULL을 허용하면 mask == NULL
과 같은 비교문을 사용할 수 밖에 없다.
- 객체와 협력할 때마다 객체의 실체를 확인하는 것말고는
NULL
인지 여부를 판단할 수 있는 방법이 없다. NULL
여부를 체크함으로써 객체가 맡아야 하는 상당량의 책임을 빼앗게 된다.
NULL 처리 방법
OOP에서 존재하지 않는 인자 문제는 널 객체(null object)를 이용해서 해결해야 한다.
- 전달할 것이 없다면, 비어있는 것처럼 행동하는 객체를 전달하면 된다.
- 전달한 인자가 객체인지 NULL인지를 확인하는 점을 메소드 구현자에게 떠넘겨서는 안된다.
- 대신 항상 객체를 전달하되, 전달한 객체에게 무리한 요청을 한다면 응답을 거부하도록 객체를 구현해야 한다.
클라이언트가 여전히 NULL을 전달한다면 어떻게 해야 할까?
- 방어적인 방법으로 여기에서는 NULL을 체크한 후 예외를 던진다.
public Iterable<File> find(Mask mask) {
if (mask == null) {
throw new IllegalArgumentException(
"Mask can't be NULL; please provide an object.");
}
// 마스크를 사용해서 파일을 찾아 반환한다
}
- 개인적으로 선호하는 방법으로 NULL을 무시하는 것이다.
- 여기에서는 인자가 절대 NULL이 아니라고 가정하고 어떤 대비도 하지 않는다.
- 메서드를 실행하는 도중에 인자에 접근하면 NullPointerException이 던져지고 메서드 호출자는 자신이 실수했다는 사실을 인지하게 될 것이다.
정리
- 중요하지 않은 NULL 확인 로직으로 코드를 오염시켜서는 안된다.
- 메서드 인자로 절대 NULL을 허용하지 말아라.
관련해서 참고해볼 내용
Optional 을 통해서 표현하는 방법 또한 알아놓으면 좋다.
반응형