Better Software - July/August 2008 - (Page 32) hy is the number twentythree so special? It certainly isn’t the answer to the Ultimate Question of Life, the Universe, and Everything. And it isn’t the number of things that most people can hold in their heads at one time (that would be seven plus or minus two). Nor does it hold the significance of the numbers three, seven, twelve, and forty in Western religions. But among object-oriented software developers who consider themselves somewhat knowledgeable, the number is special—almost mystical. W Design Patterns Of course you know what I am talking about. There are twenty-three design patterns in the universe, right? They have memorable names, such as Observer, Singleton, Abstract Factory, and Visitor [1]. Thanks to the Gang of Four (GoF), these patterns have elevated software design and programming from an obscure craft akin to magic to a somewhat less obscure craft that merely borders on alchemy. Now don’t get all worked up that I dare to question the positive impact of the GoF patterns. To be sure, they have had a major impact on object-oriented software design throughout the world. However, because they have been so successful, too many programmers think that the GoF’s twenty-three design patterns are the only patterns in the world, or at least the only ones worth knowing. This notion is even reinforced in print. The otherwise excellent book Head First Design Patterns [2] discusses the Null Object pattern, but relegates it to “pattern honorable mention” status. It’s not a full-fledged pattern? By whose standard? I sense that you are dubious. “What is this Null Object thing?” you ask. “And why should I care? Surely it can’t be as good as Strategy, Template Method, or State.” Let me explain this pattern, and you will see its value. Then perhaps you will stop believing in the inviolability of the number twenty-three. problem it solves. “Some object behavior is executed only in the presence of some other object. If this other object is absent, the behavior is either to do nothing or to use some default value. Using explicit conditionals to check an object reference for null and then branching, however, introduces a great deal of repetition and complexity into the code” [4]. Surely you have seen such code—you are reading along and suddenly there it is—a check to see if an object (or reference or pointer) is null. If it isn’t, you continue on, but if it is, you must take some exceptional action, such as error handling. At best, this makes the code more difficult to read and understand. But it’s worse than that—multiple checks in different parts of the code often lead to repeated code that handles the null case. Worst of all, though, is that it is easy for the developer to forget to check for null. This is a ticking time bomb. The solution is surprisingly easy— “Provide something for nothing: a class that conforms to the interface required of the object reference, implementing all of its methods to do nothing, or to return suitable default values. Use an instance of this class, a so-called ‘null object,’ when the object reference would otherwise have been null” [4]. class WidgetBase { public: virtual void method() = 0; }; dling actions. Or Null Object may be a singleton, thus relieving the programmer of the responsibility of remembering to delete it when a real object is used. Null Object can be profitably used in factories (Abstract Factory, Factory Method); the factory returns a real object if the input conditions are valid, and a null object if the input conditions are invalid. By now you are beginning to see the value of Null Object. It makes the code more convenient to write and easier to understand. But Null Object has benefits beyond that. To illustrate, let’s consider the usual benefits of patterns. Why are the GoF patterns so popular? It is because they help solve the design problems we encounter again and again. If we need to encapsulate requests, the Command pattern is a convenient solution. If we have objects with different interfaces that must communicate, we can turn to Adaptor or Mediator. It makes design easier and, in many cases, facilitates code enhancement later by adding new subclasses or extending the functionality of our classes. In a few cases, a pattern might even help us write correct code. For example, Builder might help ensure that all components are properly constructed before use. The Null Object pattern goes beyond class RealWidget: public WidgetBase { public: void method() { /* do the appropriate stuff */ } }; class NullWidget: public WidgetBase { public: void method() {} /* does nothing */ }; Listing 1 The Null ObjecT PaTTerN Before I explain what the Null Object pattern is [3], let me describe the 32 BETTER SOFTWARE JULY/AUGUST 2008 The structure of Null Object is simple. Listing 1 shows a sample in C++. Listing 2 shows one way to use it. Of course, there are many variations. The methods of Null Object may actually do something, such as logging an error or taking appropriate error hanwww.StickyMinds.com these benefits. It explicitly improves the external quality of the software. It does this by directly addressing a very common source of user-visible bugs: handling empty objects. Let me illustrate with a story. A little while ago, I purchased something at a local depart- http://www.StickyMinds.com
For optimal viewing of this digital publication, please enable JavaScript and then refresh the page. If you would like to try to load the digital publication without using Flash Player detection, please click here.