Helping Developers Master PowerBuilder Classic and .NET

Yakov Werde

Subscribe to Yakov Werde: eMailAlertsEmail Alerts
Get Yakov Werde via: homepageHomepage mobileMobile rssRSS facebookFacebook twitterTwitter linkedinLinkedIn

Related Topics: Enterprise Architecture, Enterprise Application Performance


Getting to the Top of the Pecking Order

Instantiating service NVOs first

"Chicken flocks have a well-defined hierarchy called a pecking order. A chicken at the top of the pecking order gets to do the things she wants by 'pushing the others around' a little, giving them a short, sharp peck if they don't submit to her, allowing her to go where she wants to go or access food and drink first. Chickens naturally have a pecking order to ensure they live in harmony. When food is available there are no fights. Everyone lives in peace.

The bird at the top of the pecking order will have first access to water, food, the best roosting place and so on. The bird at the bottom of the pecking order has the least ‘rights' in the flock and will usually be the last to the food and will ‘skirt' around food that is scattered for them, nipping in to grab a beak full when possible. She (or sometimes he) has last rights to food and other resources."

What's pecking order got to do with PowerBuilder? When does pecking order matter in PowerScript coding? Read on to see the connection!

PowerBuilder Scenario
Your application has a window containing custom visual user objects (CVUOs) that require system services in their constructor events. Obviously, the services must be resident and active before the CVUO constructor is invoked. Using globals (functions, or NVO references) is one approach, but you want to code your solution in a Service Based Object Oriented manner. Being an object-oriented aficionado, you don't want the service to be of global scope. You'd rather define the NVO as a Window service. You define the service inside a Custom Class User Object (NVO) that you declare on the window and instantiate in the Open event. The window defines a NVO instance variable and creates it in its Open event. The CCUO calls the NVO service via the window in its constructor event. Figure 1 shows the code objects in the system tree. Figure 2 illustrates the scenario.

Figure 1: Code objects

Figure 2: CVUO in a Window calling service in constructor

The problem is that the NVO is not created until after the CCUOs. At runtime, because CVUO control constructors are invoked before the service is instantiated, a Null Object Error will be thrown. Figure 3 shows the Window event sequence. Notice that number 3, the NVO constructor, follows number 1, the CCUO constructor. In other words the NVO is lower down in the pecking order. How can we move the NVO up to number 1? After all, the open event always occurs after all the controls are created? I'll show you three possible solutions. You pick the one that suits your taste best.

Figure 3: NVO lower down in the pecking order

Solution 1: Deferring CCUO Constructor code
I term the first solution "Classic" because it relies on a technique that has been around since the earliest versions. The solution relies on Post vs. Trigger event invocation timing. Every PowerBuilder programmer has seen this technique used in the Window open event cascade. You add an event that you usually call ue_postconstructor to the CCUO, code a this.PostEvent(   ) to it in the constructor, and move the timing-sensitive code from the constructor into the ue_postconstructor. As you can see in Figure 4 the problem is solved because the ue_PostConstructor is invoked after the NVO is resident.

Figure 4: Sequence when CCUO code move to post constructor

Now it looks like the NVO is #1 but in truth it's really not. It's there because we lost the ability to record the CCUO constructor (which is still #1) and we recorded the Window Open (which is really #2) after we created the logging service. So the service is really still #3. It just faked its way to the top of the list. The question still remains: how can we really move the NVO up to the #1 position? In the sections that follow, I'll show you two methods to escalate NVO instantiation.

Solution 2: Auto Instantiate the NVO
In this approach you mark the NVO to be AutoInstantiated on its property sheet. That means THE VARIABLE DECLARATION IS THE INSTANTIATION. Figure 5 shows the design time AutoInstantiate designator.

Figure 5: AutoInstantiate designator

In addition, you must remove the now illegal CREATE statement from the Open Event. Since instance variables are allocated before controls are instantiated, the NVO reference is moved up to #1. Figure 6 shows our NVO in the top position.

Figure 6: The NVO is #1

However, a word of caution is appropriate: autoinstantiated NVOs behave like structures. That is, assignment statements cause a copy of the NVO to be passed, not a pointer to the original object. The will be a problem if your NVO maintains internal state.

Solution 3: Letting the Painter Define the NVO
The window painter has a little-known view called the Non-Visual Object List. As you can see in Figure 7, in the default layout, it's located on a tab on the bottom of the same folder containing the Properties View.

Figure 7: Non-Visual Object List

It lists NonVisual User Objects that you place on the layout surface using the painter. You can both drag and drop a non-visual control from the System Tree onto the Layout or use a menu item to accomplish the deed. Figure 8 shows the Insert Object menu on the Window Painter.

Figure 8: Placing an NVO on the layout

When you place an NVO, the painter gives it a default name just like any visual control - class name prefix followed by a numeric suffix. You can use the property sheet to have the name follow your standard naming convention. Figure 9 shows the view after defining an NVO. Please note that you can only define non-autoinstantate NVOs in this manner.

Figure 9:Non-Visual Object List

The painter is a privileged character. It can write code in framework source code places that are not in the developer domain. In our case, the painter defines the NVO in the Type Declaration section and instantiates it in the CREATE event. That means that the NVO is instantiated earlier in the instantiation process. Figure 10 shows part of the painter-generated code.

Figure 10: Generated Source Code

In addition to rising to number 1 in the pecking order, the NVO garners two other bonus features from this approach; first, the NVO behaves like an NVO. Assignment statements assign the address of a single object in memory; state is retained. Second, like a visual control the NVO becomes an inner control defined within the window. As you can see in Figure 11, you can write additional event handler code for it in the window painter. Now that may prove useful some day!

Figure 11: NVO in the Window Script Editor

One mystery still remains unsolved. A careful read of the CREATE code shows the NVO created AFTER the CCVOs. By all rights and logic, NVO calls in CCUO constructors should fail. But they WORK!!? Obviously there is some sleight of hand going on inside the runtime.

PowerBuilder, like just about everything in life, offers a reasonable face value experience, but provides hints and tools that you can follow and use to rise above the pack. Armed with the desire for a better solution and a bit of fortitude to see it though, you'll find a way to write better code, thereby becoming #1 in the pecking order.

More Stories By Yakov Werde

Yakov Werde, a 25 year IT industry veteran, is a member of TeamSybase and the newly formed Sybase Customer Evangelist Team. Yakov is a recognized author, speaker and trainer who has been designing and delivering PowerBuilder, .NET, EaServer, Web App Development, and Java training for over 14 years to corporate, military and government developers. Prior to discovering his aptitude as an educator, Yakov worked as an architect, project manager and application coder in the trenches of application software development. Yakov holds a Masters in Education with a specialty in instructional design for online learning from Capella University and a BS in math and computer science from Florida International University. Yakov, managing partner of eLearnIT LLC (www.elearnitonline.com), authors and delivers workshops and web based eLearning tutorials to guide professional developers toward PowerBuilder Classic and .NET mastery. Follow Yakov on Twitter as @eLearnPB

Comments (1) View Comments

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.

Most Recent Comments
acartagenas 08/21/11 05:13:00 AM EDT

Hi Yakov,

There's another approach in order to put the NVO on top of CVUO with regards to instantiation.

Instead of explicitly placing the CVUO on the window control, we can set it as instance variable. Thereby instantiating it using CreateUserObject function of the window, thus, you have the luxury of selecting in w/c order you want to instantiate the NVO and CVUO.