[Refactoring] 5. 널 객체
- 컴퓨터공학과/그외
- 2015. 11. 18.
이번에는 널객체와 타입코드에 대한 이야기입니다.
5. 널객체
파일과 콘솔에서 로그를 기록하는 FileLog와 ConsoleLog 클래스를 구현합니다. 각각의 객체가 존재할 때 Write를 하는 LogService 클래스도 구현합니다.
LogService 클래스에서는 run 함수 안에서 FileLog가 null이 아니면 FileLog.write()를, ConsoleLog가 null이 아니면 console.write()를 하게 됩니다.
그런데! 같은 일(write())을 하는데 객체마다 한번씩 여러 번을 처리하고 있습니다.
????????????!!!!!!!!!!!!!!!!!!!! 배운거에요!!!!!!!!!!!!!
이럴 경우 강한 결합Tightly coupling 으로 OCP를 위배합니다. 다형 객체를 하나로 처리하기 위해서 부모 클래스가 필요합니다. 파일 로그와 콘솔 로그의 다형적 객체를 하나의 타입으로 처리하기 위해 부모 클래스 Log를 도입합니다. 리스코프의 치환 원칙 "공통 속성 값은 부모가 제공해야 한다."를 생각해보니 순수가상함수가 생각나시죠? 바로 강제화!
그리고 이는 서로 다른 클래스를 연결하는 인터페이스의 성향이 강합니다. 접두어 I를 붙여 ILog로 표현해봅시다.
5~9 라인과 같이 ILog 클래스(인터페이스)를 만들어주고 write()를 순수 가상함수로 만들어 자식 클래스에서 기능을 구현을 강제하도록 합니다.
FileLog, ConsoleLog는 모두 ILog를 상속받도록 하구요. 이렇게 하면 25 라인의 LogService에서 28, 29라인 대신 30 라인으로, 34 라인 대신 35 라인처럼 구현할 수 있게 됩니다.
!!!!띠용
그런데 여기서 39, 40 라인 if(pLog != 0)에서 Null 체크를 하게 됩니다.
지금이야 2번이지만 100번의 write를 한다고 하면 할 때마다 모두 널 체크를 해주어야되겠죠?
그러나 Null check를 자주 사용하는 것 역시 벧 스멜~
Null check가 계속되면 Null object를 만들어서 null check를 없애야 합니다.
♥ 널 객체를 도입해라(Introduce Null Object)
ILog 클래스에 null인지 체크하는 is_null()을 만들고 기본적으로는 false를 반환하게 하여 null이 아님을 리턴해줍니다.
class ILog
{
public :
virtual void write() = 0;
virtual bool is_null() { return false; }; // null인지 체크(default : not null)
};
그리고 ILog를 상속받는 NullLog를 만듭니다. 그리고 (부모클래스인 ILog에서 virtual로 구현을 했으니 무조건 구현을 해주어야하지만 하는 일은 없으니) write()를 물려받아 빈 몸체로 만들고, is_null()은 true를 반환하게 합니다.
class NullLog : public ILog
{
public :
void write() {};
virtual bool is_null() { return true; };
};
38 라인처럼 ILog* p = new NullLog를 사용하면 null인 객체는 NullLog에서 true를, null이 아닌 객체는 ILog에서 false를 반환하게 됩니다. if(pLog != 0) 없이도 null check가 가능한 것이지요.
<정리>
Null Check를 자주 사용하는 것은 Bed Smell!
>> Null Obejct를 사용하라.
※ 참고
우선 ILog 인터페이스를 만든 후에 → Null Check를 진행한 것처럼
♥ 리팩토링을 할 때에는 문제를 쪼갠 후, 하나씩 리팩토링해 나가는 것이 중요합니다.
♥ 또한 테스트 케이스를 작성해서 리팩토링 전의 결과와 후의 결과가 같은지 검증하는 것이 필요합니다.
'컴퓨터공학과 > 그외' 카테고리의 다른 글
IEEE Citation Reference. 참고문헌 표기법. (0) | 2020.03.15 |
---|---|
[Refactoring] 6. 타입 코드 (1) | 2015.11.18 |
[Refactoring] 4. 상속 (0) | 2015.11.18 |
[Refactoring] 3. 캐스팅 (0) | 2015.11.18 |
[Refactoring] 2. 인터페이스 (0) | 2015.10.29 |