Depending on the language, calling a method on a variable which is null leads to errors, system crashes or related behavior. In order to avoid this, developers wrap the variable in null checks. Repeating such null handling logic in one or two places is not necessarily a problem, but sprinkling it over the entire codebase is less than ideal.
Code with many null checks is usually harder to read and comprehend. Null checks must also be repeated in all future code, so all developers have to be aware of duplicating the appropriate behavior.
Introducing a Null object, an object which represents the behavior in case of “null”, should usually reduce or at least keep the code size even. If the code size increases, it is usually a sign that a Null object is not necessary.
A Null object can rawly be implemented in two flavors. Either by sub-classing, or by implementing an interface. In the examples section, we will demonstrate both variants.
If you implement a Null object by sub-classing, the null handling behavior has to be implemented by overriding each time a method is added to the parent class which might be forgotten.
If you instead implement an interface, an error will be produced if the new method is not implemented.
Checklists present a proven order of necessary refactoring steps and are especially helpful for beginners.
If you feel comfortable with a refactoring, there is no need to follow each of the steps literally; you can often perform multiple steps at once or skip some.
We suggest to try the recommended order at least once; this will often provide new insights - even for seasoned developers.