Better Software - July/August 2008 - (Page 34) class Leaky { public: Leaky (unsigned int cap) : _capacity (cap), _counter (cap) {} void timer_tick(); bool got_event(); // Returns true if event threshold exceeded private: const unsigned int _capacity; unsigned int _counter; }; // Called from external clock function void Leaky::timer_tick() { if (++_counter > _capacity) _counter = _capacity; } // Called whenever an error event happens // Returns true if the event threshold is exceeded bool Leaky::got_event() { if ( counter > 0) return false; _counter = _capacity; // Reset to catch next error return true; } Listing 4 objects” [6, 7]. Each half-object allows some functions to be performed locally that would have been distributed. Because many operations can be done locally, the response is much faster and, overall, the necessary message traffic is reduced. A protocol is required to coordinate the half-objects and keep them in sync, as shown in figure 1. “I can see how this improves performance,” you say. “But doesn’t this create a different set of problems?” Yes, it does. Data and functionality are duplicated, and there are challenges with keeping the data synchronized. All solutions to problems involve tradeoffs. Patterns describe the consequences, both positive and negative, of using particular solutions. This is only one of many higher-level design patterns. You can use these patterns earlier in your design, before you write any code. As you implement these patterns, you often find yourself using the lower-level design patterns and language-specific idioms. Yet there are even higher-level patterns, as well. There are many architecture-level software patterns that describe the overall structure of the system, creating a view of the system shared by all developers. The best known architecture patterns include Layers, Pipes and Filters, Broker, and Model-View-Controller. In fact, I’m sure many of the systems you have worked on follow one or more of these architecture patterns. But I digress. Let’s get back to patterns of design. Patterns and Design Figure 1: A protocol is required to coordinate and sync half-objects but requires the surrounding program to keep track of time and call the object’s timer function at regular intervals, as shown in listing 4. A more general Leaky Bucket Counter manages the time ticks internally and is only slightly more complex. However, the simple example in listing 4 illustrates the pattern. The beauty of the Leaky Bucket Counter pattern is its simplicity. In addition, it is very low overhead, making it appropriate for high performance systems. 34 BETTER SOFTWARE JULY/AUGUST 2008 The half-ObjecT Plus PrOTOcOl PaTTerN The patterns I have shown you are much like the GoF patterns in that they are patterns that apply to detailed software design. There are also patterns at higher levels. For example, designers of distributed systems constantly deal with issues of performance and latency across networks when exchanging requests and responses. One way to alleviate this problem is to replicate some of the data in local address spaces, creating “halfwww.StickyMinds.com Now are you learning that the pattern world does not stop at the number twenty-three? Good. Although I showed you only four additional patterns, you should understand that there are many, many others. Discover and learn them, especially those specific to the domain in which you may be working. But there is another issue here. It may be even more important than expanding your pattern quantity horizons. You may start your work with this question, “I’m designing a system that does X. Which pattern do I use?” That’s the wrong question. You see, design patterns are not design, nor are they a substitute for design. 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.