Comments
Richard Davies wrote: The UK has a good crop of technology pioneers in cloud computing - for example ElasticHosts, FlexiScale, Flexiant, OnApp - and also some strong government initiatives such as G-Cloud. We will have to see whether this kind of technical leadership converts into swift mass-market adoption or not.
Cloud Expo on Google News


2008 West
DIAMOND SPONSOR:
Data Direct
SOA, WOA and Cloud Computing: The New Frontier for Data Services
PLATINUM SPONSORS:
Red Hat
The Opening of Virtualization
GOLD SPONSORS:
Appsense
User Environment Management – The Third Layer of the Desktop
Cordys
Cloud Computing for Business Agility
EMC
CMIS: A Multi-Vendor Proposal for a Service-Based Content Management Interoperability Standard
Freedom OSS
Practical SOA” Max Yankelevich
Intel
Architecting an Enterprise Service Router (ESR) – A Cost-Effective Way to Scale SOA Across the Enterprise
Sensedia
Return on Assests: Bringing Visibility to your SOA Strategy
Symantec
Managing Hybrid Endpoint Environments
VMWare
Game-Changing Technology for Enterprise Clouds and Applications
Click For 2008 West
Event Webcasts

2008 West
PLATINUM SPONSORS:
Appcelerator
Get ‘Rich’ Quick: Rapid Prototyping for RIA with ZERO Server Code
Keynote Systems
Designing for and Managing Performance in the New Frontier of Rich Internet Applications
GOLD SPONSORS:
ICEsoft
How Can AJAX Improve Homeland Security?
Isomorphic
Beyond Widgets: What a RIA Platform Should Offer
Oracle
REAs: Rich Enterprise Applications
Click For 2008 Event Webcasts
SYS-CON.TV
Top Links You Must Click On


Using Properties to Make Your PowerBuilder Application More Robust
A best practice that gives developers greater control of how data is used

Like Java and C# programmers, PowerBuilder developers can create properties via the undocumented keyword indirect. Properties look like ordinary variables, only their value isn't accessed directly. When you declare a variable using indirect, you have to specify a function that's called when the variable is assigned (a setter) and another function that's called when the variable's value is returned (a getter).

Below is an example syntax for declaring a property using indirect:

      // l_patient_id is an instance on a NVO
indirect long l_patient_id { of_set_patient_id( *value ), of_get_patient_id() }

You have to write the getter/setter functions in the same context as the indirect declaration. You cannot use indirect with "pure" global variables; in this article, "global variables" are instance variables declared on a global NVO 'g'. The getter/setter functions would be on that NVO. They can (and should) refer to a private variable:

    // Accessed ONLY by the getter/setter functions so it's private
    private long l_patient_id

    // Getter on the NVO
    function long of_get_patient_id()
       return l_patient_id

    // Setter on the NVO function void of_set_patient_id( long al_patient_id )
       l_patient_id = al_patient_id

Given this declaration and getter/setter then assigning to the g.l_patient_id:

g.l_patient_id = 1234

is turned into a function call by the PowerBuilder compiler, in effect:

g.of_set_patient_id( 1234 )

where 'g' is the name of the global NVO. Accessing the value becomes another function call, so:

ll_current_patient = g.l_patient_id

becomes the equivalent of:

ls_current_patient = g.of_get_patient_id()

How Could Properties Be Useful?
You can use properties to make your PB application more robust.

Using properties is a best practice with modern programming languages like Java and C# because they are safer than directly accessed variables. Consensus says that properties make code more robust and reliable, principally because they give the developer greater control of how the data is used.

Properties are more powerful than ordinary variables because the setter/getter functions give you a hook where you can write code, e.g., to validate the data. Is there something you want to do whenever a variable changes? If you don't now you will later, and the setter function gives you a place to write the code to do that.

Example:
Converting Globals to Properties

There are a lot of PB applications out there that were crafted before any of us knew what we were doing. In particular, they make extensive use of global variables, which are inherently unsafe. There's a good reason why we were all taught to avoid globals! The indirect keyword gives us a way to convert globals to properties.

My example comes from a legacy medical application that used a long patient ID instance on the global NVO 'g' to keep track of the current patient. The global patient ID was set and reset a couple hundred times in the application. In some contexts, there was no patient until the user selected a row, or until the code processed a row in a DataWindow. In those circumstances, the global would be set to zero to signify that there was no current patient. When the patient was selected, a new patient ID would be assigned to the global long.

One problem was that another global variable needed to be kept in sync with the global patient ID. Whenever the patient ID changed, the global patient name string had to be reset too. Keeping them in sync was essential. The application perpetually displayed the current patient's name in the MicroHelp area, and it routinely displayed the global patient name on reports, without first refreshing it to make sure that it corresponded to the global patient ID.

This led to bugs. We'd get support issues like "The prescription had the correct patient ID but the wrong name." Inspecting the code, I found that most of the time a change to the global patient ID was done by a call to a function that reset the patient name accordingly. However, there were a dozen patient ID assignments where that function call was missing. Bugs!

There was also nothing in the application that cleared the patient's name from the MicroHelp when the patient ID was zeroed out to signify "no current patient." The MicroHelp conveyed that so-and-so was the current patient, while the application would put up messages like "You must select a patient before..."

I could have simply added a reset-the-patient-name function call to the dozen places where it was missing. However, that would have left the vulnerability intact, and subsequent programmers would have had to be aware of the requirement to call the function whenever they set the patient ID. That wouldn't have done anything to fix the misleading MicroHelp that presented the current patient's name when there was no current patient.

A better solution was to replace the global patient ID and patient name with properties.

Implementing the Global as a Property
The process of converting the variables on the global NVO 'g' to properties took just a few minutes. The process was:
1.  Declare private variables on the 'g' NVO to hold the patient ID and patient name:

    // On the application object
    private long il_patient_id
    private string is_patient_name

In effect, these become new global variables equivalent to the old ones that are get/set using the properties.

2.  Write getter/setter functions for the new private variables. For the global patient ID:

    // Patient ID Getter
    function long of_get_patient_id ()
       return il_parient_id

    // Patient ID Setter
    function void of_set_patient_id ( long al_patient_id )

       string ls_pt_name // Name shortened for this article! :)

       // Validate the patient_id
       if IsNull( al_patient_id ) then
         g.warn( "NULL patient ID!" )
         al_patient_id = 0
       elseif al_patient_id < 0 then
         g.warn( "Negative patient ID: " + string( al_patient_id ) )
         al_patient_id = 0
       end if

       // Do we HAVE a patient ID?
       ls_pt_name = "" // In case the ID is invalid
       if al_patient_id > 0 then // Yes

       // Does the patient ID exist?
       select pt_name into :ls_pt_name from patients where pt_id = :al_patient_id;
       if sqlca.sqlcode = 100 then
         g.warn( "Invalid patient ID: " + string( al_patient_id ) )
         al_patient_id = 0
       end if

       end if

       // Save the patient ID
       il_patient_id = al_patient_id

       // Reset the patient name property (so the setter() is executed)
       g.s_patient_name = is_pt_name // SELECTed above (or blank)

The patient ID setter illustrates the advantage of the property over the global variable. It provides a hook where the patient_id can be validated, especially against the ever-troublesome NULL value. The g.warn() presents its message in a console window during development and always logs the message so the developer will get a clue if some error is leading to assigning invalid patient IDs and the support team can inspect the log file when "wrong name" bugs appear.


About Hoyt Nelson
Hoyt Nelson is an independent contractor, a 10-year PowerBuilder veteran, and father to the amazing Nelson, Kent, Emma, and Molly (Hi, kids!).

In order to post a comment you need to be registered and logged in.

Register | Sign-in

Reader Feedback: Page 1 of 1

I checked it with PB 11 Beta and it works with .NET generation also.


Your Feedback
Arthur Hefti wrote: I checked it with PB 11 Beta and it works with .NET generation also.
Enterprise Open Source Magazine Latest Stories . . .
Apache Deltacloud, the Red Hat-contributed ReSTful API that abstracts differences between clouds so services on any cloud can be managed – provided of course there’s a driver – has graduated from the Apache Foundation’s incubator and is now a full-fledged Top-Level Project (TLP). The...
With Cloud Expo 2012 New York (10th Cloud Expo) just four months away, what better time to start introducing you in greater detail to the distinguished individuals in our incredible Speaker Faculty for the technical and strategy sessions at the conference... We have technical and st...
AMD said late Tuesday that its chief sales officer Emilio Ghilardi had left the company and that CEO and president Rory Read is going to do his job while a replacement is sought. AMD didn’t say why Ghilardi left but it’s assumed Read wants his own people. Read is relatively new to th...
During the lifespan of M3 (Monitis Monitor Manager) there has always been something lacking – timers. M3 execution procedure was outlined in this previous article. The execution mentioned in the latter was a one-time-execution, whereas server monitoring requires periodic invocati...
Red Hat is putting its bought-in Gluster scale-out NAS storage technology, acquired in October, on the Amazon cloud. It’s styled Red Hat Virtual Storage Appliance for Amazon Web Services and other clouds are supposed to follow in short order.
A new episode of the screencast series is now available at the OpenNebula YouTube Channel. This screencast demonstrates the new easily-customizable self-service portal for cloud consumers. Its aim is to offer a simplified access to shared infrastructure for non-IT end users. The scree...
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