YOUR FEEDBACK
AJAX: XMLHttpRequest Vs. iFrames
Kenneth wrote: You forgot to mention a disadvantage of xmlHttpRequest that i...
AJAXWorld RIA Conference
$300 Savings Expire July 25
Register Today and SAVE!


2007 West
GOLD SPONSORS:
Active Endpoints
Your SOA Needs BPEL for Orchestration
BEA
Virtualized SOA: Adaptive Infrastructure for Demanding Applications
Nexaweb
Overcoming Bandwidth Challenges with Nexaweb
TIBCO
What is Service Virtualization?
SILVER SPONSORS:
WSO2
Using Web Services Technologies and FOSS Solutions
Click For 2007 East
Event Webcasts

2008 East
PLATINUM SPONSORS:
Appcelerator
Think Fast: Accelerate AJAX Development with Appcelerator
GOLD SPONSORS:
DreamFace Interactive
The Ultimate Framework for Creating Personalized Web 2.0 Mashups
ICEsoft
AJAX and Social Computing for the Enterprise
Kaazing
Enterprise Comet: Real–Time, Real–Time, or Real–Time Web 2.0?
Nexaweb
Now Playing: Desktop Apps in the Browser!
Sun
jMaki as an AJAX Mashup Framework
POWER PANELS:
The Business Value
of RIAs
What Lies Beyond AJAX?
KEYNOTES:
Douglas Crockford
Can We Fix the Web?
Anthony Franco
2008: The Year of the RIA
Click For 2007 Event Webcasts
SYS-CON.TV
POWERBUILDER LINKS YOU MUST CLICK ON


PowerBuilder Developer's Journal: Building a Working Application Shell
Design considerations

Digg This!

Page 2 of 2   « previous page

Code promotion is the movement of code from a descendant class to an ancestor class accompanied by the necessary generalization of that code so it applies to the ancestor. When you build a simple base class library with limited functionality, as in our case, you may find that functionality is missing when you begin to actually build your application. The key is to be aware of what is being added to the application-specific classes and keep an eye out for features that become prime candidates for code promotion because they could be used across applications. You can think of those as non-application specific features. The importance of not duplicating code cannot be overstated. It is a bug waiting to wreak havoc on your system.

In our application, there were two instances when I realized, after I coded an implementation, that the functionality could be easily generalized and moved to the application framework. The first instance was when I needed to implement the Close All menu item functionality. This fairly common item on many application menus allows all open windows to be closed with a single command. Because I know this feature is fairly common, I chose to place it on the framework's m_frame Window menu. However, I didn't code an implementation at the framework's menu level initially. My first implementation was in m_cs_frame, my application's descendant menu. The first implementation looked like this:

// Declare variable for active sheet
w_cs_sheet lw_Sheet

lw_Sheet = w_cs_frame.GetActiveSheet ()

do while IsValid (lw_Sheet)
     // There is an active sheet, so close it
     Close (lw_Sheet)
     lw_Sheet = w_cs_frame.GetActiveSheet ()
loop

Fairly straightforward...get the current active sheet, close it, get the next active sheet, close it...until all sheets are closed.

I then took a second look and noticed that I had not one, but two application-specific references that I was sure I could generalize. If I could do that, I could also move this generic implementation to my framework and have code that could be executed as is probably 90% of the time.

The first reference I wanted to generalize was my reference to w_cs_frame. Since w_cs_frame is inherited from w_frame, that was an easy change. The second reference I wanted to change was from w_cs_sheet to w_sheet. Again, another easy change. Or was it? When I ran this code, I encountered the dreaded null object reference error (see Figure 7).

Why did I get this error? I took a closer look at line 4:

lw_Sheet = w_frame.GetActiveSheet ()

The only object that could possibly be null on this line is w_frame. But w_cs_frame obviously exists and is active. Why would w_frame give a null object reference? After all, it's the ancestor class and if the descendant exists, then the ancestor must exist as well since I can execute functions and events from the ancestor. The answer is due to the fact that w_frame, as an object, does not, in fact, exist. My application does have an object of type w_cs_frame which does exist. It also has access to w_frame's functions, events, protected, and public instance variables. What I can do is use a variable of type w_frame to reference my existing w_cs_frame, but w_frame as an object just does not exist.

Adding an extra line:

w_frame = w_cs_frame

gets me no closer to my goal of ensuring the code is generalized so it can reside in the ancestor class. How can I refer to the frame, then, without referring to it by name or type?

The answer is the same as how we do it in our spoken languages: pronouns. If I don't want to refer to Mike by name when I'm speaking to Alice, I can use "he." When I don't want to specify whether it was my mom or dad who drove the car into the tree (didn't really happen, by the way - really!!), I can use "parent." In PowerBuilder, several pronouns are available that are useful in this same way. The list of pronouns can be found in the Help by searching for, what else but, "pronoun." (see Figure 8)

In my particular case, the "pronoun" I need is ParentWindow, which is actually a menu object property, but looks and acts like a pronoun. So, the final version of the code became:

// Declare variable for active sheet
w_sheet lw_Sheet

lw_Sheet = ParentWindow.GetActiveSheet ()

do while IsValid (lw_Sheet)
     // There is an active sheet, so close it
     Close (lw_Sheet)
     lw_Sheet = ParentWindow.GetActiveSheet ()
loop

Since GetActiveSheet() returns a reference to a window, shouldn't I use the even more generic "window" as the variable type? The short answer is yes, but there are tradeoffs. What are the tradeoffs of using w_sheet versus window? Using w_sheet makes it easier to change the code to use more framework-related functionality. Using window allows the code to work even when sheets are opened that are not descended from type w_sheet. While technically a no-no, there may be situations where this is acceptable. I prefer to use w_sheet in this case and to force the usage of the framework base sheet window in my application for all sheets.

The second instance where I realized I could make a little change and promote code to the framework was in the default handling of the closequery event. I realized that my CloseAll functionality was not taking into account the possibility that the application would code a closequery event somewhere and prevent a window from closing. A quick look at the Close() function shows that the return code will be 1 or -1 where 1 indicates the close was successful and -1 indicates an error. -1 also indicates that a value of 1 was returned from the closequery event to prevent the close of the window. I had to make another change to the CloseAll functionality by handling the return value of the Close() function call:

if Close (lw_Sheet) = -1 then
     exit
end if

Namely, if there was a problem closing any open window, terminate the CloseAll loop.

For the closequery event itself, I wanted to create a generic handler in my base application-level sheet asking if the user really wanted to close the window. I quickly realized that this code could be promoted to the framework because there was nothing application-specific about it. So, the w_sheet::closequery event became:

int li_Rc

li_Rc = MessageBox (this.Title, "Are you sure you want to close this window?",
Question!, YesNoCancel!, 2)

choose case li_Rc
     case 1
       return 0
     case 2
       return 1
     case 3
       return 1
end choose

Conclusion
At this point, we have a functional shell of an application. We still have a lot of work to do to complete the application. As we work toward that goal, we will encounter numerous opportunities to add to our application base classes and our framework. We will also take the time to discuss other design considerations and best practices. If you want to get a copy of the complete source code to date, please send me an e-mail at steve.katz @teamsybase.com and I will be glad to send you the application.


Page 2 of 2   « previous page

About Steve Katz
Steve Katz is a senior developer at HSBC Bank USA and has extensive experience developing applications utilizing PowerBuilder, Java, and other technologies. He has used PowerBuilder since v2.0a, taught at Techwave, and even wrote some articles about PowerBuilder a very long time ago.

news desk wrote: As I was reviewing my previous 'state of the application' and began to work toward a basic application shell, I realized that there was some additional code that I needed to write.
read & respond »
PBDJ LATEST STORIES . . .
Adobe's Kevin Lynch and Microsoft's Scott Guthrie to Keynote AJAX World RIA Conference & Expo
Two of the biggest launches in Rich Internet Application history took place in 2007/2008 when Adobe launched AIR 1.0 in February '08 and Microsoft launched Silverlight (September '07). At the 6th International AJAXWorld RIA Conference & Expo in October SYS-CON Events is delighted to be
PowerBuilder and EAServer: Uniting the .NET and J2EE Communities
In PowerBuilder 11.2, .NET meets J2EE head-on with the capability to deploy .NET Windows Forms and Web Forms applications (as well as assemblies and Web Services) that access Enterprise JavaBeans (EJBs) in Sybase's own EAServer. As you'll see over the course of this article, integratin
HarPB Tool Review
HarPB is a specialized utility for checking PowerBuilder source objects in and out of AllFusion Harvest. It handles the special requirements of checking objects out to PowerBuilder Libraries (PBLs) and checking objects in from PBLs. These operations are non-standard to most source cont
PowerBuilder Editorial: The State of the State
Back in 2002, Sybase announced their four-phase approach toward adding .NET support to PowerBuilder. Phase 1 was the implementation of web services in PB9 and Phase 2 was the release of DataWindow.NET, which was packaged with PB 10. Phases 3 and 4 were the more significant phases. In P
PowerBuilder History - When Did Sybase Develop PB and How Did It Evolve?
I have been asked many times by various clients, students, and the IT curious about PowerBuilder: When did Sybase develop the product and how did it evolve? I keep telling this story and answering e-mails on the subject. I am now to the point where I have decided that I should have PBD
PowerBuilder 11's .NET Interoperability
PowerBuilder 11 deploys entire applications as .NET Windows Form or Web Form applications and deploys individual components as .NET Assemblies and as .NET Web Services. Version 11 consumes resources of the default .NET framework as well as resources of custom developer-defined .NET res
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021

SYS-CON FEATURED WHITEPAPERS

ADS BY GOOGLE
BREAKING POWERBUILDER / SYBASE NEWS
Sybase Reports Record Second Quarter Results, Driven by 15% Revenue Growth
Sybase, Inc. (NYSE:SY), the largest enterprise software and services company exclusively