Nabil is the president of Optimum Solutions Inc., where he specializes in client/server and Forte development. He can be contacted at nhijazi@ optimum.org.
Many vendors have recently introduced packaged solutions to the object/relational problem (see accompanying text box entitled "The Object/Relational Problem"). Among the very best of these is Forte Express, from Forte Software in Oakland, California. Before we examine Forte Express, we need to briefly look at the Forte development environment.
Forte is a development tool for building distributed, multi-tier, client/server applications. Development in Forte consists of coding in Transactional Object-Oriented Language (TOOL), a 4GL that provides GUI capabilities, support for shared application services, and database access via a SQL subset of the TOOL language. TOOL is supported on most major GUI platforms (including Windows, MacOS, and Motif) and most RDBMSs (Sybase, Oracle, DB2, Informix, and others via ODBC).
Of course, many vendors provide a 4GL. What makes Forte different is how it handles partitioning and deployment. A Forte distributed application is developed as if it were one logical application to be run on one machine. The deployment environment is defined separately. Forte partitions the application into client partitions to be deployed on whatever client machines are in the defined environment, server partitions that contain the shared business logic to be deployed on application servers, and database partitions to be deployed on database servers. I'm impressed every time I deploy a Forte application. If you have ever had to distribute software over a network the hard way, then you'll appreciate the elegance of the Forte solution.
Forte is object oriented through and through, and everything in Forte is an object. It comes with large class libraries for GUI, non-GUI, and database-access development. Nevertheless, you have to deal with the object/relational problem on your own. You still have to design your data-access classes, your shared-services classes, and their architecture. You have to deal with the huge amount of data-access code that must be produced. This is where Forte Express comes in.
Forte Express is a visual tool for client/server application development that solves the object/relational problem by providing an architectural foundation for the solution, and then generating high-quality code for that solution. More specifically, Express generates the UI and database-access components of object-oriented, multitier applications. On the client side, Express supports Windows 3.1/95, MacOS, and OSF Motif. On the server side, Express supports OpenVMS, UNIX, Windows NT, Solaris, and others.
The steps in using Forte Express to produce the database application are:
To illustrate how you use Forte Express, I'll develop a classic database app--the order-entry application. This application is typical in that it is based on a relational-database schema of several interrelated tables and a front-end GUI application that supports the business process while maintaining a database. This class of application is by far the most common kind of client/server application today--RDBMS-based applications.
Figure 1 shows the OMT diagram for the business model produced by Forte Express from an existing database. I used the demo database that comes with Oracle (scott/tiger account). The database is almost identical to the tutorial database used in Express documentation but a bit more realistic. It has line-item totals and an order total.
The OMT notation for class diagrams is similar to the notation for Entity Relationship Diagrams (ERDs). Figure 1 says, in effect, that the business consists of customers, orders, items, and products. An Order object refers to a Customer object. An Order object is also an aggregate object for several component Item objects. An Item object refers to a Product object. Figure 2 is a simple application model produced quickly to prototype entering an order.
The application model consists of an Order window that has an Item window nested in it. By simply setting properties of the Order window and Item window in the application model, you can quickly produce a working application that looks like Figure 3.
Figure 3 was produced by requesting a Menu and Toolbar interface for the Order Window, a Button interface for the Item window, and requesting that the Item window layout be an array. The layout for the Order window was set to Form. This working prototype (produced in minutes) is almost usable to take orders. It lets you browse orders and items. It also allows you to insert orders and items within orders. It does not do much validation, nor does it help you look products up or enter orders for new customers.
The look and feel of the first prototype can be quickly changed by altering settings in the application model workshop. Simply changing the Form layout attributes for the Order Form from "across" to "down," and the number of rows displayed for the Item array from 5 to 8 in the Window Workshop generates the window layout in Figure 4.
Once I built the prototype and used it, I realized I needed the following customizations to make the application implement some business rules:
Generating identifiers is a simple server-side customization. You need to add a method to get the next customer number, order number, or item number from the database. A simple SQL Select achieves that.
Some of the customizations required a change to the application model. Looking up customers and products and providing a mechanism to add a customer required additional windows and controls in the application model--about an hour's work. Figure 5 shows the window for entering new customers, while Figure 6 shows the window for looking up products. Figure 7 is the application model to accommodate these requirements.
The customization to produce a line-item total is straightforward: You need to find out which event is posted when a field value changes. Add an event handler to handle the quantity-field change and the price-field change. When either changes, the event handler calculates the new product of the two and updates the item-total field.
The customization that proved tricky was updating the order total when any line-item total changed (that is, if an item's quantity or price changed). The Order window is a separate window from the Item window, which is nested inside it. The order total is the sum or all the item totals. You don't want to pass the whole array of item prices and quantities back to the order window when any price or item changes. A clean solution is to have the field-change event handler in the Item window post an OrderTotalHasChanged event that the Order window can watch for. Before posting the OrderTotalHasChanged event, the field-change event handler calculates the new order total, since it has access to the item array and all the item prices and quantities. The new order total is simply passed as one parameter of the OrderTotalHasChanged event. When the Order window handles the OrderTotalHasChanged event, it updates the order-total field. User-defined events and event handling in Forte are other powerful and distinguishing features of the tool.
I spent a month evaluating Express for a client, trying to determine whether it would enable a productivity gain of 100 to 500 percent over manual implementation via Forte alone. We concluded, after investigating both approaches, that using Express would give us the needed productivity boost. In addition, it produced robust, customizable, high-quality code. Express also provided a well-designed architectural framework that would have taken a substantial amount of time to develop on our own. Model-based development was also considered to be an additional benefit of using the tool. It allows you to concentrate on the desired functionality of the intended system at a level substantially higher than the coding level and much closer to the user's view of the system.
The major risk factor in using Express seemed to be the length of time customizations would take. This turned out to be more of a learning-curve issue. Using Express without customizing the generated code is an exercise in effective model-based development. You can do a great deal with careful data modeling, business-object modeling, and application modeling. Once you get comfortable with working at the business- and application-model levels, you will start thinking of ways to customize by altering the model, as opposed to customizing the generated code.
Customizing the generated Express code requires the application of advanced Forte programming techniques. The generated server and client code fit in a complex three-tier architecture. You must understand the architecture of the generated code, as well as the architecture of the supplied Express libraries. You must also understand the run-time object event dynamics. Once you know where to put which customizations, and how to code them, customization work can proceed more rapidly.
There are also process and management factors in implementing a rapid-development process utilizing Express. Rapid development is essentially a multiphase, incremental, successive refinement process.
One approach that seems well suited to development in Express is a three-phase technique. All screens for a given system or subsystem (categorized along data-model subject areas) would be rapidly prototyped to produce the first working version with minimal customizations. During Phase I, you log needed customizations in a tracking database (an Express database application) and resist the temptation to get into the code and do the customization. Senior developers and managers review logged customizations, classify and prioritize them, and schedule their implementation. Many customization requests would result in only a few distinct customizations. A large class of customizations can be accommodated via domain (type) customizations. Many are very similar to referential-integrity constraints that implement referential business rules. By waiting, you'll find that the customizations fall into predictable aggregations, so deferring them is quite beneficial in reducing the overall amount of customization work required.
In Phase II of the rapid-development process, all the screens undergo the first level of customization and migrate to a second working prototype. Only customizations critical to business functionality are accommodated in Phase II. Note that at all times, there would be working prototypes that can demonstrate progress.
In Phase III, final customizations (look and feel, behavior, and business rules) are done and the application is ready to be turned over to quality assurance.
The most difficult part of getting a developer to adhere to this process is to get the developer to resist being a perfectionist. Developers want to impress others with the quality of their efforts. A Phase I prototype is, by definition, rough and imperfect. You need to develop a concept of "good enough" and stick to it, while clearly understanding that quality is not being sacrificed--it is being postponed. Otherwise you risk having a whole bunch of little applications that are complete and perfect, but years behind schedule.
By staging and deferring customization work, you can blast through hundreds of screens implementing rough functionality at the beginning, while demonstrating concrete progress to management and clients.
Forte Express, coupled with careful modeling and a staged, incremental development process can provide a low-risk, minimal-cost approach for delivering large, complex applications on time and within budget.
I first encountered the object/relational problem in late 1987. I was at a point in my career where I was making one of those changes in direction we software professionals undergo every five years or so, when major paradigm shifts hit us directly. I'd had enough of databases, and wanted to make the switch to the wonderful new world of objects. Everyone was talking object-oriented this or that. I had been doing database work since 1976 and had played around with Modula-2 and objects a bit, but not in any intensive way. Thus, I could not count myself among the enlightened. I joined the software engineering staff of a large government think tank and plunged into object-oriented software engineering. My first assignment was to look into a problem everyone seemed to be having with interfacing object-oriented systems to SQL databases.
I did some preliminary research to see what the problem was and to survey the existing solutions. What I discovered was some really bizarre object/relational binding solutions dreamt up by government contractors--costing millions to the taxpayers and inflicting pain and suffering upon those attempting to use them.
The problem seemed to be simple enough conceptually: You need to find an interface mechanism that binds, yet separates, two different and somewhat conflicting paradigms. What seemed to thwart the solution in large organizations was a more political than technical issue. There were purists in both the object camp and the relational camp who managed to kill most good ideas with objections about the degree of either the object-orientedness of the solution, or its relational purity. The solutions that survived review by both camps tended to be more like political compromises drafted by Congress than good technical solutions.
Determined not to produce yet another political solution, but an engineering one, I sketched a simple, practical solution, based on the notion of interfacing objects and relations utilizing the abstraction central to each. If a relation is mapped to a class, and a row is mapped to an object instance, we would have a conceptual basis for the interface mechanism. There is no consensus that this is the best solution. For a different view of a solution, read any of C.J. Date's works.
I used the object-to-a-table idea as the basis for an object/relational binding and did some proof-of-concept development work using Ada and Oracle. I published the approach in a paper, "Design Models for Developing Database Applications in Ada: An Object-Oriented Approach to the Ada/SQL Interface Problem." Although the work was done for Ada, the approach is applicable to other object-oriented languages.
After I left government research work in 1989, I found my expertise in interfacing relational databases to object-oriented languages quite profitable. I worked on several large projects for a diverse group of clients ranging from large defense contractors to large Wall Street financial institutions. These projects needed interfaces between front ends developed in Ada, C, C++, PowerBuilder, and other 4GLs, to Oracle, Sybase, Informix, and other relational databases.
Over the years, I perfected my original solution and refined it so that a code generator could be used to produce all the data-access code needed based on a template for the data accesses required, as well as the database schema. From each CREATE TABLE script, the code generator produces a C++ class or Ada package (or, for C, header and compile files that encapsulate the table as an object), maps all the columns as attributes, and defines cursor operations on rows of the table. On a project that has hundreds of tables and thousands of columns, the data-access code could be hundreds of thousands of lines. The code generator would produce verifiably correct code for all the data accesses needed in hours.
On large client/server projects, the project can languish if the developers implemented a poor object to relational interface. On many projects where I was hired as a database consultant to look into "database problems," I have found a poorly designed object/relational data-access architecture.
I cannot emphasize enough the importance of a good solution to the object/relational problem. In my experience it is a major determining factor in the success of today's client/server projects.
--N.H.
Figure 1: Order-entry business model.
Figure 2: Order-entry application model.
Figure 3: Order-entry application (first prototype).
Figure 4: Order-entry application (second try).
Figure 5: Adding a new customer.
Figure 6: Looking up products.
Figure 7: Application model to allow adding customers and looking up products.
For More Information
Forte Software
1800 Harrison
Oakland, CA 94612
510-869-3400
http://www.forte.com