We've got a large legacy C++/ObjC++ application that could benefit from Null Object to replace thousands of redundant checks:
Thing *thing=CurrentSelection();
if (thing) thing->Drill()
If, when nothing was selected, CurrentSelection returned an instance of NotAThing
class NotAThing public: Thing
{
public:
virtual ~NotAThing(){}
virtual bool IsValid() const { return false;}
virtual void Drill() {}
};
We could get rid of almost all those checks. For a well contained class with few clients, Null Object can be a Good Thing. But this class is ubiquitous; dozens of classes depend on it and there are thousands of checks.
Can we incrementally refactor toward Null Object?
One approach would be to overload operators on NotAThing to lie:
We'd need to overload !, !=, and probably the casts to bool and int. And that still won't catch the explicit comparison "thing==nil". And I can already hear Scott Meyers (Effective C++) warning that this was lies madness. At minimum, it's a code smell.
And, while we might incrementally back out some of these and lean on the compiler in order to find and remove unneeded nil tests, I worry about coercion chains causing confusing and unexpected results -- one reason to avoid those casts.
On the other hand, there’s all those nil checks. They’re a code smell, too.
What’s the wisdom for large-scale refactoring toward null object? The mechanics in Fowler and in Kerievsky are sound, but they’re designed for classes with a small number of clients