"We want our customers to look at their hires on the web site, and also to do some transactions like de-hires and new hires."
"er ... I have not done any of that kind of stuff before."
"Yeah, but we need it."
"I have a friend who does active server pages, you know, intelligent web sites. You want me to talk to him, and get some idea of what it will cost?"
"My friend has let me down. I cannot find the guy. I have done some investigating in the mean time. I reckon that we can do this in Delphi, so it will use the same language as the other stuff we have done for you. I want to learn this Web stuff. If we keep to the same quote, can we do it my way?"
"That will be great! Go for it."
Some time later we had a web site up and running. This had to be hosted by a networking company, and we had a process in place for information to be transferred between the two systems. These things always get more complicated than you anticipate. For example:
"Our parent company has heard great things about the web site, and want a demo to show their clients."
"I have heard that one before. I assume that it is to run of a CD, and is not to install anything funny on the PC."
Delphi provides some great tools for building "Web Server" applications. I now had some idea of how they could be used to solve my client's problems. I decided to start with a little prototype site. I knew that it would take some trial and error to learn the best way to use this new tool. We would build a small site that would show one report, and capture the data for one dehire. Once we knew how to do these things, it would be easy to do more of the same.
Under these circumstances it is wrong to try and be elegant or sophisticated. Many things will need to be tried until those that work reasonably well are found. You then throw everything away and do a better job with what you have learned. You can then start trying to be elegant.
I had learned my lesson from the earlier experience. The database handling code was nicely isolated. This time I decided to use FlashFiler from TurboPower. This is now an open source project on Source Forge. It was more compatible with SQL Server, and the database engine could be compiled into the web program itself. This meant that I had no problems with installing all sorts of other software to get my demo to work on somebody's PC. What I did have to do was to make more changes to the architecture to handle different databases.
One difference between a Web program, and a Windows program is the interaction between the program and the user. In Windows, the program can react to anything that the user does. In a web program, this is generally not so. The program formats the web page, and eventually gets some information back. In the mean time lots of other things could have happened. The Windows program will only be interacting with one user at a time. It can remember things, like which form is being shown and how the user got there. A web program does not have that luxury. It will have to encode this information and save it somewhere.
There are two possibilities. The session information could be saved on the database, with a session key that accompanies the web page, and the information that makes its way back. The other is to put all of this information on the web page itself as hidden data that gets sent back with the user's response.
The information that comes back from the web is one or more lists consisting of Name=Value pairs. The first bit of sophistication is to merge these lists so that the program only needs to deal with one.
Another difference is that, with that version of Delphi, a web program is monolithic. You have to do everything in one place. It came as a huge shock to me that my favorite way of structuring a Delphi program, the use of data modules, was not allowed. A data module is like a form that does not get displayed. It is used for putting together components that access the database. It allows the programmer to separate those parts of the program that deal with the data from those that deal with the user. I would not be able to reuse any code from the Windows program. This was very bad. As soon as there are two pieces of code doing the same job they can start drifting apart. Changes are made to one, and not to the other. It is easy to say that the programmer should be disciplined, but a new programmer could work on the program who is unaware of the problem. It is much better to avoid the problem altogether.
Fortunately Borland provides the source code for their software. I could investigate the reason for this difference between Windows and the web. It turns out that a Windows program tends to have a single link to a database. A web program can spawn several copies of its working code to deal with several requests at the same time. Each of these copies will have its own link to the database. With this information I could find a way to use data modules in a web program.
Architecture changes for Windows and the web
If I wanted to reuse code from a Windows program in a web program, I would have to change the way I did things.
One way was to make my Windows forms look more like a web form, from the program's point of view. In particular, I would have to put all the data on the form into a list, so that the code that deals with it need not know the source of the data. It could come from either source. Conversely, the data should be moved from the list to the form. Fortunately it is easy to do this.
The code that processes the data, or stores it on the database would then look for it in this list.
I had heard of a similar solution. In some artificial intelligence programs, the components interact by looking at a "blackboard", a shared information store. They would put the results of their deliberations on the blackboard, or would change the information. In this way the components could co-operate without needing to know anything about each other. I decided to use the same metaphor.
Another change was to make the code work in a multi-instance environment. A Windows program would be the same as a web program, except that one instance is all that ever gets used.
Delphi started with a single database engine, the BDE (Borland Database Engine). This dated from the time when Borland was competing with Microsoft to establish a database connectivity standard. It was an alternative to ODBC (Open Database Connectivity). At the time there was only one way to connect to a database.
Since then Delphi has been changed to use multiple database engines, such as ADO (ActiveX Data Objects). Third party vendors added their own engines. All of this resulted in a proliferation of different data connectivity objects in the programs. When a programmer decided on a particular database engine, his program was filled with objects specific to that engine.
To keep the architecture flexible, so that the engine could be changed fairly conveniently at a later change, I changed the architecture to have drivers specific for each database engine. These hide database specific details for almost all database access code. Code that took advantage of specific features would be isolated to that it would be easy to find and replace with compatible code for another database engine.