|
February 2002 Using
C++ To Develop Posix-Compliant Apps One hidden asset in this
quest is the port of the GNU compilers done by Mark Klein. One of the
things that makes C++ attractive is that it links directly with the
IMAGE intrinsics. And code developed using the GNU compilers is
easily ported to another Posix-compliant platform. Most readers are aware that C++ is an object-oriented extension of the C programming language. Many readers may not be aware of object-oriented database design. We have an increasing need to provide the same functionality to all possible interfaces (CGI, XML, etc.). It is impractical to expect our interface developers to incorporate and maintain business rules in every conceivable interface as we did with our COBOL/IMAGE/VIEW applications. This is where object-oriented database management comes into play. We encapsulate the business rules into objects separate from the interface. The interface developers then need only be given an object, and that object in turn inherits all necessary business rules. C++ by itself isnt, of course, a database management system. So its objects dont exist beyond the instance of execution. We can, however, use our existing IMAGE database as a storage mechanism to allow our C++ objects to persist beyond the instance of execution. This interaction between
C++ and IMAGE is maintained through an IMAGE class library. It is
important that all interaction between the application and IMAGE be
done exclusively through this class library so that only this class
library need be modified to complete the port. Lets now get an overview of the IMAGE class library and how it works. We have a Base class. This contains methods for manipulation at the database level. This includes an openModify (DBOPEN mode 1), openRead (DBOPEN mode 5), lockBase (DBLOCK), unlockBase (DBUNLOCK), beginWork (DBXBEGIN), commitWork (DBXEND), rollbackWork (DBXNDO), and closeBase (DBCLOSE). We have a Set class. This contains methods for manipulation at the set level. This includes methods such as find (DBFIND), getChainedForward (DBGET mode 5), getCalculated (DBGET mode 7), setUpdate (DBUPDATE), and setPut (DBPUT) just to name a few. We would not use the Set class by itself because it has no knowledge of any data items. It would, instead, be used as a Base class to well-defined Set classes. We have a series of Item classes used to move data to and from the buffer contained within the Set class. We have an AlphaItem class for type X items. The length in characters must be specified when the AlphaItem class is instantiated. We have a ShortItem class for type I1 items. We have an IntegerItem class for type I2 items. We also have some custom items. We have a DateItem class which stores the date in the buffer in an arbitrary YYYYMMDD format in a type I2 field. We have a TimeItem class which stores the time in the buffer in an arbitrary HHMMSS format in a type I2 field. Item classes are attached to a Set class when they are instantiated.
The listing
below shows an example of a fully formed Set class specifically for
the ISSUES data set. You can think of the class definition for a
specific data set to be a container class because it contains Item
classes. We did not specify the key
path when we defined the ICIssuesSet class. In this particular
example we have a path via either the Part Number or the Reference
Number. The Key class to be used must be specified when the Set
class, which ICIssuesSet is derived from, has been instantiated. The listing that follows
is the ICIssuesAdd class responsible for the actual update if the
Issues data set. This is a transaction level class that the database
developers would make available to the interface developers. Once again, the database developers need to provide the interface developers with a single method. That includes referential integrity between datasets. Note that line 2 specifies that the ICIssuesAdd class shall inherit the properties of the ICRequirementsIssues and ICPartMasterIssues classes. The ICRequirementsIssues class (not illustrated) defines the referential integrity between the Requirements data set and the Issues data set. Line 25 executes a method that validates the existence of a requirements record for the specified Part Number and Reference Number. Line 36 executes a method that will adjust the quantity issued and quantity required of the requirement record in accordance with the issue. The ICPartMasterIssues class (not illustrated) defines the referential integrity between the Part Master dataset and the Issues dataset. Line 24 executes a method that validates the Part Number on the Part Master. Line 36 executes a method that will adjust the total quantity on-hand and the total quantity in demand on the part master record in accordance with the issue. Figure 1 illustrates the relationship
between these datasets. Our sample user interface
is a CGI program. One of the drawbacks to CGI programming is that it
is stateless and every transaction requires that a new process be
launched. Heavy transaction processing can easily bring a system to
its knees. But if high-volume transaction processing is not an issue,
then CGI programming is an attractive option. The use of C++ class
libraries simplifies the CGI application interface just like Transact
simplified the VIEW application interface. The listing below is a
complete CGI program written to process issues. The GNU C++ compiler is a powerful tool that is worthy of serious consideration. It can be compiled down to fully optimized native code that links directly with your legacy IMAGE databases. It allows us to modernize our applications through object-oriented design. And it is fully portable to other Posix-compliant platforms. Whether or not you
choose the GNU C++ compiler for development of portable applications,
the concept of developing Posix-compliant applications that gradually
displace your legacy applications should be given serious
consideration because it mitigates the risks inherent in
migrations. Copyright The 3000 NewsWire. All rights reserved. |