Session E-BO

Advanced Business Objects

Kevin McNeish
Oak Leaf Enterprises


Contents

This session takes you beyond the basics of business objects into advanced topics of creating, distributing and using business objects in the real world. See how the new features of Visual FoxPro 6 Service Pack 3 can help you create business objects that can automatically adapt and scale to their environment; whether it's a two-tier, three-tier or n-tier architecture. Learn how to overcome the inherent slowness of DCOM. Learn to create business objects with crisp boundaries and a well-balanced load of responsibilities. During this session you'll see live examples of business objects at work in a variety of settings from the desktop to the Internet, serving up Visual FoxPro cursors, HTML, XML and ADO recordsets.

 

What is a Business Object?

A business object is a high-level abstract object that represents a person, place, event or business process. All applications have certain entities that are the “main” objects handled by the application. For example, if you are creating a point-of-sale application, the main business objects might be Customers, Invoices and Inventory. You can create objects in Visual FoxPro that represent each of these entities.

The use of business objects is not unique to the Visual FoxPro community. These powerful objects have been in use for some time in languages such as SmallTalk, C++ and so on. For more information on the use of business objects outside of the Visual FoxPro world check out the Object Management Group’s web site at www.omg.org.

Why Use Business Objects?

Encapsulation

Business objects allow you to encapsulate all of the characteristics and behavior of a real-world entity, such as an Invoice, in one class rather than spreading its functionality throughout your application's forms and control methods. Business objects make complex software systems easier to understand and create because they closely model real-world entities. There is a one-to-one correspondence between objects in the real world and objects within your software application.

Although this concept may be difficult for procedural programmers to grasp, once you understand it you’ll never want to go back! Business object encapsulation makes the job of analysis, design, software construction and maintenance far easier than procedural techniques.

Reusability

One of the greatest benefits of using business object is code reusability. When you place code in the method of a form, you can only access the method from within that form. For example, if you have an Invoice form in your application, you can add a CheckCreditLimit()method to the form that can be used to check a customer’s credit limit. However, this method is only available when the Invoice form is instantiated.

In contrast, if you put the same method in a business object, as shown below, you can drop the business object on any form and have full access to all of its functionality:

Scalability

Although software reuse within a single application is a good thing, it doesn’t stop there. Business objects allow your application’s logic to be reused in many different software products! This is possible because business objects can be compiled into Active-X Automation servers that can be accessed by any product that knows how to talk to COM (i.e. Visual Basic, Microsoft Office products).

In order to understand how this works, we need to define multiple tier architectures. We’ll look at single, two, three and n-Tier architectures and see how business objects fit into each model.

Business Objects in Single-Tier Architectures

A single-tier architecture consists of a program running on a user’s machine that accesses a database on the same machine or a mapped network drive. All of the processing takes place on a single machine—the user interface, business and data processing.

This architecture encompasses the way most Visual FoxPro applications are configured…a Visual FoxPro executable runs on a workstation(s) and accesses Visual FoxPro data on a local or network drive.

 

In this model, software applications contain the user interface, business processing and data processing. Business objects are instantiated and run within the application.

 

Business Objects in 2-tier Client/Server

In a two-tier client-server model, the work (and associated processing overhead) of storing and retrieving data is moved off of the workstation onto a dedicated database server. This is distributed computing in its simplest form.

This architecture exists in systems where a VFP application is running on a workstation(s) and is accessing a client-server database such as Oracle or SQL Server that is running on a database server. In this model, the software application still contains the user interface, business processing and data processing. Business objects are instantiated and run within the application.

 

Business Objects in 3-Tier Client/Server

 

Three-tier client-server helps ease network traffic by placing an application server—another physical server that manages network traffic—between the workstations and the database server.

This model allows us a great deal of flexibility in deciding where to place the application’s business processing. You can move virtually all of the business processing off the workstations and onto the application server—or leave the majority of the business processing on the workstation.

When business objects are compiled as Active-X automation servers, you can create a three-tier system architecture in which the business objects are instantiated on an application server via Microsoft’s COM (Component Object Model).

In a three-tier architecture, the user interface or presentation layer resides on tier 1. This can be a Visual FoxPro program, a Visual Basic program, a Microsoft Office product or any software that knows how to talk to COM objects. Tier 2 contains business objects which contain the majority of an application’s logic. This is the key to software reuse across multiple software applications. Tier 3 is where an application’s data resides. It may be Visual FoxPro, SQL Server, Oracle, or any database that has an ODBC driver. In this type of design, any component can be swapped out in an architecture that is far more flexible, extensible and maintainable.

Accessing Business Objects Via the Internet

Just about every Microsoft product can instantiate and use COM objects. Microsoft’s Active Server Pages technology is no exception. The ability of an ASP page to instantiate a COM object is what allows applications to be accessed via the Internet. If you place the majority of your application logic in business objects and make them accessible as COM objects with an Automation Server, you have ready-made Internet access to your application.

Placing Application Logic in Business Objects

What we have discussed so far brings us to a very important conclusion:

The majority of an application’s logic should be placed within business objects!

 

One of the biggest mistakes developers make is placing the majority of their application logic in the user interface. This presents a real problem when moving an application to a multi-tier architecture. Application logic must be removed from the user interface and placed into business objects.

However, if you place the majority of an application’s logic in business objects, you will create an application that is far more flexible, extensible and reusable…without a great deal of additional effort.

Logical 3-Tier System Architecture

Even if you’re not ready to create a true three-tier architecture today, using business objects that logically partition your application logic makes the step to true three-tier architecture much easier. As shown below you can create a logical three-tier architecture.

In a logical three-tier architecture, business objects exist as a second tier within the application. This maintains a degree of separation between each tier. Business objects provide a buffer zone between an application’s user interface and its data. Business objects are responsible for loading, unloading and manipulating data. This allows you to change your application’s data source in tier 3 without changing the application code! If you adhere to the above model when writing your applications, and maintain the separation between each tier, it provides a much easier transition to truly distributed applications.

Identifying Business Objects

How do you identify the entities in your application from which business objects should be created? This involves object-oriented analysis and design. There are many different object-oriented methodologies to choose from. At Oak Leaf Enterprises we use the Unified Modeling Language as well as portions of Rational Software’s Unified Process (see my articles in the January and February ’99 issues of FoxPro Advisor for more information on the Unified modeling language). Whichever methodology you choose, you will eventually end up with a definition of the characteristics, responsibilities and collaborations of your business objects.

Once you have completed this portion of the Analysis and Design, you can begin constructing business objects. You can create properties and methods on your business objects that correspond to the characteristics and responsibilities captured in your analysis and design.

Creating a Well-Designed Object Model

Realizing that you should use business objects in your applications is the easy part. The more difficult part is deciding which business objects to create and which responsibilities to assign to each. For ideas on how to design your object model, it’s a good idea to study existing models found in readily available products such as Microsoft Office. For example, the illustration below shows the object hierarchy of Microsoft Outlook.

To learn more about the properties and methods of these objects, do the following in Outlook:

  1. Open any item except a note
  2. On the Tools menu, point to Forms, and then click Design This Form
  3. On the Form menu, click View Code.
  4. On the Help menu, click Microsoft Outlook Object Library Help.

A good visual depiction of a well-designed object is that of a hard, solid sphere with several access ports that require standard connectors. Keep in mind that when you are creating a business object, you are creating an API that you or another developer will have to use in the future

Business Objects and User Interface

By their very definition business objects contain no user interface logic. They do not display messages or interact with the user interface in any way. This allows them to be scalable to the widest variety of platforms—including the Internet. If your business objects contain logic that requires a specific kind of user interface, it hampers your flexibility in tier 1. This conceptual user interface restriction is physically enforced by Visual FoxPro when creating in-process .dlls. In Visual FoxPro 6, if you attempt to create a user interface in an in-process .dll, Automation generates an error.

 

The Anatomy of Business Objects

 

As shown in the UML class diagram to the right, a well-designed business object is composed of two major components—a User Interface component and a Data-Centric component.

UI-Centric Object

The UI-Centric object is the only portion of the business object which clients reference directly. It contains the majority of the application logic. It is responsible for dynamically instantiating the Data-Centric object at run time.

The UI-Centric portion of the business object can be dropped directly on a form or can be instantiated dynamically as a Visual FoxPro or COM object.

Data-Centric Object

The data-centric portion of the business object handles the data-related responsibilities of the business object including navigating, saving and deleting records. It is instantiated by the UI-Centric portion of the business object  in one of the following ways:

  1. Directly from a VFP class library
  2. Via COM
  3. Via DCOM

Flexibility and Scalability

Using composition to divide the major functionality of the business object into two main parts provides a great deal of flexibility. For example, it allows the data behavior to be easily changed—a family of data-behavior objects can be created and interchanged as needed.

Composition also provides business objects with tremendous scalability. The UI-Centric object can instantiate the Data-Centric object directly from a Visual FoxPro class or as a COM object from an Automation Server. The Data-Centric object can also be distributed to another machine on the network and instantiated via DCOM. Since clients interface directly with the UI-Centric object the scaling of the Data-Centric object is completely transparent.

 

Architecture Details

As shown in the UML class diagram to the right the business object also contains :

  • Data Session object
  • Data Environment object
  • Business Rules object

Data Session Object

The data session object allows business objects to have a private data session. This is useful in COM environments so that multiple instances of business objects do not suffer from contention problems.

Data Environment Object

The data environment class is used to load and unload data.

Business Rules Object

The business rules object enforces business rules that pertain to the entity represented by the business object. Business rules can be checked at the UI level before data is sent to the back end.

Business Objects as a Data Conduit

Getting around VFP’s Data Environment Limitations

In Visual FoxPro, a Data Environment describes the views, tables and relationships that are opened when you run a form or report. However, the default Visual FoxPro Data Environment class has two big limitations:

  1. Data Environments do not exist outside of forms or reports
  2. Data Environments hard code your data access

o they can load the data they need wherever they’re used.  The second limitation is an important issue affecting scalability. By default, Visual FoxPro forces you to drag specific tables or views into a data environment, thereby hard-coding your data access. For example, if you drag a Visual FoxPro “Invoices” table into a form’s data session, what happens when you move to client-server? You must go back and change the application to work with client server data.

Visual FoxPro Views—The First Degree of Separation

Visual FoxPro views provide a degree of separation between your application and its data source. You can drag local views into your data environment, then when you upsize to client-server, you can create remote views with the same name that access client server data instead. However, this forces an either/or data access model. Either you’re using local data or you’re using remote data. You can’t dynamically swap between the two at run time.

However, you can create a subclass of Visual FoxPro’s Data Environment that eliminates both of these restrictions and allows you to swap between local and remote data dynamically at run time. For example, a technique developed by Flash Creative Management involves standardizing the names of local and remote views. Local views begin with the “lv_” prefix and remote views begin with the “rv_” prefix. Corresponding local and remote views are given the same name with a different prefix. For example, a local Invoices view would be named lv_Invoices. Its corresponding remote view would be named rv_Invoices. At run time, the decision is made to load either a local or remote view. The view is loaded with a generic alias as follows:

 

This allows you to generically refer to v_Invoices without knowing whether the source was local Visual FoxPro data or remote client-server data.

Understanding Data Sessions

A data session is a representation of the current dynamic work environment used by a form, form set, or report. Each data session contains its own set of work areas. These work areas contain the open tables, their indexes, and relationships.

Business objects that are hosted on Visual FoxPro forms load cursors into a single form data session. For example, if a form contains three different business objects; Projects, Clients and Project Tasks, each object loads its views into the same data session as shown in the following illustration:
  • The Projects business object loads v_Projects
  • The Clients business object loads v_ClientContacts
  • The Project Tasks business object loads v_ProjectTasks 

The New Data Session Class

Visual FoxPro 6, Service Pack 3 introduced the new Session class. This class allows business objects to have their own private data session. As mentioned previously, this is important in COM scenarios so multiple instances of business objects do not suffer from contention problems.

Using Business Objects From Visual FoxPro

Business objects can be instantiated directly from a class library within Visual FoxPro. For example:

When you need to use a business object on a Visual FoxPro form, you can drag the UI-Centric class from your business object library and drop it directly onto your form. You can then add code to your form that calls the methods of the business object.

Data Binding UI Controls to Business Object Views

Business objects (by means of the Data-Centric object) load data into a form’s data session. Since all cursors are loaded into a single data session of a form, you can tie the ControlSource of a form’s UI controls directly to the cursors loaded by the business objects. For example, in the form shown below, the UI controls on Page 2 are bound to the v_Projects view that is loaded by the business object on Page 1 of the form:

The views loaded into the form’s data session can be accessed by any user interface control located on any page of the form. This approach affords maximum reuse of business objects since you can drop the same business object on multiple forms.

Does Binding UI Controls to VFP Cursors Break the 3-Tier Model?

No, it doesn’t! The real issue is that the business object has loaded the data…the form did not. The form has no idea where the data came from; whether it’s Visual FoxPro data or remote client server data. Once the data has been loaded it’s perfectly acceptable to access the views directly from within the form.

Some have argued that user interface ControlSources should be tied to properties of the business object rather than a Visual FoxPro cursor. To do this, they create a property on the business object for each corresponding field in the business object’s cursor, and tie the UI ControlSources directly to these properties.

This methodology falls apart in a few places. First of all, it breaks down when using General fields. You can’t copy a General field to an object property, so you end up having to circumvent the “rules” to display General fields. Second, it also breaks down for controls that display multiple records. If you want to display a few hundred records in a grid (which is acceptable, even in a client-server environment) you have to dynamically build a cursor on the fly by copying business object properties to cursor fields, sitting in a loop asking the business object for the “Next” record. Third, it breaks down in the area of optimization—it’s extremely slow.

This methodology begs the question—why? Visual FoxPro works best with cursors—hands down. It does not have an object-based data access model, so why force one on it? Rather than having business objects force a particular data format on the client, business objects should adapt to the needs of the client!
Rather than having business objects force a particular data format on the client, business objects should adapt to the needs of the client!

Business objects can be designed to serve up data in a variety of formats that suit the client—XML, ADO RecordSets, HTML or Visual FoxPro cursors.

Serving Up Data in the Best Client Format

Well-designed business objects should be able to serve up data in a variety of formats. Depending on the client, one data format is usually preferred over another. For example, if business objects are instantiated from within Visual FoxPro, the desired data format is usually VFP cursors. If instantiated from a Microsoft Office application, the preferred format may be an ADO recordset. If instantiated from an Active Server Page, the preferred data format may be ADO, HTML or XML.

 
As shown in the UML class diagram to the right, a business object might contain the following methods:

CursorToADO –  Converts a VFP Cursor to ADO RecordSet
CursorToHTML – Converts a VFP cursor to HTML
CursorToXML – Converts a VFP cursor to XML
RSToCursor –      Converts an ADO RecordSet to a VFP Cursor
XMLToCursor – Converts XML to a VFP Cursor
SetDataFormat – Sets the default data format desired by the client
GetDataFormat – Returns the current default data format

 

Understanding the Business Rules Object

One of the primary roles of business objects is to enforce business rules. When business rules are associated with business objects, the rules can be applied wherever the business object goes—in a Visual FoxPro form or application, in an Active Server Page, in a Microsoft Office product, from within a Visual FoxPro DBC stored procedure, etc.

Business rules usually fall into one of two broad categories:

Data Integrity Rules

Data Integrity rules ensure the viability of your data. For example, most cursors have at least one field that must be filled in before a record can be saved…other fields must contain unique values. The Business Rules object can be used to enforce these rules.

Domain Rules

Domain rules encompass the rules that are specific to a particular domain. For example, a customer whose credit limit exceeds $10,000 may not be allowed to generate any new invoices; or the maximum discount applied to an invoice may be 10%.

 

Understanding the Business Rules Object

 

Breaking out business rules into its own object provides flexibility and scalability. This structure allows business rule objects to be swapped dynamically at run time.

As shown in the UML diagram to the right, the business rules object enforces business rules and keeps track of any broken rules. A method is added to the rules object for each rule to be enforced. If the rule is broken, the broken rule is added to the aBrokenRules array. If the rule is not broken, it is cleared from the array.

Business rule methods can be called individually. For example, if a field must contain a unique value, in the valid of the corresponding UI control, a call can be made to a method on the rules object that checks if the value entered by the user is unique.

Business rule methods can also be called collectively. For example, when a user clicks the Save button, before the record is saved, a call can be made to a method on the rules object (i.e. CheckRules) that calls all of the data-related rules.

In order to maintain scalability, business rule objects cannot display error messages. Clients, such as forms can retrieve the broken rules from the object by means of the GetBrokenRulemethod and display the messages themselves.

COM Business Objects

If you have placed the majority of your application’s logic within business object classes you can easily allow other products and technologies such as Visual Basic, C++, J++, Microsoft Office and Active Server Pages to access your application as an Automation Server (COM Component).

 
All you need to create an Automation server in Visual FoxPro is a project that contains Business Object classes defined as OLEPUBLIC. You can have as many OLEPUBLIC classes as you want in the project.

You can specify as many or as few classes as you wish as OLE Public. For example, you may wish to expose only a few business objects as OLE Public and instantiate other business objects behind the scenes.

To specify a class as OLE Public, do the following:

  • Open the class in Visual FoxPro
  • From the Class menu, select Class Info.
  • Select the OLE Public checkbox.
  • Click OK to save changes

 

Compiling Automation Servers

When you build a project with OLE public classes, Visual FoxPro creates three files:

By default, the .dll or .exe is given the same name as your project, with a .dll or .exe extension.

 

Project Information

After building the project, click on the Project menu, and select Project Info to launch the Project Information dialog. Click on the Servers tab to see a list of all Server classes.

As you click on each server class, you can change the Instancing, Description and Help context ID for each class. Help File, Project Name and TypeLib Description apply to all classes.

This information is placed in the Type Library and the Windows Registry.

Type Libraries

The type library file is a binary file that lists all the published classes in your Automation server, along with their properties, methods, and events. Visual FoxPro’s Class Browser can read Type Libraries and present them in a readable format.

Visual FoxPro 6 now supports intrinsic (Visual FoxPro) properties, events, and methods in an Automation server type library. Only properties whose visibility is set as PUBLIC are included in the type library.

Both custom, user-defined properties and user-defined methods appear in Visual FoxPro type libraries as long as they are marked PUBLIC. For methods, Visual FoxPro also includes a return value type (variant) and list of parameters (variants) parsed from the original method definition. Property descriptions from .vcx class files also appear in the type library.

Type libraries generated by the Build process are stored in .tlb files created along with the .dll or .exe server.

In Visual FoxPro 6 SP3, on machines running Windows NT, type libraries are also included in the .dll or .exe file as a bound resource. This eliminates the need to ship the extra .tlb file, although it is still built, along with the .vbr file, for use with remote deployment. For remote deployment, you can include just the .tlb and .vbr files and use CLIREG32.EXE to register the .vbr file to point to a remote server.

Business Objects and Distributed Computing

Distributed computing is defined as a system in which computers are interconnected for the purpose of sharing CPU power and appear to users as a single computer. The following factors may influence the decision to move to a distributed system:

Microsoft’s answer to distributed computing is Distributed COM. DCOM allows applications to be split into a number of different component objects, each of which can run on a different computer. DCOM provides network transparency. A client can make a call to an object on another computer as if the object was on the same machine. DCOM performs the interprocess and cross-network function calls transparently.

However, this ease of use comes with a price—slow performance.  A call to an object on another machine via DCOM is about 2,000 times slower than a call to an object on the same machine. How can you get around this speed problem?

The answer lies in the architecture of the business object. Rather than distributing the entire business object to another machine, one half of the business object (the UI-Centric portion) remains on the client and the other half of the business object (the Data-Centric portion) gets distributed to another machine on the network.

Take for example, the scenario of calling a business object from a Visual FoxPro form. At design time you can physically drop the UI centric portion of the business object directly on the form. When the form and the business object instantiate at run time, the UI-centric portion of a business object instantiates the data-centric portion. If the data-centric portion resides on the same machine, CREATEOBJECT is used to instantiate it. If the data-centric portion resides on a remote machine, CREATEOBJECTEX can be used instead.

This distributed architecture minimizes the interprocess and cross-network traffic. The client (i.e. the VFP form) interfaces directly with the UI-centric portion of the business object. The UI-centric object passes the call on to the data-centric portion only when it needs data.

This two-part structure also allows more data-intensive methods can be placed on the data behavior object, closer to where the data resides for the best all-around optimization!