Does this site look plain?

This site uses advanced css techniques

Background

One of my customers is a B2B connectivity company. It sells software that enables companies to send and receive their electronic business documents (purchase orders in EDI, etc.) over the internet to their trading partners. Internet communications are much cheaper than the legacy mode of EDI exchange, the VAN (Value Added Networks). VANs are private networks set up by large companies that provide electronic mailboxes for their customers and take care of routing and sending the EDI documents. Connectivity to the VAN is generally via modem only.

For my customer, it was critical to its success to support not only Internet communications, but also support VAN connectivity so that customers could replace their entire system with my customer's software. This new software would send documents over the Internet when possible, or fall back to dialup via VAN for trading partners when required.

The customer had some VAN connectivity in its product, but it was built on TAPI and ran on NT only, and it did not support popular file-transfer protocols such as ZModem. The customer wanted to have its product run on the major UNIX platforms and wanted more diverse file-transfer protocols.

Within a few weeks, I wrote a completely new VAN connectivity subsystem that fitted seamlessly into their product. Since the release of the new version of the customer's project that included my code, zero defects were found and the number of customers calling in with problems decreased dramatically. The customer considered my work to be an overwhelming success.

Technical Aspects

The library had several modules that I tried to abstract into higher-level C++ objects, and the cross-platform requirements (UNIX and NT) made this a bit more difficult.

Low-level Serial and Network I/O
[Serial I/O] I chose to use fully asynchronous I/O on both UNIX and NT platforms because this would give a much more responsive system: the program would not ever be completely blocked on a read or write operation. The library supported both serial and TCP/IP connections, and the either kind of IOChannel object could be passed to the worker objects transparently.
Modem dialers
[Modem Dialers] In order to call a remote VAN over a serial line, the software first had to dial them via the modem. This involved much more than just "dialing the phone" (which is fairly standardized via the Hayes command set): I also had to configure the modem properly. This mainly included parameters to set the modulation and compression methods to be used (V.32? LAP/M?), plus managing of flow control in the modem.
The modem objects were abstract, and adding new supported modems was straightforward and centralized.
VAN Scripting
[VAN Scripting] Once I'd connected with the target VAN - I supported a half dozen of them - the software typically faced with a menu system that was designed for a human operator, not a remote program. So I studied the menu systems and created custom scripting code that knew how to nagivate these menus, and it detected every error that I was able to simulate on my own.
I put the VAN scripting in a separate library to make adding a new one straightforward, and even within each VAN module, I had separate "login", "logout", and "transfer" methods. Each VAN had a descriptor object that informed the caller about the VAN's full name, which I/O methods were supported, the types of file transfers permitted, and the form of the login credentials required to gain access to the system.
File Transfer Modules
[File Transfers] Once connected and logged in, and after navigating the necessary menus, I had to actually transfer the data. This was done with a separate library of file-transfer modules, and I supported "raw" ASCII transfers, XModem (of a few flavors), and ZModem. These transfer objects had just a few entry points but plenty of status callback methods to allow the caller to know how the transfer was doing.
Test Scaffolding
[Test Scaffolding] Initially, it was not practical to test this library in the customer's server because of the long cycle time to build and install the server, and to submit a job for processing. Taking ten minutes for each test run would have made incremental debugging very tedious, so I instead created a test skeleton that would exercise the library as the customer's server would.
Working with the customer's software architect, we together defined a single "worker" object that would be the sole interface between their software and mine. It had a handful of high-level methods and a few status callbacks that would allow them to present a "transfer job" to this object, and it would handle everything. For months, both I and the QA department would use the tester tool to validate the various aspects of the system: do we dial all the modems correctly? do we navigate the VAN menus correctly? do the files transfer correctly? and so on. This provided dramatically lower cycle times for testing.

When, near the end of the process, I bolted my library into the customer's server, it compiled and ran correctly the first time. This was a testament to the good design of the interface objects, and neither the server engineer nor I really knew each other's code at all.