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.
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 Groups web site at www.omg.org.
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 youll never want to go back! Business object encapsulation makes the job of analysis, design, software construction and maintenance far easier than procedural techniques.
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 customers 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:
Although software reuse within a single application is a good thing, it doesnt stop there. Business objects allow your applications 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. Well look at single, two, three and n-Tier architectures and see how business objects fit into each model.
Business Objects in Single-Tier ArchitecturesA single-tier architecture consists of a program running on a users machine that accesses a database on the same machine or a mapped network drive. All of the processing takes place on a single machinethe 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/ServerIn 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 serveranother physical server that manages network trafficbetween the workstations and the database server. This model allows us a great deal of flexibility in deciding where to place the applications business processing. You can move virtually all of the business processing off the workstations and onto the application serveror 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 Microsofts 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 applications logic. This is the key to software reuse across multiple software applications. Tier 3 is where an applications 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. |
Just about every Microsoft product can instantiate and use COM objects. Microsofts 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.
What we have discussed so far brings us to a very important conclusion:
The majority of an applications 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 applications logic in business objects, you will create an application that is far more flexible, extensible and reusable without a great deal of additional effort.
Even if youre 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 applications user interface and its data. Business objects are responsible for loading, unloading and manipulating data. This allows you to change your applications 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.
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 Softwares 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.
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, its 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:
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
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 platformsincluding 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 componentsa User Interface component and a Data-Centric component. |
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.
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:
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 changeda 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 DetailsAs shown in the UML class diagram to the right the business object also contains :
Data Session ObjectThe 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 ObjectThe data environment class is used to load and unload data. |
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.
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:
o they can load the data they need wherever theyre 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 forms 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 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 youre using local data or youre using remote data. You cant dynamically swap between the two at run time.
However, you can create a subclass of Visual FoxPros 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:
Loading a local view
USE lv_Invoices ALIAS v_Invoices
Loading a remote view
USE rv_Invoices ALIAS v_Invoices
This allows you to generically refer to v_Invoices without knowing whether the source was local Visual FoxPro data or remote client-server data.
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:
|
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.
Business objects can be instantiated directly from a class library within Visual FoxPro. For example:
o = CREATEOBJ('Clients')
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.
Business objects (by means of the Data-Centric object) load data into a forms data session. Since all cursors are loaded into a single data session of a form, you can tie the ControlSource of a forms 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 forms 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.
No, it doesnt! 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 its Visual FoxPro data or remote client server data. Once the data has been loaded its 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 objects 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 cant 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 optimizationits extremely slow.
This methodology begs the questionwhy? Visual FoxPro works best with cursorshands 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 clientXML, ADO RecordSets, HTML or Visual FoxPro cursors.
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 |
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 goesin 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 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 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.
If you have placed the majority of your applications 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:
|
|
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 InformationAfter 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. |
|
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 FoxPros 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.
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:
Microsofts 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 priceslow 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!