9 Best Practices to Improve Your PowerBuilder Code Quality
Writing clean and efficient PowerBuilder code is essential for developing maintainable, high-performance applications. This guide covers key coding rules that help eliminate unnecessary complexity, improve logic clarity, and ensure best practices for structured programming.
Visual Expert helps you automatically detect these code quality issues in your PowerBuilder and SQL code, allowing you to focus on what matters most: building reliable software. Let's explore the nine most important rules to follow.
- Refactor Loops with At Most One Iteration
- Avoid Hard-Coded FOR Loop End Conditions
- Never Use GOTO Within Loops
- Prefer Structured EXIT Statements in Loops
- Refactor SQL Loops with Single Iterations
- Create Dynamic IF Statement Conditions
- Avoid Nullable Subqueries in NOT IN Conditions
- Eliminate Contradictory WHERE Clause Conditions
- Remove Redundant WHERE Clause Conditions
PowerBuilder Code Quality Rules
1. Refactor Loops with At Most One Iteration
Loops that iterate only once introduce unnecessary complexity and reduce code readability. They should be refactored to execute the contained logic directly.
Why It Matters:
- Reduced Complexity: Simpler code structure improves maintainability
- Improved Readability: Clearer logic makes code easier to understand
- Increased Efficiency: Removes execution overhead for better performance
- Reduced Memory Usage: Minimizes resource consumption
Non-Compliant Code Example:
function integer TestFunctionCall (integer cnt)
integer A = 1, B = cnt
DO WHILE A <= 15 //Non compliant code (Only one iteration will take place because of EXIT)
A = (A + 1) * B;
EXIT;
LOOP
return A
end function
Compliant Code Example:
function integer TestFunctionCall (integer cnt)
integer A = 1, B = cnt
DO WHILE A <= 15 //Compliant code
A = (A + 1) * B;
IF counter > 10 THEN
EXIT;
ELSE
A = B;
END IF;
LOOP
return A
end function
function void TestFunctionCall ()
do while IsValid (lpo_parent) //Compliant code
if lpo_parent.TypeOf() <> window! then
lpo_parent = lpo_parent.GetParent()
else
exit
end if
loop
end function
2. Avoid Hard-Coded FOR Loop End Conditions
Hard-coding end conditions in FOR loops makes code inflexible and prone to errors. Instead, loop boundaries should be dynamically determined based on relevant data.
Why It Matters:
- Flexibility: Adapts to changing data without code modifications
- Readability: Makes loop termination logic clearer
- Efficiency: Allows for quicker adjustments during development
- Consistency: Maintains uniform coding standards across applications
Non-Compliant Code Example:
function string TestFunctionCall (int cnt)
integer i
for i = 1 to 10 //Non compliant code (FOR loop end condition value is hard-coded)
boxes[i].Checked = NOT boxes[i].Checked
next
return "
end function
Compliant Code Example:
function string TestFunctionCall (int cnt)
integer i
for i = 1 to cnt //Compliant code
boxes[i].Checked = NOT boxes[i].Checked
next
return "
end function
3. Never Use GOTO Within Loops
Using GOTO within loops disrupts structured flow control, leading to unexpected jumps that complicate logic tracking and create potential maintenance nightmares.
Why It Matters:
- Prevents Infinite Loops: Ensures controlled execution paths
- Improves Readability: Makes code flow easier to understand
- Enhances Maintainability: Simplifies debugging and modification
Non-Compliant Code Example:
function int TestFunctionCall (int cnt)
DO WHILE cnt <= 15
IF cnt < 0 THEN
goto restart; //Non compliant code (GOTO statement is used within loop)
END IF;
cnt = cnt - 1
LOOP
messagebox('Test','testing... ')
restart:
if isvalid(cnt) and not isnull( cnt ) then
messagebox('Test','is valid found ')
end if
return cnt;
end function
Compliant Code Example:
function cnt TestFunctionCall (int cnt) DO UNTIL (cnt <= 15 AND cnt >= 0) cnt = cnt - 1 LOOP messagebox('Test','testing... ') if isvalid(cnt) and not isnull( cnt ) then messagebox('Test','is valid found ') end if return cnt; end function
4. Prefer Structured EXIT Statements in Loops
Using basic EXIT within loops disrupts structured flow control. Instead, use structured exit conditions such as EXIT WHEN or EXIT FOR to maintain predictable behavior.
Why It Matters:
- Prevents Infinite Loops: Reduces risk of endless execution
- Enhances Readability: Creates more understandable code
- Improves Efficiency: Prevents unnecessary iterations
Non-Compliant Code Example:
function int TestFunctionCall (int cnt)
DO WHILE cnt <= 15
IF cnt < 0 THEN
EXIT; //Non compliant code (EXIT statement is used within loop)
END IF;
cnt = cnt - 1
LOOP
return cnt;
end function
Compliant Code Example:
function cnt TestFunctionCall (int cnt) DO UNTIL (cnt <= 15 AND cnt >= 0) cnt = cnt - 1 LOOP return cnt; end function
5. Refactor SQL Loops with Single Iterations
This rule applies to SQL Server development as well. Any loop that runs only once should be refactored into a simpler construct to improve code clarity and performance.
Why It Matters:
- Eliminates Potential Confusion: Removes ambiguity about the loop's purpose
- Reduces Complexity: Makes the codebase easier to maintain
- Improves Readability: Enhances code clarity for review and modification
Non-Compliant Code Example:
WHILE ( SELECT AVG(ListPrice) FROM dbo.DimProduct) < 300 --Non compliant code (While loop will break after first iteration)
BEGIN
UPDATE dbo.DimProduct SET ListPrice = ListPrice * 2;
SELECT MAX ( ListPrice) FROM dbo.DimProduct;
BREAK;
END
Compliant Code Example:
WHILE ( SELECT AVG(ListPrice) FROM dbo.DimProduct) < 300 --Compliant code (While loop will break based on the IF condition result)
BEGIN
UPDATE dbo.DimProduct
SET ListPrice = ListPrice * 2;
SELECT MAX ( ListPrice) FROM dbo.DimProduct;
IF ( SELECT MAX (ListPrice) FROM dbo.DimProduct) > 500
BREAK;
END
6. Create Dynamic IF Statement Conditions
An IF condition should not always evaluate to TRUE or FALSE. Static conditions lead to redundant checks and unnecessary code execution.
Why It Matters
- Prevents Unconditional Execution: Ensures code runs only when specific conditions are met
- Enhances Accuracy: Guarantees operations occur only when necessary
- Improves Efficiency: Eliminates unnecessary code execution
- Boosts Readability: Promotes clearer code through selective execution
Non-Compliant Code Example:
function string TestFunctionaCall (string cnt) if true then //Non compliant code messagebox('true') end if if false then //Non compliant code messagebox('false') end if return cnt end function
Compliant Code Example:
function string TestFunctionaCall (string cnt) if cnt == 'true' then //Compliant code messagebox('true') end if if cnt == 'false' then //Compliant code messagebox('false') end if return cnt end function
7. Avoid Nullable Subqueries in NOT IN Conditions
Using subqueries that return NULL values within NOT IN conditions can lead to unexpected results. NULL is not recognized as part of the compared set, causing false results.
Why It Matters
- Data Consistency: Prevents inconsistencies in query results
- Enhanced Performance: Streamlines query execution
- Improved Result Accuracy: Ensures precise query outcomes
Non-Compliant Code Example:
CREATE TABLE Type1
(
TypeId INT,
TypeName VARCHAR(50),
TypeCategory VARCHAR(50)
)
GO
CREATE TABLE Type2
(
TypeId INT,
TypeName VARCHAR(50),
TypeCategory VARCHAR(50)
)
GO
SELECT TypeId, TypeName, TypeCategory
FROM Type1
WHERE TypeId NOT IN (SELECT TypeId FROM Type2) --Non compliant code (TypeId column might be null)
Compliant Code Example:
CREATE TABLE Type1
(
TypeId INT,
TypeName VARCHAR(50),
TypeCategory VARCHAR(50)
)
GO
CREATE TABLE Type2
(
TypeId INT IDENTITY(1,1) NOT NULL, --Compliant code (Ensure that TypeId column is not null)
TypeName VARCHAR(50),
TypeCategory VARCHAR(50)
)
GO
SELECT TypeId, TypeName, TypeCategory
FROM Type1
WHERE TypeId NOT IN (SELECT TypeId FROM Type2)
8. Eliminate Contradictory WHERE Clause Conditions
Logical consistency in WHERE
clauses is essential. Contradictory conditions, such as mutually exclusive statements, lead to ambiguity and potentially empty result sets.
For example, the following WHERE
clause contains a contradiction:
WHERE age > 18 AND age < 18
Since a value cannot be both greater and less than 18 simultaneously, this condition is logically impossible and should be avoided.
By following this best practice, developers ensure clear, precise queries that are easier to maintain and troubleshoot.
Why It Matters
- Accuracy: Ensures query results reflect intended data selection
- Consistency: Promotes uniformity in data retrieval
- Performance: Optimizes query execution and reduces overhead
Non-Compliant Code Example:
SELECT Product.ProductID,
Product.Name,
Color
FROM Production.Product
WHERE ListPrice > 50 AND ListPrice = 200; --Non compliant code (Where clause condition is contradictory)
Compliant Code Example:
SELECT Product.ProductID,
Product.Name,
Color
FROM Production.Product
WHERE ListPrice > 50; --Compliant code (Where clause condition is not contradictory)
9. Remove Redundant WHERE Clause Conditions
Optimizing WHERE
clauses in SQL queries by removing redundant conditions streamlines execution and improves query performance. Unnecessary conditions increase computational overhead.
Why It Matters
- Reduced Complexity: Simplifies query logic for better maintainability
- Improved Performance: Allows the query optimizer to generate efficient execution plans
- Increased Accuracy: Creates more precise query results
Non-Compliant Code Example:
SELECT Product.ProductID,
Product.Name,
Color
FROM Production.Product
WHERE ListPrice > 50 AND ListPrice = 200; --Non compliant code (Where clause is having redundant conditions)
Compliant Code Example:
SELECT Product.ProductID,
Product.Name,
Color
FROM Production.Product
WHERE ListPrice > 50; --Compliant code (Where clause is not having redundant conditions)