CURRENT ISSUE Contests
Feature Article
|
|
Issue #212 March 2008
LESSONS FROM THE TRENCHES
Do You Want to Do a Design?
Linked Lists
by George Martin
Start | Design Challenge | Database Design | Use A Linked List | Design Implementation | Code Review | Sources & PDF
DESIGN IMPLEMENTATION
So we now have a design. Let’s look at what we need to implement that design. I’m going to present the routines required using UML diagrams. Refer to the Resources section for Circuit Cellar articles about UML. UML has several diagrams to describe a system: class diagrams, use case diagrams, collaboration diagrams, state diagrams, activity diagrams, and implementation diagrams. Let’s start with the case diagram of the operations for the call out design (see Figure 1).
|
| Figure 1—This is the UML case diagram for the initial design of the call out code. |
I defined a class named CallOut. Don’t worry, we’re not getting into object-oriented programming (not just yet, he says, laughing hysterically). But I would put all the call out code in a file named CallOut.c. The CallOut.c file (class) has two static (think of them as private) variables and they are listed in the block below the name of the class. And the routines or procedures of the class are listed in the next block. I also added a note that you see attached to the class design.
Let’s look into the routines as they are defined right now. InitCallOutGroup(); initializes the CallOutGroup. It takes no parameters and returns no parameters. InitCallOutNumbsStruct(); initializes the CallOutNumbs structure. It takes no parameters and returns no parameters. AddCallOutGroupNumb(); appends a number to the end of the call out group. It takes the group number and a pointer to the string of digits to dial. It returns no parameters. DeleteCallOutGroup(); deletes all of the numbers in a call out group. It takes the group number and returns nothing. GetNextCallOutNumber() takes the current call out number and looks to see if there is a next number to dial. If so, it returns that next number. If not, it returns –1.
The question to ask ourselves at this point is this: can we complete the design with these routines? Let’s see. We need to initialize the CallOut data elements probably at the factory. Perhaps we’ll give the user a means to delete all the numbers. Then we need to delete a particular group, add numbers to a group, and get the numbers in order for a group. Looks like we’ve got it covered.
So, I sat down at the keyboard and fired up Borland’s C++ BuilderX on a PC. I’ve discussed this program in earlier articles. I created a new console application. I’m going to use a DOS window to create and run a test program to exercise the routines we’ve just designed. Nothing fancy here. It took me about four hours spread out over two sessions to get the code written and debugged. The file TestLinkList.c holds the main() routine and runs the test code. I created a file CalOutReports.c to generate printout type routines. These routines report the data in our internal elements out the DOS window for your viewing. And remember that you can pipe the output into a file for hard copy documentation purposes. I have a copy of that file (report.txt) in the files area. I also created a CCILinkedlist.h header file to hold system constants. So the meat of the solution is contained in the files CalOut.c and CalOut.h. Note that a better name for these files would be CallOut.c and .h. That’s part of a review process and more on that later.
If we look into CalOut.c, we’ll see the routines contained in the UML class diagram (see Table 3).
| Routines | Changes |
|---|---|
| InitCallOutGroup(); | No change |
| InitCallOutNumbsStruct(); | No change |
| DeleteCallOutGroup(); | No change |
| void FindFreeNumber(void); | New |
| void AddCallOutGroupNumb(INT8 Grp, INT8 *s); | No change |
| GetNextCallOutNumber(); | Deleted |
| INT8 GetFirstCallOutNumberIndex(INT8 Grp); | New |
| INT8 GetNextCallOutNumberIndex(INT8 Idx); | New |
| Table 3—Here’s a list of the routines in the final version of the code and an indication of what’s added, deleted, and changed. | |
Most of our original design had no change. One is deleted and some are added. What’s the story? The real world. As I was implementing the code, I saw problems with the design, easier ways to perform a task, or missing elements.
Look at FindFreeNumber. I need to look through the struct CallOutNumbs[] to find a free spot to save a new number to. “Well, of course,” you might say, but it escaped us at the initial design point. That one is not a big deal.
Next, look at the missing GetNextCallOutNumber();, which is replaced with the two routines INT8 GetFirstCallOutNumberIndex(INT8 Grp); and INT8 GetNextCallOutNumberIndex(INT8 Idx);. If you consider how the database is designed, we first need to look into the INT8 CallOutGroup[] array to see if there is a first number entered or if the group is empty. If there is a number, we can start using the forward linkages to keep finding the next number in the group. So we really needed this change, but it could create other problems in the system. Once again, these are the type of real-world issues that you come across. Now the next step is to redo the UML diagrams to keep them current with the tested design. I’ll leave that up to you.
