특정 값(가장 흔하게는 null이나 "미확인" 같은 표시값)을 만날 때마다 같은 처리를 하는 코드가 곳곳에 흩어져 있을 때, 그 경우를 대표하는 객체를 하나 만들어 공통 동작을 담는 패턴. null을 대표하면 널 객체(Null Object)라 부르며, 널 객체는 특이 케이스(Special Case)의 한 예다.
// before: 곳곳에 같은 검사
const name = customer === 'unknown' ? '거주자' : customer.name
// after
const unknownCustomer = Object.freeze({ name: '거주자', plan: basicPlan, isUnknown: true })
const name = customer.name- 검사 코드 대부분이 평범한 속성 접근이나 메서드 호출로 바뀐다
- 읽기만 한다면 위처럼 불변 리터럴 객체로 충분하고, 동작이 필요하면 메서드를 가진 클래스로 만든다. 데이터를 받아올 때 변환 함수에서 특이 케이스 객체를 끼워 넣는 방식도 있다
- 특이 케이스 여부를 꼭 알아야 하는 곳을 위해
isUnknown같은 속성을 남긴다 - 임시 필드(Temporary Field)가 비어 있을 때를 위한 대안 객체로도 쓴다
언어 차원의 대안으로 옵셔널 체이닝과 null 병합이 있지만, 그건 검사를 짧게 쓸 뿐 흩어진 처리를 모아 주지는 않는다. 다형성으로 분기를 없앤다는 점에서 조건부 로직을 다형성으로 바꾸기과 같은 계열이다.
출처: 『리팩터링 2판』 마틴 파울러 (원서 Refactoring, 2nd Edition) · refactoring.com: Introduce Special Case · Refactoring.Guru: Introduce Null Object · Martin Fowler: Special Case