Download Ada in Action

Transcript
Chapter 4. Programming isn't Software Engineering
117
4.6.11. Keep I/O Routines Separate
Some of you may have read an article I wrote for the February 1986 issue of Dr. Dobb's Journal of
Software Tools. It contained a Version 1 of the PLAYING_CARDS package. That version contained
overloaded Put procedures that I have removed from the version 2. That's because I realize now that it was
a mistake to mix I/O routines with processing routines.
I used to believe I should always include I/O routines for new data types in the package that defines the
data types. I thought, "There's not much point in creating things if you can't input or output them." Well,
that's true, but it doesn't mean those I/O routines have to be in the same package. Version 1 used
TEXT_IO to write phrases like "Three of Hearts" to the screen. If I ever write a book of advanced Ada
examples, I will probably expand on this example by using a graphic interface to draw the cards on the
screen. TEXT_IO wouldn't be any use in that application. I shouldn't have to modify and recompile the
PLAYING_CARDS package just because I'm using a graphics package instead of TEXT_IO to display
Cards. If I change the output device or output method, I expect to have to rewrite I/O packages, but I
shouldn't have to rewrite any processing packages. Routines that turn pixels on and off (or write messages
to the screen) have nothing to do with routines that shuffle and deal cards. Therefore, they don't belong in
the same package.
4.6.12. A Limit to Reuse
The PLAYING_CARDS package body is shown in Listing 67. It's simple enough that it doesn't require
much explanation, but I do have to justify my Sort routine. People have spent years searching for the
ultimate sort routine, and here I've used this simple bubble sort. Isn't this a golden opportunity to reuse a
generic sort routine?
I'm all for reuse (the Draw_Poker program reuses RANDOM_NUMBERS, STANDARD_INTEGERS,
MONEY, DIM_INT_32, SCROLL_TERMINAL, and ASCII_UTILITIES), but sometimes reuse is more
trouble than its worth. It's true, a more exotic sort routine might be faster, but how long can it take to sort
five cards, even using the most inefficient routine? If I were sorting 5,000 cards, and speed were
important, then I might instantiate somebody else's super-optimized generic sort package. In this case it
was quicker to write thirteen lines of simple code than search for a reusable component that will do the
job.
If I already had a generic Sort routine that was easy to instantiate, and had established its reliability, of
course I would have used it. If I expected to need to sort large collections often, then it would make sense
to write (or buy) a generic sort routine, verify it, and use it in whenever I needed it. But this is the first
time in 22 years of programming that I've ever needed a sort routine, and I don't anticipate needing one
again in the next 22. A reusable sort routine isn't high on my priority list right now.
Writing a book is a lot like doing a real project. There is a deadline that has to be met, and you can't waste
your time searching for the most elegant solution when you already have something that works perfectly
well, especially when there are other things that aren't done yet. Looking for a generic Sort routine is
counterproductive.
4.6.13. Efficiency VCR Verifiability
The Sort routine also brings up another issue. Which is more important, efficiency or verifiability? The
answer depends on the situation. The Draw_Poker program runs so quickly I had to add some delay
statements to slow it down (I like to keep the player in suspense while the cards are being dealt), and it fits
easily in memory so I'm not concerned about size. In this situation I don't care at all about efficiency, but I
want to be sure the program works correctly, so this time it is an easy question to answer. Verifiability is
Ada in Action