Better Software - March 2009 - (Page 19) Code Craft using System.Collections; ArrayList list_of_colours = new ArrayList(); // note: untyped list_of_colours.Add(“Green”); list_of_colours.Add(“Yellow”); list_of_colours.Add(Int(3)); // oops! Error // We don’t declare any max function void even_better_example() { int a = 3, b = 10; int c = std::max(a, b); } Listing 7 Listing 3 using System.Collections.Generic; List list_of_colours = new List (); list_of_colours.Add(“Green”); list_of_colours.Add(“Yellow”); list_of_colours.Add(Int(3)); // doesn’t compile Listing 4 The original listing 5 version had yet another problem: The macro clobbered a name in the C++ standard library. This led to the even better solution shown in listing 7—Just use the built-in std::max function! It’s obvious in hindsight—the kind of thing you’d cringe about now but had no idea about back in the day. Design Decisions Did I really write that code in Perl? Did I really use such an inefficient sorting algorithm? Did I really write that by hand, rather than using a built-in library function? Did I really craft that awful interface for the module? This class of problem is typically very hard to repair without a major code rewrite. This highlights why it’s so important to make good design decisions up front and to ensure that your code has good modularity and is easy to change. Some time ago, I worked with a team of C programmers moving (actually, shuffling slowly) toward the brave new world of C++. One of the initial additions to their new codebase was called max and is shown in listing 5. (Do you know why we have all those parentheses? Post your answers in the comments section of my article on StickyMinds.com.) Much later, someone revisited that early code and, knowing more about C++, realized how distasteful it actually was. This person rewrote it in the more idiomatic C++ shown in listing 6. This actually fixed some very subtle lurking bugs, which are illustrated in listing 6. #define max(a,b) ((a)>(b)) ? (a) : (b)) void example() { int a = 3, b = 10; int c = max(a, b); } Listing 5 Bugs Perhaps this is what dragged you back to an old codebase. We’ve all been there: A new bug has been discovered that forces you to look at some archaic code. Coming back with fresh eyes uncovers obvious problems that you missed at the time. How could this old stuff ever have worked? Looking back over your old code is like a time-lapse code review, but it’s a valuable exercise. Perhaps you should take a quick tour through some of your old work. Do you like the way you used to program? It’s important to understand how times have changed, how the programming world has moved on, and how your own personal skills have improved over time. Perhaps you don’t have the time or opportunity to revise old code now, but knowing where you’ve come from helps to shape where you’re going in your coding career. Like the Ghost of Christmas Past, there are interesting cautionary lessons to be learned from our old code—if you take the time to look at it. {end} template inline max(const T &a, const T &b) { // No brackets needed! return a > b ? a : b; } void better_example() { int a = 3, b = 10; // this would have failed using the macro // because ++a would be evaluated twice int c = max(++a, b); } Listing 6 How does your old code shape up in the modern world? If it doesn’t look too bad, does that mean that you haven’t learned anything new recently? Follow the link on the StickyMinds.com homepage to join the conversation. www.StickyMinds.com MARCH 2009 BETTER SOFTWARE 19 http://www.StickyMinds.com http://www.stickyminds.com/codecraft11-2 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.