Putting It All Together

When first writing this part of this chapter, I thought that we had already covered everything needed to build a real application program that would allow the user to create, update, and find items in the database with reasonable ease and convenience. The main program for my first attempt at this was called hmtst7.cpp. When Susan tried it out and then read the code, it had quite an effect on her, as indicated in this letter she wrote to her sister.

Susan: I had another revelation over programming last night. After having read hundreds of pages of this book, Steve showed me the Home Inventory program that we are writing. Annie, it is the smallest little program that you can imagine. Just in DOS, and it is so simple. But I have just spent weeks tearing my hair out trying to understand how it all comes together, it is so complicated, and JUST SO HARD.

Then Steve shows me the program [running] and IT LOOKS LIKE NOTHING! I could not believe it. I just see this little menu on the screen and yet I know what is behind it. At least 1500 lines of code including 7 different header files. If you saw this program [run] you would laugh. It is just so basic. But if you saw what went into it you would die. It is nothing less than pure genius. As I told Steve yesterday it is like having a steak dinner but having not to just cook the meat, but having to go kill the cow. He corrected me, it is like having to make the gun first to kill the cow and invent fire and a grill to cook it.

You have to write everything, I mean all of it. That includes the meaning for = and all the other operators. Unbelievable. Then I looked at Windows 95 and said, then “If that little program takes 1500 lines of code, what does this take?” Steve said “About 5 million lines.” Computers look like they are technological miracles. And they are. But behind them is nothing but sheer, old fashioned, genius of man. And it is all hard work. It looks like a miracle but there is no magic.

If you wish, you can try the program yourself, but I won't be reproducing the code here because it turned out that it was far from finished. You see, as stunned as Susan may have been by the complexity of this program, she wasn't too amazed to tell me what was wrong with it and how it could be improved. Here's her “wish list”, along with my responses.

First Test Session: Change Requests and Problem Reports

  1. Presenting the menu options in different colors.

    Can't be done with standard C++ input/output functions.

  2. Showing the list of names below the menu rather than above.

    See below.

  3. Putting the menu in the center of the screen rather than at the top.

    These two changes became irrelevant after I redesigned the program to use the screen more efficiently.

  4. Sorting the items by name rather than by the order in which they were originally entered.

    Done, via a new HomeInventory::SortInventoryByName member function (but see later comments on problems with this function).

  5. Being able to move to the next matching item if there is more than one (on a partial field match).

    Wrote several HomeInventory member functions to assist in handling multiple matching entries (for more details, see “handling more entries than will fit on the screen”, below).

  6. Removing an item.

    Done.

  7. Making a list of categories and displaying it when adding a new item.

    Not done, for reasons indicated below.

While watching Susan use the program, I came up with my own list of problems that needed to be fixed and some other improvements in addition to the ones she mentioned above.

  1. The error message for an invalid entry is poorly formatted.

    Added functions for error reporting.

  2. An error in entering a numeric value isn't handled properly.

    Same as above.

  3. There's no indication to the user as to how the date or amount fields are supposed to be entered (YYYYMMDD and a number with a decimal point but no $ or comma, respectively).

    Added a note in the input prompt indicating proper data entry format.

  4. An invalid date entry (i.e., other than a valid YYYYMMDD date) should be detected and reported to the user.

    Added code to check for this problem: the date must be at least 19000101 (but see later discussion of problems with this solution).

  5. The user should be able to determine how many items are in the inventory.

    Added a line at the top of the menu indicating how many elements are currently in the inventory.

  6. Allowing the user to select an item from a list of all items that meet some criterion (e.g., name, description).

    Added selection functions as noted above for this purpose.

  7. Handling a list containing more entries than will fit on the screen at one time.

    Wrote a selection function in a new HomeUtility namespace to allow scrolling through any number of items.

  8. Continuing rather than aborting when an error is detected.

    Handled most of these problems by improved error checking in the code; further problems surfaced later and were noted where they occurred.

  9. Saving the data during the execution of the program.

    Not handled in this version of the program.

  10. Backing up the old database before writing over it.

    Not done; left as an exercise.

  11. If the user asks to delete an item, the program should ask, “Are you sure?”

    Done.

Amazingly, the hardest one of these turned out to be the “list of categories”. In fact, I didn't implement this at all because it would have required a fairly significant reconstruction of the structure of classes in the program. The problem with this seemingly simple request is that the category list would have to be generated in the HomeInventory member function (because each HomeItem has only one category value out of all those in use, not the entire list). However, the list would need to be used in the HomeItem classes because that's where the user needs to specify the category. Getting the data from the HomeInventory object to the appropriate HomeItem object would be difficult because the existing HomeItem functions don't have any facilities for doing this. While there are ways to solve such problems, they would take us too far afield to be worth the trip in this particular case, since the category listing is not absolutely essential to the usability of the program.

After finishing the above revisions to the program, I compiled it and tested it myself until I was satisfied that it worked. Then I had Susan give it another test. I fully expected that she would be happy with the new functionality and would find the program pretty much bullet-proof. Here are my notes from that second test session, along with my determination of the cause of the problem or question.

Second Test Session: Change Requests and Problem Reports

  1. Adding a new Music item with a bad date such as “1997/02/15” (instead of 19970215) caused the program to abort with a fatal error.

    This was caused by my forgetting to check the return value of the HomeItemBasic version of the input function when calling it from the corresponding HomeItemMusic function.

  2. The sorting algorithm used to put the items into alphabetical order sorts lowercase letters after uppercase ones. It should ignore case.

    This problem was caused by the use of <, which is case-sensitive, to compare strings. I fixed this by adding a less_nocase function to the xstring class and using that function in the sorting algorithm instead of <.

  3. If the user typed in an item number that was not valid, the program exited with an illegal vector element error message.

    I added code to check whether the item number was valid and to ignore an invalid number rather than end the program.

Susan had some other comments and questions after using this version of the program.

Susan: The Music items should be listed separately from the other items.

Steve: What if you want to see all the items in your inventory? That may not seem to make sense with CDs and furniture, but what about when we add the clothing, appliance, and other types?

Susan: I don't want them jumbled together.

Steve: Well, we could add separate functions for showing things of each type, but I'm not sure how valuable the discussion of all those functions would be. I know, I'll make it an exercise!

Susan: Okay. Now, I noticed that if you type in something illegal (like a bad date) you have to start over again rather than being able to fix it right there.

Steve: Yes, that's true. It would make another good exercise to add the ability to continue entering data for the same item after an error. Thanks for the suggestion!

Susan: As long as I don't have to do it. I also have some other questions about the dates. What if I inherited something old that was purchased before 1900? Also, what if I don't know the date when I bought something? Can I type in ???????

Steve: I'll make the starting date 1800 rather than 1900. As for using question marks to mean “I don't know”: that won't work because the input routine is checking for a numeric value. However, I'll change it so you can use 0 to mean “I don't know when I got it”. How's that?

Susan: That's okay. However, I noticed one more thing. It would let me type 19931822 (the 22nd day of the 18th month of 1993). Shouldn't it check for legal dates?

Steve: Yes, that would be a good . . . exercise!

After making all these changes, I recompiled and tested the program, then gave it to Susan to see what she could do with (or to) it. Here are my notes of that trial along with how I handled the points that came up.

Third Test Session: Change Requests and Problem Reports

  1. On a screen with only 25 lines, it was pretty easy to overflow the available space when editing a long item. This resulted in a very messy display.

    I changed the program to clear the screen before editing an item. Now the entire screen was available to display the item rather than the main menu being on the screen all the time.

  2. If the user typed something other than just hitting the ENTER key after a message that said “ENTER to continue”, the other keystrokes were interpreted as menu selections.

    I added code to ignore any keystrokes preceding an ENTER in that situation.

  3. When the user typed an invalid item number, the program just ignored it rather than giving any indication of an error.

    I added code to display an “invalid item number” message in such a situation.

  4. The routine that asked for an item number didn't handle backspaces correctly.

    I changed the routine to fix that problem.

  5. If there weren't any items matching the user's selection criterion, the selection area was blank with no other indication of what had happened.

    I added code to provide a “No items found” error message.

  6. The “category” field was pretty useless, as it couldn't be used for selecting items.

    I added a “select by category” menu item, which displays the category as well as the name of the item.

In addition to these changes, this version of the program also implemented a “crash protection” feature, which automatically saves the latest version of the database in a separate file every time a change is made to any item or an item is added or deleted. This might be a problem in terms of performance if the database gets to be very large, but I think it's worth it overall. Without such a feature, the user could spend an hour or two typing in data and then have a power failure (or a program bug for that matter) and lose all that work.

Another item that might be useful (especially with long descriptions), but isn't essential in getting the program to work, is the ability to edit a text field without typing it all in again. That's the topic of another exercise at the end of this chapter.

After making all of these changes and testing them to make sure they seemed to work, I went back to the well one more time. Here are the results of this go-round.

Fourth Test Session: Change Requests and Problem Reports

  1. If Susan typed in a category that didn't exist, the program aborted with a “virtual memory exceeded” error.

    The problem here turned out to be my attempt to format the category listing header. If the header was longer than the actual category names, the code calculated a negative number of characters of padding. Then it tried to create an xstring of that number of spaces by calling the xstring constructor that takes a number of characters as its argument. When this constructor called the new operator to allocate the space for the padding, it passed the negative number of characters along to new. However, new doesn't expect to get a negative argument as the number of objects to create, and so it interpreted that negative value as a very large positive number. When it tried to allocate that number of characters, the underlying memory allocation routines couldn't handle the request and terminated the program after giving that error message. I fixed this by correcting the formatting logic so that the program wouldn't ask for a negative amount of padding.

  2. The code to display an error if there were no items found wasn't working.

    I changed the “wait for CR” code to fix this.

  3. The name and category header wasn't lined up properly with the actual name and category entries for item numbers greater than 9 (i.e., more than one digit).

    I changed the formatting of the selection function to fix the width of the item number at 5 digits rather than as variable according to the size of the item number. This made it much easier to line the header up with the data.

Susan had another suggestion to make the program easier to use, as well as a question about the category listing function.

Susan: How about letting the user type the date in with the slashes, as YYYY/MM/DD?

Steve: That would make a good exercise too.

Susan: How does the category listing function know where to put the categories on the screen?

Steve: It goes through the items once to figure out how long the names are and once to do the formatting. Thus, by the time it does the formatting, it knows how long the longest item name is. We'll go over exactly how that works when we get to that function, SelectItemFromCategoryList (Figure 13.31 on page 965).

After making all the changes indicated above, I had Susan try it once more, with the following results.

Fifth Test Session: Change Requests and Problem Reports

  1. There wasn't any way to cancel the “Add item” operation if the user decided not to do that after starting the operation.

    I added code to allow ENTER to cancel the “Add item” operation.

  2. Susan wanted to know how she could use the “Find item by category” operation if she didn't remember which category she was looking for.

    Here is one of the rare times when a program has a desired feature that the programmer didn't think to add explicitly. As it happens, all you have to do is hit ENTER when you are asked for the category name, and it will include items from all categories. I changed the prompt to inform the user about this feature. Since this serendipitous feature also works when the user is asked for a description or name, I changed those prompts as well.

After all these changes, I finally had a program that seemed to work properly according to a representative user's expectations for it. We'll analyze this final version of the home inventory program in great detail in the next chapter, but first we should take a look at the development process that I've just described.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset