First the good news: PowerBuilder is a great tool; in fact you can't accidentally do much wrong. This strength is based on a number of reasons. The following is list of why I think PowerBuilder is so great, but you might like to add one or two more items to it: PowerScript is simple; it's easy to learn because of its clearly laid out grammar. PowerScript is a stronglytyped language; many problems simply don't arise because of the compiler telling you about an error. PowerScript is easy to read. PowerBuilder itself takes care of the tedious task of correct indentation. Thus PowerBuilder programs look pretty much the same in terms of "layout" in all PowerBuilder shops around the world. There is no pointer system. You cannot access addresses of objects and do nastythings with them. PowerBuilder does all the low-level memory management for you. There's no need to allocate and dealloacate memory for strings or arrays, as it's done for you. When using objects, garbage collection cleans up after you. No dangling pointers. All references to a single object become invalid whenever the the object is destroyed and can be checked by using IsValid(). Values ofsimple data types are initialized - numeric values with zero, Booleans with FALSE, etc. Those elements are part of the strength of PowerBuilder (plus the DataWindow, of course). However, there are a few pitfalls in PowerBuilder programming that seem to frequently occur. This article will show you some of those issues. I have collected them over time in my function as technical lead where I do a lot ofcode review and "programmers first-level support" as I repeatedly come across the same problems. For some of the problems, I'll propose a workaround to make your programs safer. Let's start.
1. Find With Wrong Parameters
What's wrong with the following piece of code? l_max = ds.RowCount() l_index = ds.Find('x>5', 1, l_max) DO WHILE l_index > 0 of_WorkOn(l_index) l_index = ds.Find('x>5',l_index + 1, l_max) LOOP Answer: It hides a potential endless loop - Find() can search backwards! If the value in column x is greater than 5 in the last row of the DataStore, l_index will eventually become l_max. The Find() will read: l_index = ds.Find('x>5', l_max + 1, l_max) PowerBuilder recognizes that l_max + 1 is greater than l_max and will start to search backwards. Of course, it will find the rowl_max that fits the expression. The perfect endless loop is done. HOW TO AVOID PITFALL 1: This behavior is documented and thus won't change. What can we do about it? There are two workarounds:
Always code the Find finishing not at RowCount(), but at RowCount() + 1. Implement a function Find in your DataWindow or DataStore ancestor class that only takes two arguments: the expression and thestarting row. Within the function use the solution stated above.
2. Incorrect Boolean DataWindow Expressions
This pitfall is really a major problem if programmers are not aware of it, so be warned. PowerBuilder supports two language grammars: PowerScript and DataWindow Expression syntax. Many functions known from PowerScript are available within DataWindow expressions as well, so it's easy forus to code in each of them. But beware, there are some subtle and very important differences. Whats's wrong with the following expression? NOT IsNull(x) AND x > 100 Nothing really. At least if you use it within PowerScript, PowerScript will evaluate it to (NOT IsNull(x)) AND (x > 100) But take care: if you use the same expression within a DataWindow (for Find, Filter, etc.), PowerBuilder willevaluate it to: NOT (IsNull(x) AND (x > 100)) therefore evaluating it to FALSE, because a value cannot be NULL and greater than 100 at the same time. What is the reason for that? DataWindow expressions have a different operator precedence for logical operators compared to PowerScript (and just about any other computer language I know). Usually NOT has precedence over AND, and AND has precedence over...