Roll up your sleeves, we have reached the point where we are ready to get technical and examine the different extension approaches.
The first extension approach requires the least amount of preparation. This approach is best illustrated by the Quick Start application. In this case PFE layer is used for both the generic reusable code and the application specific logic. Using this approach a separate PFE layer is maintained for each individual application. The objects in the PFE layer can be directly modified with application specific code.

Figure 8 - PFE as an Application Layer
Advantages
Does not require any up-front
planning.
This is the "out of the box" solution. You can copy the 4 PFE pbls into a separate directory and start coding.
Limitations
Once the generic framework code is combined with the
application specific it cannot be easily separated.
This approach is based on an assumption that there is little or no need for reusable code. The extension scope is defined as two components PFC and application. If you plan to reuse any code or to share it between multiple applications this approach is not practical.
Do not underestimate the common framework requirement for your application. The reusable framework may be as small as a few PFC bug fixes. Reapplying the same fixes for the next project can be very tedious.
Requires maintaining a separate copy of PFE and PFC
pbls for each project.
The reason for separate PFE pbls is clear, they are specific to each project, but why PFC? The answer lies in the nature of object relationships between the two layers. PFC layer contains many objects which are inherited from the objects in the PFE layer, for example pfc_w_sheet is a descendant of w_master. The same is true for associative and aggregate relationships. The transaction object referenced in PFC objects is n_tr and not pfc_n_tr. In many cases by modifying the PFE objects with the application specific code makes the PFC objects application specific as well.
This brings up an important distribution issue: If you create pbds or dlls from the PFC pbls they may not be compatible between multiple applications!
Using the second approach both the framework and application elements are included in the extension scope. The PFE layer is reserved for framework objects only. The application specific logic is added by inheriting from the PFE layer as demonstrated in Figure 9.

Figure 9 - PFE as a Framework Layer
Advantages
PFE and PFC pbls, pbds or dlls may be reused /
shared between multiple applications.
The framework and PFC can be treated as a single unit. The application extension is not a part of the extension layer and therefore it has no effect on the framework and PFC objects. Some companies are distributing the framework with using pbds only. This is the only approach that still allows this type of distribution. Whether the pbls or pbds are distributed to different project teams, the framework and the application distribution is simplified.
Easier to support.
All the circular references are contained to PFC and PFE. The application specific code is added below PFE. Once the framework is complete and deployed to different application development groups there is not much that can be done on the application level to inadvertently change the framework behavior. The framework support is simplified.
Lean Approach
This approach allows separate framework and application components with the minimum number of objects. Other approaches, discussed later, require an additional layer, which increases the number of pbls and objects.
Limitations
The application specific logic is limited to
extension by inheritance and delegation.
Extension by inheritance is limited to the lowest descendant objects. None of the abstract PFC ancestors can be extended with the application specific logic. For example, application specific code cannot be placed in w_master, this object is in PFE layer and is reserved for the framework code.
There are many objects in PFC that favor extension by insertion. Any PFE object that was referenced from PFC cannot be easily extended by inheritance. Most of the PFC objects cannot be extended by inheritance but instead may require extension by insertion or delegation. This is because these objects were directly referenced from the PFC layer. A bulk of these are service objects, but there are some client objects as well.
This method does allow the generic framework logic to be added by insertion, the PFE layer can be modified directly. The limitation lies only with the application specific code. Extension by insertion is typically used for the generalization code. Is there a need for generic behavior at the application level? Lets take a look at two examples that do require application specific logic at the PFE level.
U_dw is the first example. The events pfc_prermbmenu, pfc_preprintdlg, and pfc_pagesetupdlg serve as place holder events that allow customization of the popup menu, print and page setup dialog windows. If u_dw is used throughout the application to customize the popup menu for the whole application, code must be added to the u_dw directly or duplicated for every u_dw placed on the window.
The second example is the status bar window service. The status bar service allows the addition of standard memory and time objects as well as custom text and bitmaps to the microhelp bar. The service allows interaction with the status bar through the use of pfc_statusbarclicked, pfc_statusbardoubleclicked, and pfc_statusbarrbottonup events. In this case application specific code has to be added directly to the n_cst_winsrv_statusbar in the PFE layer.
The workaround for the first case is to create an application level abstract class - u_app_dw inherited from u_dw. Every datawindow in the application must be of u_app_dw type. It would then be possible to change the popup menu on the application-wide level by adding code to the u_app_dw. The solution for the second case is a little more challenging. The status bar service reference variable is of n_cst_winsrv_statusbar type. See the excerpt from the of_setstatusbar function below:
if ab_switch thenif IsNull(inv_statusbar) Or not IsValid (inv_statusbar) theninv_statusbar = create n_cst_winsrv_statusbarinv_statusbar.of_SetRequestor (this)Return 1end ifelseBecause the inv_statusbar is created as n_cst_winsrv_statusbar extension by inheritance has no effect. One possible solution for this problem is to use delegation technique and create another application specific status bar object as shown below.

Figure 10 - Status Bar Delegation Solution
A new object app_n_cst_winsrv_statusbar is created. All the events are triggered from the corresponding n_cst_winsrv_statusbar status bar object. The new object is instantiated as inv_app_statusbar and serves as a placeholder for application specific logic.
Another way to solve this problem is to delegate the status bar events to the MDI frame window.

Figure 11 - Status Bar Delegation Solution
The application specific status bar related code may now be placed in the application frame window descendant.
Possible conflict with third party utilities.
The hard-coded references to the objects in PFE layer lead to one important benefit. The PFE layer has provided an industry standard. There are a few PFC related tools available now with many more on the way. Their contributions range from object modeling to wizard based template generation. The reason these tools were able to get this far is because they are able to generate code based on the objects in the PFE layer. When objects are extended by inheriting from PFE, the new descendant objects fall outside this standard, rendering the tools useless.
Cannot be further extended through inheritance.
With some limitations it is possible to add application specific code by inheriting from PFE. It is not possible to add another generic framework layer below PFE. As an example try to inherit from n_cst_dwsrv_sort, add a function called of_MyFunction and then attempt to call of_MyFunction through the existing inv_sort reference variable. The compilation of the code will fail because the inv_sort is declared to be of n_cst_dwsrv_sort type and of_MyFunction does not exist in n_cst_dwsrv_sort.
Extension by delegation is still possible. As seen in previous examples service delegation technique is very powerful and can be used to compensate for inability to extend through inheritance. Nonetheless loss of the inheritance based techniques should be carefully evaluated and balanced against the advantages of this approach.
If you are developing an industry specific framework or a class library and there may be a requirement to add another generic layer below yours, this method will not work. In other terms this is a selfish approach. Using the PFE layer for the framework does not leave any room for another generic layer.
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.