Helping ordinary people create extraordinary websites!
GET OUR NEWSLETTER
Your Email:
 

Build a Perl/CGI Voting System

By Allan Peda
2005-07-05


Details: Hash keys

The use of hashed keys to create associative arrays in Perl allows on-the-fly development of complex data structures. When you combine this feature with the ability to store these (arbitrarily complex) structures in a binary DBM file, you can develop what amounts to a tiny database system. The missing component that allows all of this to work is provided by the MLDBM and MLDBM::Sync modules.

The MLDBM module allows complex Perl hashes to be almost seamlessly stored in a local file. The MLDBM::Sync module makes it possible to safely lock these file, using the $sync->Lock and $sync->ReadLock methods. After loading or saving the structure of interest, a subsequent call to the UnLock() method flushes I/O and unties the variable. (See the Perl documentation regarding the MLDBM::Sync module for more information -- man 3 MLDBM::Sync.)

Essentially, the logic flow is as simple as that shown in Listing 1.

Listing 1. Pseudo-code logic flow



1 unless( defined( $q->param( $vparm ) )){
2 # Display initial voting stuff here
3 # select a candidate
4 $ballotBox->printForm( $q );
5 } else {
6 # if vote is tallied, do _not_ mail a ballot
7 if( $castBallot->voteIsTallied( $q ) ){
8 print "Your vote has already been recorded"
9 } else {
10 #
11 # vote not tallied yet, check if we have a draft ballot on file
12 # and move the draftBallot into the castBallot object
13 #
14 if( $draftBallot->exactMatch( $q ) ){
15 # cast ballot
16 print $q->h2('Thank you, your vote has been recorded.');
17 # add the vote to the cast ballot db file
18 $castBallot->tallyVote( $q );
19 # sum up all votes
20 $ballotBox->addVotes( $castBallot );
21 $cc_msg->send();
22 } elsif ( $draftBallot->voter_is_okay( $voter_email )){
23 # Send e-mail to allow voter to confirm vote
24 $mime_msg->send()
25 } else {
26 print 'Only University ballots are acceptable';
27 }
28 }
29 }

Once I had decided what the underlying conditional flow would be, the only remaining task was to construct objects that would fit into this sequence of actions. As I noted previously, the necessary hash data structures were retrieved and updated using tie'd variables and MLDBM file locking. The objects used were more like smart structures than full-fledged objects; the data was passed between them in a way that paralleled the progress of a ballot from an initial draft to a final counted vote.

In other words, the list of ballots was used to construct a DraftBallot, which in turn was used to create the CastBallot and BallotBox classes. In this way there was minimal coupling to the main ballot CGI program.

On another tangent, while I understand that it is generally considered poor practice to have constructors that rely on external resources such as files (since they could fail and wind up in an unpredictable state), the code in this case was much easier to understand by doing just that. Since Perl doesn't rely on pointers, I can see no reason not to take advantage of this simplification.



Tutorial Pages:
» Using locked DBM files with CGI-driven forms saves client data without DBMS overkill
» CGI considerations: Simplicity vs. complexity
» Functional design considerations
» Details: Hash keys
» Details: E-mail gotchas
» Details: Not-so-secret ballots
» Details: File layout
» Details: Static vs. dynamic DNS
» Details: Is GET harmful?
» Other possible improvements
» Conclusion
» Resources


First published by IBM DeveloperWorks


 | Bookmark
Related Tutorials:
» Random subroutines in Perl
» Log Script Use
» Creating Perl Modules for Web Sites
» Bit Vector, Using Perl Vec
» Perl Range Operator
» Creating Perl Modules for Websites

Advertise with Us!


Tutorials Scripts Web Hosting Developer Manuals
Resources