PFC Guide Titlebar
HomeFAQLinksPFCMAGExtensionsDownloadWhat's NewSearch

PFC Extension Strategies (cont.)

Table of Contents     Previous Page


Extension Techniques

Having the extension layer raises the first question: Should I add the new logic directly to the extension layer or should I add the logic by inheriting from the extension layer? The answer is both. The difference between the two methods lies in the circular relationship between the PFC and PFE layers. The logic added to the extension layer affects the whole library. The logic added by inheritance will only affect a new descendant object. Let’s identify and define the different techniques.

Extension by Insertion

Extension by Insertion - Extending by adding code directly to the objects in the PFE layer or any layer between the PFC and PFE layers. These extensions are usually generic in nature.

Extension by Insertion is very powerful. Every PFC object has a corresponding PFE descendant. Every object in the class library can be extended.

To use this method the insertion object must already exist in the class library. Another limitation of this method lies in a fact that any change made by insertion is global for the scope of PFE layer. Lets take a look at the transaction object n_tr. It contains several precoded and placeholder functions. To make the transaction object functional for sybase we need to override of_setuser, and if autocommit is set to true, of_begin and of_end as well. This is illustrated in Figure 3 below.

Figure 3 - Transaction extended by insertion

The above works great for a single database application, but what happens if you need to connect to different databases? Adding the DBMS specific functions to n_tr has made every transaction in the application specific to a single DBMS. There are ways around this problem, but as a rule extension by insertion has to be generic enough for the scope of the PFE layer. .

Extension by Inheritance

Extension by Inheritance - Extending by inheriting an object from the PFE layer and adding code to further specialize the object. This form of extension is usually more specific in nature.

Extension by inheritance can get more specific. Figure 4 below demonstrates how different windows can be extended by inheritance. In this case an application frame and multiple sheet windows are generated by inheriting from the windows in the PFE layer.

Figure 4 - Extension by Inheritance

Extension by Inheritance works great for the lowest descendant objects. There is a problem using extension by inheritance to add logic to the ancestor object. Because the new object is not a part of the inheritance chain, the functionality added to w_app_master will not make it to the w_app_frame. Figure 5 shows this limitation.

Figure 5 - Extension by Inheritance Limitations

Extension by Inheritance is limited to the lowest level descendants and concrete classes, it does not work for the abstract classes.

The limitation of the extension by inheritance could also be considered an advantage. Extension by inheritance makes it possible to generate very specific objects without affecting the rest of the class library. Lets get back to the transaction example. As you can see from figure 6 below we can generate a DBMS specific transaction through inheritance.

Figure 6 - Transaction Extended by Inheritance

The transaction object is easily extended by inheritance because it is declared as a global variable. The developer can select a specific transaction. This method may not be appropriate for pre-referenced service classes.

 

Extension by delegation

Extension by Delegation - Extending by delegating tasks to new service objects. This form of extension can be generic or specific in nature but due to the additional complexity it may be reserved for the code intended for reuse.

Two previous methods have added new logic through the use of inheritance. An important alternative that should not be overlooked is extension by delegation or by creating new services. Because the services are associated at runtime this methods opens new opportunities for implementation techniques such as operational polymorphism, which allows dynamic object association. This method was used to implement the file and platform PFC services. Figure 7 demonstrates how the transaction object can be extended using this technique.

Figure 7 - Transaction Extended by Delegation

The of_connect function is extended to create the appropriate transaction service.

CHOOSE CASE Upper(Left(this.dbms, 3))
	CASE ‘SYB’, ‘SYC’
		this.inv_trsrv = CREATE n_cst_trsrv_sybase
	CASE ‘OR7’, ‘O71’, ‘O72’, ‘O73’
		this.inv_trsrv = CREATE n_cst_trsrv_oracle
	CASE ELSE
		// unsupported dbms
		return -1
END CHOOSE
return super::of_connect()

 

The of _setuser function is then delegated to the transaction service.

 

IF IsValid(inv_trsrv) THEN
	inv_trsrv.of_setuser(as_userid, as_password)
END IF

 

Typically, the tasks are delegated by client objects to service providers. Application delegates it’s tasks to application manager, datawindow control to datawindow services, windows to window services and so on. However, the service delegation is not limited to two levels. The service providers may assume the role of client objects and transfer some responsibilities to other service objects. Therefore it is possible to use the extension by delegation technique to extend the PFC’s service objects.

Table of Contents     Next Page

Article based on the material from "PowerBuilder Foundation Class Library Professional Reference", McGraw Hill, ISBN 0-07-913267-7.

Last revised: February 15, 2004 03:58 AM.