Server-side programs: overview
Which languages were used?
Perl was chosen as the language in which the server-side programs would be written. The reasons were:-
- CGI (Common Gateway Interface) programs are traditionally written in Perl. Although this is not as true as it used to be with the advent of new competitors, it is still true enough to make this a valid approach.
- Perl is easy to learn. Unlike most other languages, Perl can be written in a procedural, functional or object-orientated manner, or even a mix. This makes it easy to learn whatever your background.
- Perl is powerful. Commands such as grep (where a procedure is applied repeatedly to every member of an array) mean that a Perl program can be powerful and short. Indeed, Perl programmers compete amongst themselves to produce the shortest code to complete a given task. This phenomenon is known as "obfuscated code" and is undisputable proof that Perl programmers really, really should get out more.
- Perl can glue things together. Unlike most other languages, Perl can interface easily with code written in other languages.
Program structure: design techniques
The initial approach was to split the task into logical parts and devote a program to each of these parts (see the seventh design principle: separation of concerns). A "junction" program would then be written to coordinate each program and pass info from one to another. This approach meant writing many small programs (see the first design principle: small is better than big). This meant that a technique had to be developed to pass information from one program to another. To do this involved the use of the Perl "qx" command (to pass info to another program) and the Perl ARGV construct (to get info from another program). An example would be as follows:-
- Calling program
$stufftocalledprogram = "Hello called program"; # set string
$stufffromcalledprogram = qx{./calledprogram $stufftocalledprogram}; # pass to called program & get reply
- Called program
$stufffromcallingprogram = ARGV[0]; # get string from calling program.
$stufftocallingprogram = dosomethingtoit($stufffromcallingprogram); # do something to it
print $stufftocallingprogram; # pass reply to calling program
What was the program structure?
The initial program structure looked like this:
- Junction program
- Get the nearest node to the origin postcode (call it the "O" node)
- Get the nearest node to the destination postcode (call it the "D" node)
- Get the time of departure.
- Compute optimum route between the two nodes.
- Add best guess for the route from the origin postcode to the "O" node at the start.
- Add best guess for the route from the "D" node to the destination postcode at the end.
- Translate the route into english.
- Create a WML page to hold that translated route.
- Display the page.
One problem surfaced when it came to routes that were too long for one page. In this case the route had to be truncated and a link to generate the next part had to be included. Now, to generate the next part requires the untranslated route, so the structure had to be changed to:-
- Junction program
- Get the nearest node to the origin postcode (call it the "O" node)
- Get the nearest node to the destination postcode (call it the "D" node)
- Get the time of departure.
- Compute optimum route between the two nodes.
- Add best guess for the route from the origin postcode to the "O" node at the start.
- Add best guess for the route from the "D" node to the destination postcode at the end.
- Page creation program
- Translate the route into english.
- Truncate the route if necessary
- Create link to generate next part if necessary (you need untranslated route to do this)
- Create a WML page to hold that translated and truncated route.
- Display the page.
Using our Perl techniques and design principles, it became relatively straightforward to create programs to do these tasks, and they were:-
- Junction.cgi
- Getnode.cgi
- Getnode.cgi
- Gettimestamp.cgi
- Planner
- Makeline.cgi
- Makeline.cgi
- Createwmlpage.cgi
- Translateintoenglish.cgi
- Truncate.cgi
- Getcontinuewml.cgi
- Getwmlheader.cgi & Getwmltrailer.cgi
- Print output
It should be noted that all the programs were written by the author with the sole exception of Planner. Planner was originally written by Oege DeMoor to handle Dijkstra’s algorithm and was heavily rewritten by the author (as per the fifth design principle: don’t keep a dog and bark for yourself) to handle the changes to the algorithm.
Where are these programs?
The programs can be found on the enclosed disk. Details of Planner and Dijkstra’s algorithm can be found in the chapter entitled "Calculation", and details of Translateintoenglish.cgi can be found in the "Parsing" chapter.
The technique: good or bad?
It should be pointed out that Perl programs aren’t normally written like this. Usually the smaller programs are written as subroutines and included within the junction program as .pl files. The technique does have the disadvantage of reduced portability (programs written this way in Unix won’t work in Windows, or vice versa) but does have the huge advantage that the programs are written as independent units and separately tested. This technique enables extraordinarily rapid development of smaller programs that are easier to understand, and is (in the author’s humble opinion), far better than the usual let’s-write-one-big-program technique. Most of the thesis programs were under one page long, had clearly defined input and output and were easily understandable. That’s good in anybody’s language.