📄 ch13.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
<META NAME="Author" Content="Steph Mineart">
<TITLE>Ch 13 -- Flat-File, Real-World Databases</TITLE>
</HEAD>
<BODY BACKGROUND="bg1.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/bg1.gif" BGCOLOR="#FFFFFF">
<P ALIGN="CENTER"><IMG SRC="sams.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/sams.gif" WIDTH="75" HEIGHT="24" ALIGN="BOTTOM"
BORDER="0"><BR>
<BR>
<A HREF="index-3.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/index.htm"><IMG SRC="toc.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/toc.gif" WIDTH="40" HEIGHT="40" ALIGN="BOTTOM"
ALT="TOC" BORDER="0" NAME="toc4"></A><A HREF="ch12.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/ch12.htm"><IMG SRC="back-1.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/back.gif"
WIDTH="40" HEIGHT="40" ALIGN="BOTTOM" ALT="BACK" BORDER="0" NAME="toc1"></A><A HREF="ch14.htm" tppabs="http://pbs.mcp.com/ebooks/0672310228/ch14.htm"><IMG
SRC="forward.gif" tppabs="http://pbs.mcp.com/ebooks/0672310228/buttonart/forward.gif" WIDTH="40" HEIGHT="40" ALIGN="BOTTOM"
ALT="FORWARD" BORDER="0"
NAME="toc2"></A></P>
<H2 ALIGN="CENTER"><FONT COLOR="#000077">Charlie Calvert's C++ Builder Unleashed</FONT></H2>
<P>
<H2 ALIGN="CENTER"><A NAME="Heading1"></A><FONT COLOR="#000077">- 13 -</FONT></H2>
<H2 ALIGN="CENTER"><A
NAME="Heading2"></A><FONT COLOR="#000077">Flat-File, Real-World
Databases</FONT></H2>
<P>
<H3><A NAME="Heading3"></A><FONT COLOR="#000077">Overview</FONT></H3>
<P>This chapter is the first of a "two-part series" on constructing real-world
databases. The goal is to move from the largely theoretical information you got in
the preceding chapter into a few examples of how to make programs that someone could
actually use for a practical purpose in the real world.</P>
<P>In several sections
of this chapter, I go into considerable depth about design-related
issues. One of the burdens of this chapter is not merely to show how database code
works, but to talk about how to create programs that have some viable use in the
real world. These
design-related issues are among the most important that any programmer
will ever face.</P>
<P>In this chapter, you will get a look at a simple, nearly pure, flat-file address
book program called Address2. This program is designed to represent the
simplest
possible database program that is still usable in a real-world situation. In the
next chapter, I will create a second address program, designed to be a "killer"
relational database with much more power than the one you see in this
chapter.</P>
<P>One of my primary goals in these two chapters is to lay out in the starkest possible
terms the key differences between flat-file and relational databases. The point is
for you to examine two database tools that perform the same task
and see exactly
what the relational tool brings to the table. I found, however, that it was simply
impossible for me to create a completely flat-file database design. As a result,
I had to content myself with a design that was nearly a pure example of
a flat-file
database. It does, however, contain one smaller helper table that is linked in using
relational database design principles. My simple inability to omit this table does
more than anything else I can say to stress the weaknesses of the
flat-file model,
and to show why relational databases are essential.</P>
<P>The second database program you see will contain a very powerful set of relational
features that could, with the aid of a polished interface, stand up under the strain
of
heavy and complex demands. You could give this second program to a corporate secretary
or executive, and that person could make some real use of it. The database shown
in this chapter, on the other hand, is meant to be a quick solution to a simple
problem.
One of the points you shouldn't miss, however, is that the database from this chapter
more than suits the needs of most people.</P>
<P>One of the classic and most commonly made mistakes is to give people too many
features, or to concentrate
on the wrong set of features. Those of us who work in
the industry forget how little experience most users have with computers. Even the
simple database program outlined in this chapter might be too much for some people.
Any attempt to sell them on
the merits of the database from the next chapter would
simply be an exercise in futility. They would never be willing to take the time to
figure out what to do with it. As a result, I suggest that you not turn your nose
up at the database shown in
this chapter just because it is not as powerful as the
one in the next chapter. Just because your typical Volkswagen is not as powerful
as an Alpha Romeo does not mean that the Volkswagen people are in a small business
niche, or even that there is
less money in VWs than in Alpha Romeos.</P>
<P>Here is a quick look at the terrain covered in this chapter:
<UL>
<LI>Sorting data.
<P>
<LI>Filtering data.
<P>
<LI>Searching for data.
<P>
<LI>Dynamically moving a table in and out of a read-only
state.
<P>
<LI>Forcing the user to select a field's value from a list of valid responses.
<P>
<LI>Allowing the user to choose the colors of a form at runtime.
<P>
<LI>Saving information to the Registry. In particular, you see how to use the
Registry
to replace an INI file, and how to save and restore information from and to the Registry
at program startup.
<P>
<LI>Using events that occur in a <TT>TDataModule</TT> inside the main form of your
program. That is, the chapter shows how
to respond to events specific to one form
from inside a second form. Or, more generally, it shows how to handle events manually
rather than let BCB set up the event handler for you.
</UL>
<P>After finishing this chapter, you will have learned
something about the kinds
of problems experienced when writing even a very basic database program that serves
a real-world purpose. The final product, though not quite up to professional standards,
provides solutions to many of the major problems
faced by programmers who want to
create tools that can be used by the typical user. In particular, the program explores
how to use BCB to create a reasonably usable interface.</P>
<P>You will find that the final program is relatively long when
compared to most
of the programs you have seen so far in this book. The length of the program is a
result of my aspiration to make it useful in a real-world setting, while simultaneously
providing at least a minimum degree of robustness. The act of
adding a few niceties
to the interface for a program gives you a chance to see how RAD programming can
help solve some fairly difficult problems.</P>
<P>Before closing this overview, I should perhaps explicitly mention that this chapter
does not cover
printing, which is certainly one of the most essential real-world
needs for a database program. I will, however, add printing capabilities to this
program in Chapter 17, "Printing: QuickReport and Related Technologies."
In fact, that chapter
will show how to add printing to all the useful database programs
that will be created in the next few chapters of this book. My plan is to isolate
the important, even crucial, subject of printing in its own chapter where it can
be properly
addressed.</P>
<P>You should also be sure you have read the readme files on the CD that accompanies
this book for information about the alias used in the Address2 program and in other
programs in this book. If you have trouble getting any of these
programs running,
be sure to check my Web site (<A HREF="javascript:if(confirm('http://users.aol.com/charliecal \n\nThis file was not retrieved by Teleport Pro, because it is addressed on a domain or path outside the boundaries set for its Starting Address. \n\nDo you want to open it from the server?'))window.location='http://users.aol.com/charliecal'" tppabs="http://users.aol.com/charliecal"><TT>users.aol.com/charliecal</TT></A>)
for possible updates.
<H3><A NAME="Heading4"></A><FONT COLOR="#000077">Defining the Data</FONT></H3>
<P>When you're
considering an address program, you can easily come up with a preliminary
list of needed fields:</P>
<PRE><FONT COLOR="#0066FF">First Name
Last Name
Address
City
State
Zip
Phone
</FONT></PRE>
<P>After making this list and contemplating it for a
moment, you might ask the following
questions:
<UL>
<LI>What about complex addresses that can't be written on one line?
<P>
<LI>Is one phone number enough? What about times when I need a home phone and a work
phone?
<P>
<LI>Speaking of work,
what about specifying the name of the company that employs
someone on the list?
<P>
<LI>What about faxes?
<P>
<LI>This is the 1990s, so what about an e-mail address?
<P>
<LI>What about generic information that doesn't fit into any of these
categories?
</UL>
<P>This list of questions emerges only after a period of gestation. In a real-world
situation, you might come up with a list of questions like this only after you talk
with potential users of your program, after viewing similar
programs that are on
the market, and after experimenting with a prototype of the proposed program. Further
information might be culled from your own experience using or writing similar programs.
Whatever way you come up with the proper questions, the
key point is that you spend
the time to really think about the kind of data you need.
<DL>
<DT></DT>
</DL>
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>Many books tell you to complete
your plan before you begin
programming. The only thing wrong with this theory is
that I have never seen it work out as expected in practice. <BR>
<BR>
Nearly all the real-world programs that I have seen, both my own and others, whether
produced by individuals or huge
companies, always seem to go through initial phases
that are later abandoned in favor of more sophisticated designs. This is part of
what Delphi and RAD programs in general are all about. They make it possible for
you to create a draft of your
program and then rewrite it. <BR>
<BR>
Think hard about what you want to do. Then get up a prototype in fairly short order,
critique it, and then rethink your design. Totally abandoning the first draft is
rarely necessary, but you are almost
certainly going to have to rewrite. For this
reason, concentrating on details at first is not a good idea. Get things up and running;
then if they look okay, go back and optimize. <BR>
<BR>
The point is that the process is iterative. You keep
rewriting, over and over, the
same way authors keep rewriting the chapters in their books. RAD programming tools
help make this kind of cycle possible. The interesting thing about Delphi is that
the same tool that lets you prototype quickly is also
the tool that lets you optimize
down to the last clock cycle. <BR>
<BR>
I don't, however, think most contemporary application programming is really about
optimization any more than it's about attempting to design a program correctly on
paper
before writing it. My experience leads me to believe that the practical plan
that really works is iterative programming. Think for a little bit and then write
some code. Review it, then rewrite it, then review it, and then rewrite it, and so
on.
Another, somewhat more old-fashioned name for this process is simply: One heck
of a lot of hard work!
<HR>
</BLOCKQUOTE>
<P>After considering the preceding questions, you might come up with a revised list
of fields for your program:</P>
<PRE><FONT COLOR="#0066FF">First Name
Last Name
Company
Address1
Address2
City
State
Zip
Home Phone
Work Phone
Fax
EMail1
EMail2
Comment
</FONT></PRE>
<P>This list might actually stand up to the needs of a real-world user. Certainly,
it
doesn't cover all possible situations, but it does represent a reasonable compromise
between the desire to make the program easy to use and the desire to handle a variety
of potential user demands.</P>
<P>At this stage, you might start thinking about
some of the basic functionality
you want to associate with the program. For example, you might decide that a user
of the program should be able to search, sort, filter, and print the data. After
stating these needs, you'll find that the user will need
to break up the data into
various categories so that it can be filtered. The question, of course, is how these
categories can be defined.</P>
<P>After considering the matter for some time, you might decide that two more fields
should be added to the
list. The first field can be called <TT>Category</TT>; it
holds a name that describes the type of record currently being viewed. For example,
some entries in an address book might consist of family members, whereas other entries
might reference
friends, associates from work, companies where you shop, or other
types of data. A second field can be called <TT>Marked</TT>; it designates whether
a particular field is marked for some special processing.</P>
<P>Here is the revised list, with one
additional field called <TT>Category</TT>,
that is used to help the user filter the data he or she might be viewing:</P>
<PRE><FONT COLOR="#0066FF">First Name
Last Name
Company
Address1
Address2
City
State
Zip
Home Phone
Work Phone
Fax
EMail1
EMail2
Comment
Category
Marked
</FONT></PRE>
<P>After you carefully consider the fields that might be used in the Address2 program,
the next step is to decide how large and what type the fields should be. Table 13.1
shows proposed types
and sizes. <BR>
<BR>
<B>Table 13.1. The lengths and types of fields used by the Address2 program. </B>
<TABLE BORDER="1">
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><B>Name</B></TD>
<TD WIDTH="96" ALIGN="LEFT"><B>Type</B></TD>
<TD WIDTH="59" ALIGN="LEFT"><B>Size</B></TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>FName</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">40</TD>
</TR>
<TR ALIGN="LEFT"
rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>LName</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">40</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>Company</TT></TD>
<TD
WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">40</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>Address1</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">40</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>Address2</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">40</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85"
ALIGN="LEFT"><TT>City</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">40</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>State</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">5</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>Zip</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">15</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD
WIDTH="85" ALIGN="LEFT"><TT>HPhone</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">15</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>WPhone</TT></TD>
<TD WIDTH="96"
ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">15</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>Fax</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">15</TD>
</TR>
<TR
ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>EMail1</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">45</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>EMail2</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">45</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>Comment</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Memo</TD>
<TD WIDTH="59" ALIGN="LEFT">20</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85" ALIGN="LEFT"><TT>Category</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Character</TD>
<TD WIDTH="59" ALIGN="LEFT">15</TD>
</TR>
<TR ALIGN="LEFT" rowspan="1">
<TD WIDTH="85"
ALIGN="LEFT"><TT>Marked</TT></TD>
<TD WIDTH="96" ALIGN="LEFT">Logical</TD>
<TD WIDTH="59" ALIGN="LEFT"></TD>
</TR>
</TABLE>
<BR>
<BR>
As you can see, I prefer to give myself plenty of room in all the fields I declare.
In particular, notice that I
have opted for wide <TT>EMail</TT> fields to hold long
Internet addresses, and I have decided to make the <TT>Comment</TT> field into a
memo field so that it can contain long entries, if necessary. The names of some of
the fields have also been
altered so that they don't contain any spaces. This feature
might prove useful if the data is ever ported to another database.</P>
<P>Now that you have decided on the basic structure of the table, the next task is
to work out some of the major design
issues. In particular, the following considerations
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -