Anda di halaman 1dari 74

FAST 4GL SYSTEMS, INC.

Corporate T echnical Documentation

1
Version

Progress Coding

Standards Manual

C O R P O R AT E T E C H N I C A L D O C U M E N TAT I O N

Progress Coding Standards Manual

Fast 4GL Systems, Inc. http://www.fast4gl.com/ 220 White Horse Pike Audubon, NJ 08106 Phone +1 877 327-8445 Fax +1 609 547-7876 By: Christopher Schreiber (chris@fast4gl.com) Thanks to all that contributed their knowledge to the creation of this document. I would especially like to thank Donald Christie (don@cat-it.co.nz) from Catalyst IT Limited (http://www.cat-it.co.nz)

Table of Contents
Document Overview...............................................................................................iv
This Manual is intended to..........................................................................................iv This Manual is not intended to.....................................................................................v

Database Design Considerations............................................................................v


Definition.......................................................................................................................v Tables (or Files)...........................................................................................................vii Fields (or Columns)...................................................................................................viii Indexes...........................................................................................................................x Referential Integrity....................................................................................................xi

Naming Conventions............................................................................................xii
General Naming Conventions....................................................................................xii Procedures...................................................................................................................xii Variables.....................................................................................................................xiv Widgets........................................................................................................................xv Frames........................................................................................................................xvi Buffers.........................................................................................................................xvi Streams.......................................................................................................................xvi Blocks.........................................................................................................................xvii Workfiles and Temp Tables......................................................................................xix External References....................................................................................................xx

Procedure Structure.............................................................................................xx
General Outline...........................................................................................................xx Program Header.......................................................................................................xxii Variables...................................................................................................................xxiii Other Defines.............................................................................................................xxv

i Progress Coding Standards Manual Fast 4GL Systems, Inc.

Forms........................................................................................................................xxvi Startup Routines.....................................................................................................xxvii

Procedure Style.................................................................................................xxvii
Indentation..............................................................................................................xxvii Statements Per Line.................................................................................................xxix Capitalization...........................................................................................................xxix Block Labels.............................................................................................................xxix Punctuation...............................................................................................................xxix Comments..................................................................................................................xxx Dictionary Formats and Labels...............................................................................xxxi Include Files.............................................................................................................xxxii If / Then / Else........................................................................................................xxxiv Case Statement......................................................................................................xxxvii Program Exits.......................................................................................................xxxvii Listing Field Names.............................................................................................xxxviii Listing Format Phrase Options.............................................................................xxxix Listing Frame Phrase Options..............................................................................xxxix Keywords to Not Use....................................................................................................xl Keywords to Avoid.......................................................................................................xl Abbreviations..............................................................................................................xli Miscellaneous.............................................................................................................xlii Frames.......................................................................................................................xliv Transactions...............................................................................................................xlv Error Handling...........................................................................................................xlv Record Reading.........................................................................................................xlvi Record Locking..............................................................................................................l

Portability.................................................................................................................l
Terminals........................................................................................................................l Names...........................................................................................................................lii Workfiles......................................................................................................................lii Operating Systems......................................................................................................liii Color............................................................................................................................liii Operating System Specific.........................................................................................liii

Performance..........................................................................................................liv
ii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Coding Techniques......................................................................................................liv

Multi-Database....................................................................................................lvii
Using Multiple Databases..........................................................................................lvii

Understanding Transactions..............................................................................lviii
Transaction Scope Overview....................................................................................lviii Default Block Scope....................................................................................................lix Controlling Transactions............................................................................................lxi Sub-transactions.......................................................................................................lxiii

Record Locks and Scope.....................................................................................lxiv


Record Locks.............................................................................................................lxiv Record Scope..............................................................................................................lxv

Using XREF and Listings................................................................................lxviii


Listings....................................................................................................................lxviii XREF..........................................................................................................................lxx

iii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Document Overview
These are the reasons why this Progress Coding Standards Manual was created.

1
Chapter

In order to ease Progress program readability and future maintenance, it is important to identify and encourage a consistent coding style. This document does not attempt to address every possible issue because our experience has shown us that the longer the standard is the less compliance there is. We don't expect everyone to agree with the standards outlined here. However, these are the standards and guidelines that come from years of experience and should not be deviated from, except under special situations. No document of this nature should ever be written in a vacuum. We would encourage you let us know of any omissions and weak spots that we can make the necessary changes and help others get off to a good start in their Progress applications.
I C O N K E Y

This Manual is intended to


Set design and programmers programming standards for Progress

Valuable information Notes and comments

Progress code
Other
references

Provide guidelines for team and project leaders during code reviews

It should be a straightforward matter to apply the standards set forth here to all new programs. The aim is to introduce an efficient style of coding that will improve readability, maintenance and performance.

iv Progress Coding Standards Manual Fast 4GL Systems, Inc.

This Manual is not intended to


Teach anyone how to program in Progress.

2
Chapter

This document does not suggest any standard or style for Smartobjects and GUI programming in general. It covers the development of 4GL code and data dictionary only.

Database Design Considerations


Proper Database Design and Naming conventions are probably the most important part of the application development process.
In order for Progress code to be easily readable and maintainable, extensive forethought must go into the design and naming conventions for the database itself.

Definition
D E F I N I T I O N

Foreign key fields have the same field name as they do in their original table. Duplicate field names should not be used except where a foreign key is being defined. should be used to

With field and table names, underscores (_) not hyphens (-) Entering all the avoid potential problems with third party SQL implementations. informa tion Field level help should be entered. correctl y in the Table and field descriptions should be entered. data dictiona Default field formats are entered. ry will lead to There should always be one unique primary index per table. not having to v override Progress Coding Standards Manual Fast 4GL Systems, Inc. these in all procedu res.

The field that repeats the most should be the first component followed by the next most repeating field. This makes searching much more efficient and helps with index compression (note: the most repeating field is the one whose value changes the least over multiple records!). Do not add or delete fields / tables / indices without carrying out impact analysis to anticipate all the effects of the change.

Using a crossreferen ce tool such as Roundta ble, can ease applicat ion develop ment.

vi Progress Coding Standards Manual Fast 4GL Systems, Inc.

Tables (or Files)


T A B L E N A M I N G

If DOS compatibility is desired, file names should be limited to 8 characters even though Progress allows 32. This restriction is lifted in Progress Version 6 with the addition of an 8 character "dump" name to the dictionary. Another reason to keep file names short is that Progress stores these names literally in the compiled R-code. Therefore, long names have a direct impact on R-code size. This also applies to field, variable, and workfile names. Use include files for the dictionary deletion validation. This allows the deletion criteria to be changed even if a database may be in use by other users. Simply edit the include file and recompile the affected procedures.

Even though table names should be kept as short as possible , they should also be long enough to be easily underst ood

vii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Fields (or Columns)


F I E L D N A M I N G

It is recommended that field names be limited to 12 characters, even though Progress allows 32. Be aware of the limitations of using the RECID datatype. During a data dump using EXPORT, Progress converts the RECID to the unknown value (?) . Using stored RECIDs normally requires the developer to write custom dump and load procedures. For DECIMAL fields, the number of decimals stored should match, or exceed the number of decimals displayed in the format. The use of SIDE-LABELS will cause DECIMAL fields using the formatting ">" character to lose decimal alignment depending upon the size of the number displayed (even if the format is the same size). Therefore, the use of the "z" formatting character is recommended. The formats for logical data types should always have the positive format on the left and the negative on the right. A format of "No/Yes" could cause severe logic problems. For character field formats, avoid using the "!" and "9" formatting characters unless a character MUST be entered because Progress does not allow a blank or non-alphabetic character when using this format. The length of a label should be limited to 14 so that the label will not be truncated when displaying WITH 1 COLUMN or WITH 2 COLUMNS. If 3 or 4 COLUMNS are used frequently, the label should not exceed 12 characters. Column-Labels should be the same width or less than the format of the field to act as a "short label" for tight reports and screens. If screen space is limited don't stack column labels more than 2 levels deep.

Make sure to always note, and change if needed, the number of decimal s stored. This is separat e from Avoid using ! and the 9 display formatti format. ng, since these force the user to enter a specific value. It is better to use a flexible format, and validate this.

viii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Avoid using the unknown value (?) as an initial value except for dates. In numeric fields, calculations involving the unknown value usually result in an unknown result.
Example
UPDATE qty price. /* user enters 5 and ? */ ASSIGN total = qty * price. /* total now equals ? */

Always check for the unknow n value (?) as this can cause unexpe cted results. When defining logical fields, list positive value first, then the negativ e. The field should be named after the positive conditio n. Always check data dictiona ry validati on after making any change s.

The initial value for a logical field should always be yes or no. Consider the following:
Example
Format: N/G Label: Net or Gross Initial: N The "N" in Initial might lead the uninitiated into believing that the default is going the be "Net" when actually it will default to a logical No or "G" for "Gross".

Mandatory should generally be set to YES for fields where the unknown value might cause a problem. This is to prevent the logical data corruption described in the previous example. Progress does not check the syntax of a validation expression until a procedure is compiled that utilizes that expression. Whenever a valexp is entered or modified, upon exiting the dictionary test the validation by using:
Example
INSERT customer. This will check the syntax of all validation expressions in the file. Also remember that the dictionary validation only applies to data entry statements (UPDATE, SET and PROMPT-FOR).

ix Progress Coding Standards Manual Fast 4GL Systems, Inc.

Indexes
I N D E X N A M I N G

The primary index should be the index that is used most often for traversing a file with a FOR EACH, not the index mainly used for random access. This will cause the data to be dumped in that order. When the data is subsequently reloaded into a new database, the RECIDs are assigned sequentially to the records during the load. When the primary index is built, it will be build with references to these sequential recids. All other indexes for that will be built with the recids in non-sequential order. Character index components should be defined as Abbreviate set to 'yes' (unless the component is not the last component of the index). This will allow the use of a PROMPT-FOR / FIND USING combination without using the BEGINS function. Do not create indexes that share the same components.
Example
Index-A Field-A Field-B Field-C Index-B Field-A Field-B

Never create an index just becaus e it might be needed in the future. Before creating any index, determi ne what you needs are.

Index-A would be considered redundant in this example, unless if IndexA was unique and Index-B was not.

It is recommended that index names be limited to 12 characters.

x Progress Coding Standards Manual Fast 4GL Systems, Inc.

Referential Integrity
R E F E R E N T I A L I N T E G R I T Y

Referential integrity means ensuring that all foreign keys fields can be resolved to a valid entry in an associated table. This implies that when these foreign key fields are populated a check must be made to ensure the valid entry exists. If an entry is deleted then a check should be made for entries in any table that may use its fields as foreign keys. If such relations exist then the deletion should be disallowed. Typically referential integrity checks must be put in place when:
a value is input to a foreign key field during user interaction an entry is written to the database an entry is being deleted

Using triggers can make sure Referen tial Integrit y is always maintai ned.

Referential integrity can carried out in three places, the data dictionary, database triggers (CREATE, FIND, ASSIGN, WRITE and DELETE) and the application code itself. Use the DELETE trigger to enforce deletion integrity and audit and the WRITE trigger for audit.

xi Progress Coding Standards Manual Fast 4GL Systems, Inc.

Naming Conventions
Following basic Naming Conventions will greatly enhance code readability.

3
Chapter

In order to ease Progress program readability and future maintenance, it is important to identify and encourage a consistent coding style. This document does not attempt to address every possible issue because our experience has shown us that the longer the standard is the less compliance there is. We don't expect everyone to agree with the standards outlined here. However, these are the standards and guidelines that come from years of experience and should not be deviated from, except under special situations.

General Naming Conventions


G E N E R A L N A M I N G C O N V E N T I O N S

All PROGRESS reserved words must be entirely in upper case. Other programming entities, such as variable names, will use either lower case or a mixture of upper and lower case, as described below for various specific instances. For those instances not discussed below, all lower case is the preferred option. Field and Table names will commence with an upper case letter, and will use lower case letters for the remainder of single word names. For multiple word names, each of the words will be separated by the underscore (_) character and each word will start with an upper case letter.

Procedures
P R O C E D U R E S

If compatibility with Progress conventions is desired, the following file name extensions should be used:
File Name Extensions

Follow the

Progres s standar d filenam xii es of Progress Coding Standards Manual Fast 4GL Systems, Inc. .p, .i and .w.

.p .i .w

Procedure Include File Window

xiii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Variables
V A R I A B L E S

To distinguish variables from database fields, it is recommended that a prefix or suffix be used to set the actual name off. This makes it much easier for the maintenance programmer to track variables through a chain of procedures. If the variable is defined LIKE a field, the field name should be contained in the variable name.
Variable Naming
DEFINE VARIABLE DEFINE VARIABLE DEFINE INPUT PARAMETER DEFINE SHARED VARIABLE DEFINE GLOBAL SHARED VARIABLE vDate vItem_no ipUpdate sGLCode gsCompany AS LIKE AS AS AS DATE Item.Item_no LOGICAL CHARACTER INTEGER NO-UNDO. NO-UNDO. NO-UNDO. NO-UNDO. NO-UNDO.

Always prefix variable names with an identific ation of what type of variable you are defining .

Because Version 6 allows the construct db.file.field, it is recommended that database names and file/buffers names be distinct to prevent confusion over database.file and file.field.

xiv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Widgets
W I D G E T S

A number of other widgets are available in V7&V8. The naming conventions for these should be the same as for field and file names but with a prefix indicating what type of object is being referred to. These are as follows:
Widget Naming
br qu cb ed tg rs sl Browse Query Combo Box Editor Box Toggle Box Radio Set Selection List

Widget Examples
DEFINE QUERY quOffice_Header FOR Office_Header.

DEFINE BROWSE brOffice_Header QUERY quOffice_Header DISPLAY Office_Header.Office_Number Office_Header.Office_Type WITH TITLE Select a Office 8 DOWN. DEFINE VARIABLE cbHist_Date AS DATE FORMAT 99/99/9999 VIEW-AS COMBO-BOX LIST-ITEMS 04/07/1066, 20/01/1966/27/10/1991.

xv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Frames
F R A M E S

As with variables, frame names should also have a prefix or suffix to set them off. In addition the frame should be identified by type (local or shared). In multi-screen conversations, the frame may also need to be numbered.
Frame Naming
DEFINE FRAME fMain.

Buffers
B U F F E R S

Buffers should also have a suffix/prefix and be identified as shared or local. The database file name that the buffer represents should be contained in the name.
Buffer Naming
DEFINE BUFFER bCustomer FOR Customer.

Streams
S T R E A M S

Streams should have a suffix or prefix.


Stream Naming
DEFINE STREAM sReport.

xvi Progress Coding Standards Manual Fast 4GL Systems, Inc.

Blocks
B L O C K S

Block labels are to be on a separate line above the block statement.


Block Labels
MAIN-LOOP: REPEAT: DISPLAY Customer.Name. END. /* MAIN-LOOP: */

All large blocks should be named for easier readabil ity.

Block labels should have a suffix or prefix and give some indication as to the nesting level of the block being labeled.
Block Label Names
MAIN-LOOP: REPEAT: /* user interaction */ TRANS-LOOP: /* update transaction */ END. /* TRANS-LOOP: */ END. /* MAIN-LOOP: */

xvii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Labeled blocks should have the block label as a comment next to the END statement for the block, include the colon in the block label for quick/easy access to the beginning and ending of the block.
Block Label Comments
MAIN-LOOP: DO: /* block code here */ END. /* MAIN-LOOP: */

Always comment the end. stateme nt with the block label, so finding the ending to a block of code is easier.

Progress allows duplicate block labels in the same procedure, however, this practice is discouraged because of the potential for confusion.

xviii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Workfiles and Temp Tables


W O R K F I L E S A N D T E M P T A B L E S

To distinguish workfiles from database fields, a prefix should be used. If the workfile represents a dictionary file, the workfile name should contain the dictionary file name. This will make it easier to locate when doing text searches.
Workfile and Temp Table Naming
DEFINE TEMP-TABLE ttCustomer LIKE Customer. DEFINE WORKFILE wfCustomer LIKE Customer.

When an index consists of only one field, the name of the index should be the same as the field. When an index has more than one component, the index should attempt to paraphrase the fields used in the index.
Index Naming
Index Name: cust-ord Index containing cust-num and ord-no fields.

xix Progress Coding Standards Manual Fast 4GL Systems, Inc.

E X T E R N A L R E F E R E N C

Always keep in E S mind to code and test for all deploye d platfor ms, and minimiz e operatin g system calls.

External References

When Progress output is directed to an ASCII file, the following naming conventions should apply. For portability, the file name should not exceed 8 characters with a 3 character suffix. To prevent collisions with other users who may also be writing ASCII files to disk, one of the following conventions can be used: Write to the user's home directory or specially designated temporary directory. Make the name of the file unique. Usually the ETIME function with a tie breaker such as USERID is sufficient to prevent name conflicts. Use a .d suffix for files that contain EXPORTed data.

4
Chapter

Procedure Structure
Following these Procedure Structure guidelines will allow for being able to track the programs flow more easily. General Outline
G E N E R A L P R O C E D U R E O U T L I N E

The general outline or flow of a program should be as follows:


General Outline
1. 2. Header Variables

xx Progress Coding Standards Manual Fast 4GL Systems, Inc.

3. 4. 5. 6.

Other Definitions Forms Procedure Body Exit Point

xxi Progress Coding Standards Manual Fast 4GL Systems, Inc.

Program Header
P R O G R A M H E A D E R

The header of each program shall be organized as follows:


Program Header
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Program Name Application Name / Module Program Location / Directory Copyright notice Modification History / Revisions / Initials / Date Reasons for each change Include file list Files read (Input) Files written (Output) Purpose and general description of program

xxii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Variables
V A R I A B L E S

Variable should be arranged in the following order:


Variables
System wide include file variables. Application specific include file variables. new global shared new shared shared local Variables should be listed alphabetically to make locating them easier.

Almost all variable s should be defined as NOUNDO to reduce writes to the local beforeimage Use shared file and variable enhanc s e sparingl perform y. All ance. shared variable s should be in include files.

All variables, workfiles, and define parameters should be defined as no-undo. All exceptions must be commented to avoid future changes that will cause problems. Variables should always be defined LIKE file.field-name whenever appropriate for self-documentation and ease of maintenance. One possible disadvantage is that LIKE requires that a session be connected to the appropriate database. Variables should not have the same name as a database field or a database (Version 6) for clarity. All NEW SHARED/SHARED variables should be stored in include files passing NEW as a parameter in the procedure where initially defined. This will make maintenance easier and also prevent problems with conflicts in DATATYPE, NO-UNDO, EXTENT, etc.

xxiii Progress Coding Standards Manual Fast 4GL Systems, Inc.

When defining variables, all definition options should be aligned for readability.
Variable Alignment
DEFINE VARIABLE vName DEFINE VARIABLE vKey AS CHARACTER FORMAT x(10) LABEL Name NO-UNDO. AS INTEGER FORMAT zz9 NO-UNDO.

No variables should be defined in a statement other than a DEFINE statement. Progress allows variable definitions in DISPLAY, UPDATE, FORM and other data handling statements, but they are difficult to locate and maintain when DEFINEd in this way.

xxiv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Other Defines
O T H E R D E F I N E S

Other definitions will be described in the following order:


Other Defines
1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. new global shared stream new shared stream shared stream stream new shared buffer shared buffer buffer new shared workfile shared workfile workfile new shared frame shared frame input parameter output parameter input-output parameter

xxv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Forms
F O R M S

Forms definitions will be listed in the following order:


Forms
1. 2. 3. 4. New shared frame include file forms Shared frame include file forms Include file forms Local forms

All FRAME Phrase options associated with a frame should be listed only on the FORM statement for ease of maintenance. All forms described in a program should be given explicit frame names. This is particularly important when FORMs are placed at the beginning of a procedure, scoping them to the procedure block.

xxvi Progress Coding Standards Manual Fast 4GL Systems, Inc.

S T A R T U P R O U T I N E S

Startup Routines

Any include file startup routines such as screen headings and security checks should be listed together. Variable initialization should also done in this section. Exit Point: All procedures should have a common exit point. This is usually a RETURN statement on the last line of the procedure. A RETURN anywhere else in the procedure is similar to a GOTO statement in another language. The only difference is that RETURN can only go back to the calling procedure. This exit point should also be used to HIDE any frames that do not need to be visible when returning to the calling procedure and initialize any shared variables that need to be.

5
Chapter

Procedure Style
Procedure Style is unique to each programmer. However, following these suggestions will allow the programs that you write to be more easily maintained. Indentation
I N D E N T A T I O N

Recommended indentation is 3 spaces. When the level of block nesting gets to the point where lines are being "broken" prematurely, 2 space indentation is allowed, although this can be a symptom of poor program design. All statements contained within a block must be indented:

Properly indented code is easier to read and maintai n.

xxvii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Indentation Example
MAIN-BLOCK: FOR EACH Customer: DISPLAY Customer. ORDER-BLOCK: FOR EACH Order WHERE Order.Cust_Num = Customer.Cust_Num NO-LOCK: DISPLAY Order. END. /* ORDER-BLOCK: */ END. /* MAIN-BLOCK: */

END statements will always line up with the block statement they are ending.

xxviii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Statements Per Line


S T A T E M E N T S P E R L I N E C A P I T A L I Z A T I O N

Only one statement per line is allowed for readability. A statement may not be extended by use of the tilde (~).

Capitalization
All code will be in lower case with the exception of the block labels and text inside a comment.

Block Labels
Major REPEAT and FOR EACH blocks should be preceded with a block label that describes the function of the block. The label should be on a line by itself above the block header (see preceding example). DO blocks only require labels when they are used for some purpose other than grouping statements together such as defining a new frame or changing transaction scope; or when they are more than 10-12 lines long. Any block that is subject to a NEXT, LEAVE, or UNDO statement must have a block label. The NEXT, LEAVE, or UNDO statement should explicitly reference that label.

B L O C K

L A B E L S

Punctuation
P U N C T U A T I O N

All Progress statements are terminated with periods except block labels and block headers (REPEAT/FOR/DO) which are terminated with a colon.

xxix Progress Coding Standards Manual Fast 4GL Systems, Inc.

Comments
C O M M E N T S

All block headers (FOR EACH/REPEAT) should be preceded with a comment describing the purpose of the block, especially if that block is a transaction block. All END statements for blocks should be followed with a comment that "matches" the END to the block header statement. The only exceptions would be blocks that contain very few statements
Comments Example
/* Update Customer Records */ CUST-UPDATE-BLOCK: REPEAT: PROMPT-FOR Customer.Cust_Num. FIND Customer USING Customer.Cust_Num. UPDATE Customer WITH 1 COLUMN. END. /* CUST-UPDATE-BLOCK: */

Proper and extensi ve comme nts will help in docume nting and reading code. This will allow for easier mainten ance and debuggi ng later on.

Multi-line comments should be in the form:


Multi-Line Comments Example
/* This line is the first comments line ** and this is the second line */

Single-line comments should be in the form:


Single-Line Comments Example
/* This is a one line comment */

No need to comment the END statement:


No need to Comment the END
IF true-condition THEN DO: MESSAGE True . END.

xxx Progress Coding Standards Manual Fast 4GL Systems, Inc.

Dictionary Formats and Labels


D I C T I O N A R Y F O R M A T S A N D L A B E L S

Labels, formats, validation and help from the dictionary should be used rather than overriding in the procedure. When overriding dictionary labels, do so on the FORM or DEFINE FRAME statement if one is being used to define the frame. For variables specify LABEL and FORMAT in the DEFINE or FORM statement rather than on data handling statements such as DISPLAY and UPDATE. Use LABEL when defining side-labels and COLUMN-LABEL when defining column labels. Keep the width of the COLUMN-LABEL the same as the FORMAT.
Column-Label Example
Last Date Invoiced Last Date Invoiced -------- -----------------12/31/99 12/31/99

Last Date Invoiced --------12/31/99

In this example, Last!Date!Invoiced may be the best for the convservation of horizontial space at the cost of one line of vertical space.

xxxi Progress Coding Standards Manual Fast 4GL Systems, Inc.

Include Files
I N C L U D E F I L E S

When overriding dictionary labels, do so on the FORM or DEFINE FRAME statement if one is being used to define the frame. Use system include files whenever possible. System include files used across multiple applications are located in the "include" directory. Application specific include files application's subdirectory (e.g. ar/). are located in that

Using named paramet ers, such as {&file} , are easier to debug then using position al paramet ers, such as {1}.

Named parameters rather than positional parameters will be used whenever parameters need to be passed to an include file. It is recommended that include files not be nested more than 3 levels deep as debugging can be difficult. Also the "explosion" of the include files seen when using the COMPILE/LISTING option makes the code difficult to read. Include file coding style, simple includes:
Simple Include Files
{std-var.i}

Include file coding style, simple parameters:


Simple Parameter Include Files
{std-var.i &var-type = NEW}

Include file coding style, multiple parameters:


Multiple Parameter Include Files
{ lookup.i &file-name &frame-attr &key }

= Customer = NO-BOX 2 COLUMNS = Customer.Cust_Num

xxxii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Include files should not terminate a block started outside of the include file. Conversely, an include file should not start a block that ends outside of the include file. Do not hardcode a path name into the include file reference. PROPATH can be used (and dynamically adjusted as necessary) to change the directories at compile time. Do not put comments within curly brackets of an include file call, as the compiler tends to get confused.
Do NOT Use Comments Within an Include File Reference
{ lookup.i &param } /* This may blow up! */ = value

Never hardcode OS specific path names into any program or include.

xxxiii Progress Coding Standards Manual Fast 4GL Systems, Inc.

If / Then / Else
I F T H E N E L S E S T A T E M E N T S

The use of NOT should be avoided. Good style dictates testing a positive condition whenever possible. Okay to use when testing logical functions and variables. Mixed AND and OR conditions should be avoided, but if used the order of evaluation should be explicitly noted through the use of parentheses. Put each condition on a separate line aligning the AND/ORs vertically.
Mixed AND / OR Conditions Example
IF true-cond1 AND true-cond2 AND (true-cond3 OR true-cond4) THEN

Instead of using a nested IF/THEN /ELSE stateme nt, conside r using the CASE stateme nt.

For a group of conditions connected by AND, the most unlikely condition(s) should be tested first. For a group of conditions connected by OR, the most likely condition(s) should be tested first.

xxxiv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Every branch of an IF/THEN/ELSE will use a DO block to enclose the code even if there is only one statement. The cost is a slight increase in R-code size. This will prevent errors if other statements are added to the branch later on.
Example of when to use DO: END. with an IF Statement
IF true-condition THEN {include.i}. If this include file originally had only one statement and more were added later, the new statement would not be conditionally executed. Instead you should use: IF true-condition THEN DO: {include.i} END.

Always place a DO/END block around any include file referen ce.

The only exception would be a nested IF/THEN/ELSE when there was only one possible statement.
Example of when not to use DO: END. with an IF Statement
IF selection = A THEN RUN add.p. ELSE IF selection = C THEN RUN change.p. ELSE IF selection = D THEN RUN delete.p.

xxxv Progress Coding Standards Manual Fast 4GL Systems, Inc.

ELSE statements should appear on separate lines, aligned with the IF statements to which they apply. For compound tests, align the ORs and ANDs.
Compound AND / OR Example
IF condition AND vBegDate > Order.Order_Date AND vEndDate < Order.Order_Date THEN DO: /* Statements */ END.

When testing logical fields or variables, do not use TRUE, FALSE, YES, and NO for comparisons because of reduced performance and larger R-code. Use the Progress CASE statement (V7) when ever possible. If it is necessary to use nested IF statements, use the following constructs:
Multiple IF / THEN / ELSE Example
IF condition AND vBegDate > Order.Order_Date AND vEndDate < Order.Order_Date THEN DO: /* Statements */ END. ELSE IF NOT (condition) THEN DO: /* Statements */ END.

Never use null THEN/E LSE stateme nts, which can lead to confusi on.

The use of "null" THENs and ELSEs is not allowed.


Null THEN / ELSE Example
IF condition THEN . ELSE . This code does compile and illustrates what a null THEN or ELSE is.

xxxvi Progress Coding Standards Manual Fast 4GL Systems, Inc.

Case Statement
C A S E S T A T E M E N T

In Version 7 Progress use the CASE statement, instead of nested IF/THEN/ELSE statements.
Example of the CASE statement
CASE selection WHEN A THEN RUN WHEN C THEN RUN WHEN D THEN RUN OTHERWISE MESSAGE END CASE.

add.p. change.p. delete.p. Incorrect Selection..

Program Exits
P R O G R A M E X I T S

All procedures should have a single exit point. The last statement of every program should be a RETURN and this should be the only RETURN used in a program. To "goto" a RETURN from within the program, use the LEAVE statement.
Example of Program Exits
MAIN: REPEAT: PROMPT-FOR Customer.Cust_Num. FIND Customer USING Customer.Cust_Num NO-ERROR. IF NOT(AVAILABLE(Customer)) THEN LEAVE MAIN. UPDATE Customer WITH 2 COLUMNS. END. /* MAIN */ RETURN.

xxxvii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Listing Field Names


L I S T I N G F I E L D N A M E S

All field names should be "qualified" and typed in as filename.field-name. If common file names are used between multiple databases, the convention dbname.filename.fieldname should be used. Lists of field names in a DISPLAY, UPDATE, FORM, etc. should be shown as follows: All names can fit all on one line:
Example of Fields on one line
DISPLAY Customer.Cust_Num Customer.Name.

Multi-line listing: One field per line indented 3 spaces. Also if the FRAME Phrase is used, it will be aligned with the fields/variables.
Example of Fields on multiple lines
UPDATE Customer.Cust_Num Customer.Name Customer.Address Customer.Phone WITH FRAME fCustFrame.

Listing field names verticall y eases readabil ity and makes it simple to add or delete fields later.

When displaying a subset of an array, use the following notation:


Example of Using an Array
DISPLAY array[1 FOR 5]. This method is easier to read and maintain than listing out each individual array element.

xxxviii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Listing Format Phrase Options


L I S T I N G F O R M A T P H R A S E O P T I O N S

When FORMAT Phrase options are used, they should be aligned vertically or horizontally.
Example of Format Phrase Options
UPDATE Customer.Name HELP Enter Customer Name VALIDATE (Customer.Name NE ,Customer Name Must Be Entered) Customer.Contact AT 20 HELP Enter Customer Contact. UPDATE vStartDate vEndDate AT 10 AT 50 HELP Enter Start Date HELP Enter Ending Date

UPDATE Customer.Name Customer.Contact

HELP Enter Customer Name VALIDATE (Customer.Name NE ,Error) AT 20 HELP Enter Customer Contact.

Listing Frame Phrase Options


L I S T I N G F R A M E P H R A S E O P T I O N S

Arrange frame phrase options in a manner that avoids placement of two integers together for different options.
Example of Frame Phrase Options to Avoid
UPDATE Customer.Name Customer.Phone WITH RETAIN 1 8 DOWN ROW 2 2 COLUMNS.

Example of Frame Phrase Options Preferred


UPDATE Customer.Name Customer.Phone WITH 2 COLUMNS 8 DOWN ROW 2 RETAIN 1.

xxxix Progress Coding Standards Manual Fast 4GL Systems, Inc.

Keywords to Not Use


K E Y W O R D S N O T T O U S E

STOP statement: Useful for testing only. USE-INDEX option: Essentially hard-codes an index name into a procedure. Don't use unless knowledge of data distribution shows that Progress' automatic index selection will be incorrect. Should never be used in Version 7 Progress.

Keywords to Avoid
OF: OF makes code easier to read, but hides the name of the field(s) being used to relate the files together. Ok to use when there are no further qualifications necessary for record selection. Do not use OF and WHERE together. ENTERED function: The ENTERED flag is easily cleared by an UNDO, RETRY and could lead to incorrect results. RELEASE statement: Use of this statement within a TRANSACTION might indicate a lack of understanding record and/or transaction scope. RELEASE cannot release SHARE-LOCK or EXCLUSIVE-LOCKs within a transaction. OR operator: Use in a WHERE clause can negate the efficient use of an index.

K E Y W O R D S

T O A V O I D

Using RELEASE inside of a transac tion will not release the lock on the record.

xl Progress Coding Standards Manual Fast 4GL Systems, Inc.

Abbreviations
A B B R E V I A T I O N S

The abbreviation of variables, file and field names is not allowed. The following keywords should not be abbreviated, because the minimum allowed abbreviation is too short:
Keywords to NOT Abbreviate
ACCUMULATE AVAILABLE AVERAGE ALL COLORS (BLACK, BLUE, CYAN, ETC.) BLINK DATE LIGHT NO-VALIDATE PROMPT-FOR RECID SUB-AVERAGE TRANSACTION UNDERLINE

The following keywords may be abbreviated, but not as much as Progress allows:
Keywords that can be Abbreviated
KEYWORD CHARACTER DECIMAL DESCENDING INTEGER LOGICAL ALLOWED CHAR DEC DESCEND INT LOG

All other Progress supported abbreviations are allowed.

xli Progress Coding Standards Manual Fast 4GL Systems, Inc.

Miscellaneous
M I S C E L L A N E O U S

Hard coding of values into any program is discouraged with the following exceptions: Parameters passed to an include file and unchanging constants (e.g. 12 months in a year). Do not hardcode keylabels into a procedure.
Example of Coding Keylabels
MESSAGE Enter Data and Press + KBLABEL(GO).

Long MESSAGEs that will not fit on one line should be coded:
Example of Long Messages
MESSAGE This is a very long message that will not fit on one line in the code. .

Note in the preceding example that the message string is delimited with a blank on each end. This suggestion also pertains to TITLEs.
Example of Titles
FORM Customer.Cust_Num Customer.Name WITH TITLE Customer Information CENTERED.

xlii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Algebraic style logical operators are preferred over the FORTRAN style. Either style is acceptable.
Example of Operators
Preferred a <> b a <= b a >= b a > b a < b a = b Instead Of a NE b a LE b a GE b a GT b a LT b a EQ b

When using DO WHILE/REPEAT WHILE loops, always test for a "less than" or "greater than" condition rather than "equal to". This prevents infinite looping if the "equal to" condition is never met.
Example of an Acceptable Check
TEST-BLOCK: DO WHILE TRUE: /* statements */ IF vCounter <= 0 THEN LEAVE TEST-BLOCK. END. /* TEST-BLOCK */

Example of an Unacceptable Check


TEST-BLOCK: DO WHILE TRUE: /* statements */ IF vCounter = 0 THEN LEAVE TEST-BLOCK. END. /* TEST-BLOCK */

xliii Progress Coding Standards Manual Fast 4GL Systems, Inc.

TRIM character field sensitive to leading blanks (i.e. sort fields). The fields in a FORM statement should be listed vertically one per line for ease of maintenance.
Example of a Form Statement
FORM Customer.Cust_Num Customer.Name Customer.Phone WITH CENTERED ROW 2.

Example of an Unacceptable Form Statement


FORM Customer.Cust_Num Customer.Name Customer.Phone WITH CENTERED.

Frames
F R A M E S

Frames should be standardized using the default box or NOBOX. Frames used for printed output should use NO-BOX to recover the blank line (and columns) that Progress allocates for the "invisible" graphics box at the top of the frame. For standardized frame widths on reports, use standard WIDTHs that match the characters per inch normally used on the printer:
Frame Widths
10 CPI: 12 CPI: etc. 75/125 90/140

Avoid widths that exceed 132 columns particularly because this compromises the ability for a user to send a wide report to their terminal (using the TERMINAL statement) without wrapping. In addition, it means that there is not need to support condensed/compressed print for a potentially variety of printers. To make maximum use of paper, but still leave an adequate margin, use PAGE-SIZE 60.

xliv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Transactions
T R A N S A C T I O N S

Block headers that define a transaction should explicitly use the TRANSACTION keyword for self-documentation. This will allow the compiler to catch possible transaction errors.

Error Handling
A Progress error (e.g. entering a duplicate key into a unique index) should not send the user back to the beginning of the block which is the Progress default (UNDO, RETRY). Instead, more localized DO ON ERROR blocks along with NEXT-PROMPT should be used to keep the cursor on the field where the error occurred. The UNDO statement should never be used without a RETRY, NEXT, LEAVE or RETURN even though Progress allows it. Always follow the UNDO with the appropriate action (NEXT, LEAVE, RETRY, RETURN) and a label if appropriate. Although Progress allows the use of RETURN, as stated earlier this is to be avoided.

E R R O R H A N D L I N G

xlv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Record Reading
R E C O R D R E A D I N G

Always use WHERE instead of OF so that whoever is looking at the code always knows which fields are being used to join files, unless there are no further conditions necessary for record selection. Do not use OF and WHERE together.
Example of Acceptable Record Reading
ORDER-BLOCK: FOR EACH Order WHERE Order.Cust_Num = 1000 NO-LOCK: DISPLAY Order.Cust_Num Order.Ord_Num. ITEM-BLOCK: FOR EACH Order_Line OF Order NO-LOCK: DISPLAY Order_Line.Order_Line_Num Order_Line.Item_Num. END. /* ITEM-BLOCK: */ END. /* ORDER-BLOCK: */

Example of Unacceptable Record Reading


ORDER-BLOCK: FOR EACH Order WHERE Order.Cust_Num = 1000 NO-LOCK: DISPLAY Order.Cust_Num Order.Ord_Num. ITEM-BLOCK: FOR EACH Order_Line OF Order WHERE Order_Line.Order_Qty > 0 NO-LOCK: DISPLAY Order_Line.Order_Line_Num Order_Line.Item_Num. END. /* ITEM-BLOCK: */ END. /* ORDER-BLOCK: */

xlvi Progress Coding Standards Manual Fast 4GL Systems, Inc.

USING may be used instead of WHERE because USING specifies the key being used. For good style the left side of the comparison in a WHERE clause will always be the field used to retrieve the record.
Example of a Where Clause
FIND Customer WHERE Customer.Cust_Num = 10. Instead of: FIND Customer WHERE 10 = Customer.Cust_Num.

If the transaction level and framing support it, all related records should be found in a single FOR EACH statement.
Example of a Compound FOR EACH Statement
FOR EACH Customer NO-LOCK, EACH Order NO-LOCK WHERE Order.Cust_Num = Customer.Cust_Num, EACH Order_Line NO-LOCK WHERE Order_Line.Order_Num = Order.Ord_Num: END.

xlvii Progress Coding Standards Manual Fast 4GL Systems, Inc.

When there are multiple conditions in the WHERE clause, use the following form (note the indentation):
Example of Multiple Condition WHERE Clause
Example 1: FOR EACH Customer WHERE Customer.Cust_Num > 10 AND Customer.Cust_Num < 100 AND Customer.State = MA NO-LOCK: END. Example 2: FOR EACH Customer NO-LOCK WHERE Customer.Cust_Num > 10 AND Customer.Cust_Num < 100 AND Customer.State = MA, EACH Order NO-LOCK WHERE Order.Cust_Num = Customer.Cust_Num AND Order.Order_Num > 100 BREAK BY Order.Order_Date BY Customer.Name: END.

When retrieving one-to-one relationship records in a FOR statement, the EACH should be used in case the record is missing. If there is a possibility that a record could be missing, it should be trapped using FIND/NO-ERROR and the AVAILABLE function. When a PROMPT-FOR is followed by a FIND, use NO-ERROR on the FIND statement unless you wish to use the Progress default error handling (an error message followed by UNDO, RETRY of the closest UNDO block). FIND/NO-ERROR will always be followed by a test with the AVAILABLE function. FIND/NO-WAIT will always be followed by a test with the LOCKED function.

xlviii Progress Coding Standards Manual Fast 4GL Systems, Inc.

The order of comparisons in a WHERE clause should follow this hierarchy:


Order of Comparisons in a WHERE Clause
1. Fields of the index being used by the FIND/FOR EACH statement. The comparisons should be in the same order as the fields occur in the index. 2. 3. 4. 5. Fields from indexes not being used by the FIND/FOR EACH. Non-indexed fields. Variables. Expressions.

Do not use a FIND statement on a non-unique index or when all of the components of a unique index are not supplied. FIND is designed to retrieve a single record based upon unique index information. Use FIND FIRST/NEXT/PREY/LAST for all other situations. Do not use a FOR block when retrieving a single record based upon a one-to-one relationship.
Do Not Use a Join for a one-to-one Relationship
FOR EACH Order_Line: DISPLAY Order_Line. FOR EACH Item OF Order_Line: DISPLAY Item. END. END. The use of FOR EACH when retrieving the item misleads one into thinking that the order-line: item relationship is one-to-many rather than oneto-one.

When testing logical fields or variables in a WHERE clause, explicitly test against the implicit true or false value of the field for R-code and performance reasons.

xlix Progress Coding Standards Manual Fast 4GL Systems, Inc.

R E C O R D L O C K I N G

Record Locking

Use NO-LOCK whenever the state of the information is not important (e.g. most inquiries and reports) to reduce contention and improve performance. When it is reasonably certain that a user will be updating an existing record and that record will not cause locking contention, read the record EXCLUSIVE-LOCK. This will reduce the potential for deadly embrace as well as offer a small performance gain. SHARE-LOCK should never be used. With SHARE-LOCK the possibility always exists that deadly embraces, or deadlock, might occur. Always explicitly state the lock status. The use of the -NL startup option is forbidden.

6
Chapter

Portability
Since Progress programs can be deployed on many different platforms, it is important to keep some of these Portability issues in mind when programming. Terminals
T E R M I N A L S

Because the possibility exists that Progress may be run using terminals with a varying number of available lines (25 for DOS, 24 for most ASCII terminals), use the following functions to calculate the available lines and make maximum use of the available screen space.

l Progress Coding Standards Manual Fast 4GL Systems, Inc.

Screen Checking Functions


SCREEN-LINES FRAME-DOWN FRAME-ROW FRAME-LINE In the Frame Phrase: expression DOWN ROW expression

The same situation exists with space taking and non-space taking terminals. To take maximum advantage of available screen space and still maintain portability, the following is recommended: All frames with data entry or using color attributes will be use ATTR-SPACE in the Frame Phrase for that frame. All procedures will be compiled with the NO-ATTR-SPACE option.

li Progress Coding Standards Manual Fast 4GL Systems, Inc.

Names
N A M E S

If DOS compatibility is needed, the following items will be limited to 8 characters in length.
DOS Limitations
File Names Procedure Names Include File Names

Name suffixes are limited to 3 characters. The period "." may not be used in the body of the name, but only to separate the procedure or include name from the suffix. All procedure and include file names should be in lower case.

Workfiles
W O R K F I L E S

On 640K DOS machines, there is very little memory available to allocate to local buffer space (the -l parameter). The 64K barrier on local buffer size on DOS machines affects portability when large numbers of workfile records might be created. Because of this, the use of workfiles is discouraged unless both of the following conditions are met: The number of workfile records created will remain static or not exceed a predetermined "high water mark". The workfile records will not be increased in size during execution of the procedure.

lii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Operating Systems
O P E R S T I N G S Y S T E M S

Use the OPSYS function to shield operating system calls.


Checking for the Operating System Example
CASE OPSYS WHEN unix THEN UNIX. WHEN msdos THEN DOS. WHEN vms THEN VMS. WHEN btos THEN BTOS. WHEN os2 THEN OS2. WHEN os400 THEN OS400. WHEN nt THEN NT. OTHERWISE MESSAGE Unknown Operating System: OPSYS. END CASE.

Color
C O L O R

Use the COLOR VALUE (color-variable) in all frame phrases. An installation that starts with monochrome monitors and then migrates to color can easily take advantage of the color if the coding is done in this style.

Operating System Specific


O P E R A T I N G S Y S T E M S P E C I F I C

OUTPUT THRU is very useful and powerful, but is not supported on all Progress platforms. AUTO-RETURN should never be used. When a transaction completes, the user should be informed with a message that the transaction has successfully finished and been committed to the database. Warning messages should be preceded with "WARNING:" Error messages should be preceded with "ERROR:". This includes the valmsg in the dictionary as well as the second argument of the VALIDATE format phrase option. All error messages should be accompanied by an audible BELL. Help messages should be preceded with "Enter". Because the END-ERROR key has two possible actions that might be taken, the ambiguous nature of the key can confuse users.

liii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Performance
Although Performance is often not the first priority when programming, it is important to keep some of these basic concepts in mind. Coding Techniques
C O D I N G T E C H N I Q U E S

7
Chapter

CAN-FIND is more efficient than FIND because CAN-FIND only looks at the index (usually 1 I/O operation) where FIND retrieves the entire record (minimum of 2 I/Os). For the display of constant data, the construct:
Example of Displaying Constant Data
FORM This is a constant string WITH FRAME fTest. VIEW FRAME fTest. /* This is more efficient then: */ DISPLAY This is a constant string.

liv Progress Coding Standards Manual Fast 4GL Systems, Inc.

When there are more than 1 assignments next to each other, use the ASSIGN statement.
Example of the Assign Statement
ASSIGN vVar1 = vVar2 vVar3 = vVar4. /* This is more efficient, and produces smaller R-code then ** the following: */ vVar1 = vVar2. vVar3 = vVar4.

Minimize RUN statements (use include files if possible) and use a fully qualified path name with a RUN statement. Only qualify the path from the top directory of the application to allow flexibility in a development/production environment. Minimize calls to the operating system. When sharing a record between programs, use SHARED BUFFERs instead of passing a RECID with a shared variable. Exception: when reading the record NO-LOCK in the calling procedure (no transaction active) and re-reading the record EXCLUSIVE-LOCK in the sub-procedure to limit the transaction to the sub-procedure. When a variable is changed in a transaction or sub-transaction that variable and all other variables in that procedure are written to the local before image (.lbi) file. To reduce the overhead of this journaling, define variables as NO-UNDO when:
When is use NO-UNDO Variables
1. 2. 3. 4. in. The variable represents a constant that will never change. The variable is always initialized before it is used. UNDO processing serves no useful purpose. The variable is changed in a loop that an error may not occur

lv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Reading a record NO-LOCK eliminates the need for Progress to check the locking table for a slight performance gain. Read records EXCLUSIVE-LOCK instead of the default which is a SHARE-LOCK upgraded to an EXCLUSIVE-LOCK when the record is updated. For multiple string comparisons, use CAN-DO, LOOKUP or INDEX versus multiple comparisons ORed together.
Examples of CAN-DO and LOOKUP
CAN-DO(PA,NJ,DE,vState) /* This is the most effiecent */ LOOKUP(vState,PA,NJ,DE) <> 0 vState = PA OR vState = NJ OR vState = DE /* Do Not Use */

Reduce start/stop of transactions in a tight loop (e.g. batch creation of a large number of records).
Example of Reducing Transactions
INPUT FROM datafile. REPEAT TRANSACTION: REPEAT vCounter = 1 TO 100: CREATE Customer. IMPORT Customer. END. END. /* Is more efficient then: */ INPUT FROM datafile. REPEAT: CREATE Customer. IMPORT Customer. END.

lvi Progress Coding Standards Manual Fast 4GL Systems, Inc.

When loading data into a database, use the NO-ECHO option on the INPUT FROM statement. When loading data into the database, use IMPORT (Version 6 and later) rather than SET or UPDATE. Only use WORKFILEs for a fixed number of static records Creating WORKFILE records in an unrestricted way can crash the user by running out of local buffer (-l) memory. Also resizing existing WORKFILE records is a potential performance inhibitor.

8
Chapter

Multi-Database
Working in a Multiple Database environment can bring up some more issues to be concerned about. Using Multiple Databases
U S I N G M U L T I P L E D A T A B A S E S

Do not use the Progress Auto-Connect feature. It can cause unexpected pauses in a procedure as the connection is initiated. For modularity, put ail CONNECT logic at the start of the user's session. Use NO-ERROR on the CONNECT and test to see if the connection was established using the CONNECTED function. Use one CONNECT statement per database. If a multi-database CONNECT fails, all subsequent connections will not be established.

lvii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Understanding Transactions
Transactions, and how Progress handles them, are often difficult but yet an important concept for programmers to grasp.

9
Chapter

The manner in which Progress handles transactions is one of the unique and powerful features of the 4GL. It is also an area that we tend to struggle with usually because we imagine that the subject is more complex than it is in reality. This is an important subject, however, as with a little bad planning and careless programming it is possible to adversely and dangerous affect the behavior of your application from both a user interface point of view and a performance and "physical" database point of view.

Transaction Scope Overview


T R A N S A C T I O N S C O P E O V E R V I E W

A transaction scope is logical grouping of changes being carried out to data that Progress guarantees will either be committed as a whole or UNDOne as a whole. Reasons for undoing a transaction will range from a user deciding to abort the current set of changes (pressing F4 for example), to applications errors, to hardware failure. Each completed transaction is guaranteed to have been written permanently to the database whilst any incomplete transactions will not be written to the database of they are interrupted. If you are unsure whether a transaction is currently active in your program use the TRANSACTION function which will return true if a transaction is currently active.

lviii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Default Block Scope


D E F A U L T B L O C K S C O P E

Progress code is structured in blocks. These take the form of procedures, triggers, DO blocks (including IF/THEN DO), FOR EACH and REPEAT. Of these the procedures, triggers, FOR EACH, DO ON ERROR and REPEAT will start a transation if there is a find with an EXCLUSIVE-LOCK in their block. This meanes that should a change be made to the data or a record found with an exclusive lock within these blocks, a transaction will be scoped to the bounds of those blocks. DO blocks have weak transaction scoping. If a change to data is made to a DO block then the transaction is scoped to the next outer transaction block.
Example #1
REPEAT: /* transaction starts here */ /* some code ....... */ FIND FIRST Order EXCLUSIVE-LOCK NO-WAIT NO-ERROR. /* Check locked status ....... */ UPDATE Order. /* some code ....... */ END. /*transaction ends here */

Example #2
REPEAT: /* transaction DOES NOT start here */ /* some code ....... */ REPEAT: /* transaction starts here */ FIND FIRST Order EXCLUSIVE-LOCK NO-WAIT NO-ERROR. /* Check locked status ....... */ UPDATE Order. END. /* transaction ends here */ /* some code ....... */ END. /* repeat */

lix Progress Coding Standards Manual Fast 4GL Systems, Inc.

Example #3
REPEAT: /* transaction starts here */ /* some code */ DO WHILE TRUE: FIND FIRST Order EXCLUSIVE-LOCK NO-WAIT NO-ERROR. /* Check locked status ....... */ UPDATE Order. END. /* DO WHILE */ /* some code ....... */ END. /*transaction ends here */

Example #4
/* start of a procedure transaction starts here */ FIND FIRST Customer EXCLUSIVE-LOCK NO-WAIT NO-ERROR. /* Check locked status ....... */ UPDATE Customer. /* Some code */ REPEAT: /* some code.... */ FIND NEXT Order OF Customer EXCLUSIVE-LOCK NO-WAIT NO-ERROR. /* Check locked status ....... */ UPDATE Order. /* some code.... */ END. /*end of the procedure transaction ends here */

lx Progress Coding Standards Manual Fast 4GL Systems, Inc.

Controlling Transactions
C O N T R O L L I N G T R A N S A C T I O N S

It is possible to force any block to start a transaction by using the TRANSACTION keyword (note this differs from the TRANSACTION function mentioned above). This method can be used to both increase and decrease the size of a transaction. Take Example 4 from above:
Example #4
/* start of a procedure transaction starts here */ DO TRANSACTION: /* Transaction starts here */ FIND FIRST Customer EXCLUSIVE-LOCK NO-WAIT NO-ERROR. /* Check locked status ....... */ UPDATE Customer. /* Some code */ END. /* Transaction ends here */ /* some code */ REPEAT: /* some code.... */ DO TRANSACTION: /* Another Transaction starts here */ FIND NEXT Order OF Customer EXCLUSIVE-LOCK NO-WAIT NO-ERROR. /* Check locked status ....... */ UPDATE Order. /* some code.... */ END. /* Second Transaction ends here */ END. /*end of the procedure */

The transactions in this example have now been scoped in a much more granular fashion.

lxi Progress Coding Standards Manual Fast 4GL Systems, Inc.

You may want to increase the scope of a transaction boundary:


Example #5
DO TRANSACTION: /* Transaction starts here */ FOR EACH Order EXCLUSIVE-LOCK: DELETE Order. END. END. /* Transaction End */

If a system crash occurs here none of the Order records will be deleted. Of course this scenario also holds locks on all the records until the end of the transaction.

lxii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Sub-transactions
S U B - T R A N S A C T I O N S

With Progress it is only possible to have one active transaction at a time. If a transaction block becomes part of an existing transaction it will form a sub-transaction. Sub-transactions can be used to UNDO parts of a transaction, however, the changes made in a sub-transaction do not get committed until the end of the main transaction. One of the most common ways of starting a sub-transaction is by calling another procedure whilst a transaction is active.
Example #6
DO TRANSACTION ON ERROR UNDO, RETRY: /* transaction starts here */ IF RETRY THEN MESSAGE "You've undone your customer changes as well." IF NOT CAN-FIND Customer OF WHERE Customer-Name = "Test") THEN RUN newcust.p. FIND FIRST Order EXCLUSIVE-LOCK. UPDATE Order WITH 2 COLUMN. END. /**** newcust.p ***** /* Program to add a new customer */ /* some code */ DO TRANSACTION ON-ERROR UNDO, LEAVE: /* start a sub transaction */ FIND FIRST Customer EXCLUSIVE-LOCK. UPDATE Customer WITH 2 COLUMNS. END. /* end a sub transaction */

The program newcust.p may not be expecting to be called within another transaction. Any update made in newcust.p can be rolled back in the calling routine if the user presses F4. Another side effect of this scenario is that a lock will be maintained on the Customer record until the end of the main transaction in the calling procedure.

lxiii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Record Locks and Scope


Understanding Record Locking and Record Scope are essential in order to produce an effective program design. Record Locks
R E C O R D L O C K S

10
Chapter

Progress has row-level locking. This means it locks individual records at a time (as opposed to pages or tables). Two types of lock are supported, they are the SHARE-LOCK and the EXCLUSIVE-LOCK. In addition, Progress can read records with NO-LOCK. A SHARE-LOCK allows a record to be read by more than one user so long as that record is not being modified. A SHARE-LOCK gets upgraded to an EXCLUSIVE-LOCK if the modification on that record begins. An EXCLUSIVE-LOCK prevents any other user modifying or placing a SHARE-LOCK on a record. NO-LOCK allows the record to be read no matter what state another user has it in. It cannot however be modified. NO-LOCK allows dirty reads. In other words, the data that is being read may not have been committed to the database. The Progress default for a record is SHARE-LOCK as this provides the user with the most protection. However, this option is not recommended unless absolutely required. In general, the developer should know what is going to happen to the record and read it with a NO-LOCK or an EXCLUSIVE-LOCK.

lxiv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Record Scope
R E C O R D S C O P E

This subject relates to how long information in a Progress record buffer remains active and by association how long Progress keeps a lock on the record. Record locks are held for the longest of the transaction scope or record buffer scope. It is possible for a record buffer to have a wider scope that the transaction scope. Locks are held on a record not a buffer (remember it is possible to have multiple buffers pointing to one record).
Example #7
FIND FIRST Customer. /* Some code */ DO TRANSACTION: /* transaction start */ UPDATE Customer WITH 2 COLUMNS. END. /* transaction end */ /* Some code */ PAUSE.

The record buffer spans the whole of this procedure, including the PAUSE statement. The first FIND will instigate a SHARE-LOCK on the customer record. When the DO TRANSACTION is encountered the SHARE-LOCK gets upgraded to an EXCLUSIVE-LOCK. At the end of the transaction the changes to the record are committed and the lock on the record is down graded to a SHARED-LOCK.
Example #8
FIND FIRST Customer NO-LOCK. /* Some code */ DO TRANSACTION: /* transaction starts */ FIND FIRST Customer EXCLUSIVE-LOCK. UPDATE Customer WITH 2 COLUMNS. END. /*SHARE-LOCK on Customer record is active */

Note that in the above example the lock status after the end of the transaction is still SHARE-LOCK. In other words, the record can only be read not modified by another user in this state.

lxv Progress Coding Standards Manual Fast 4GL Systems, Inc.

Note that finding another record in the same table will release the SHARE-LOCK.

lxvi Progress Coding Standards Manual Fast 4GL Systems, Inc.

The RELEASE statement can also be used to clear out a record buffer and release the locks on that record at the end of the transaction.
Example #9
FIND FIRST Customer NO-LOCK. /* Some code */ DO TRANSACTION: /* transaction start */ FIND FIRST Customer EXCLUSIVE-LOCK. UPDATE Customer WITH 2 COLUMNS. RELEASE Customer. END. /* transaction end, No more locks held */ /* Some code */ PAUSE.

In this example the lock is released at the end of the transaction but the Customer buffer is no longer available. RELEASE is a bit of a cop-out indicating a failure to properly control your record and transaction scopes. In addition it behaves differently if it is used in a sub-procedure that has been called within an existing record scope. In this case the lock is not released but downgraded to a SHARE-LOCK at the end of the procedure. Finally, it is possible to narrow (or increase) the scope of your record by using the DO FOR tablename construct. This strongly scopes the record to the block. No references to the buffer can be made outside the block without a subsequent FIND.
Example #10
DO TRANSACTION: /* transaction start */ FIND FAST Customer EXCLUSIVE-LOCK. UPDATE Customer WITH 2 COLUMNS. RELEASE Customer. END. /* transaction end, No more locks held */ IF AVAILABLE Customer THEN MESSAGE "Customer record is available"

The free reference to Customer outside the transaction boundary effectively increase the scope of that record (but not the transaction).

lxvii Progress Coding Standards Manual Fast 4GL Systems, Inc.

The following example ensures that the record is not available outside the bounds of the transaction. In fact, it should not compile.
Example #11
DO FOR Customer TRANSACTION: /* transaction start *? FIND FIRST Customer EXCLUSIVE-LOCK. UPDATE Customer WITH 2 COLUMNS. RELEASE Customer. END. /* transaction end, No more locks held */ IF AVAILABLE Customer THEN MESSAGE "Customer record is available".

11
Chapter

Using XREF and Listings


Using the Progress XREF and Listings compiler options can give invaluable insight into a program and are often useful in debugging.
When a program has been completed, it should be compiled to produce two extra files. These are the LISTING file and the XREF (cross-reference) file. These files contain vital information, which will help ensure that your programs behave as expected. Use these files to help with unit testing and code reviews.

Listings
L I S T I N G S

The listing file expands include files and numbers the program lines by block. At the end of the listing is a summary of each block within the procedure, the procedure itself being the main block. The record buffers and transaction that are scoped to the block are shown, as are the frame scopes.

lxviii Progress Coding Standards Manual Fast 4GL Systems, Inc.

Use the COMPILE filename.p LISTING filename.lst option form the PROGRESS editor of the Compile option in the Application Compiler to produce the output file.
Example Listing
1 showlist.p 2 3 {} Line Blk 4 ------5 1 1 DO FOR Account: 6 2 2 DO TRANSACTION: /* start of a transaction */ 7 3 2 FIND FIRST account EXCLUSIVE-LOCK 8 4 2 MESSAGE TRANSACTION. /* "yes" or "no" */ 9 5 2 PAUSE. 10 6 1 END. 11 7 1 12 8 2 REPEAT: /* start of a transaction */ 13 9 2 FIND FIRST policy_header EXCLUSIVE-LOCK. 14 10 2 LEAVE. 15 11 1 END. 16 12 1 17 13 1 /* shows the transaction is complete */ 18 14 1 MESSAGE TRANSACTION. 19 15 1 PAUSE 20 16 END. /* DO FOR Account */ 21 23 File Name Line Blk Type Tran Blk. Label 24 --------------------------------------------25 showlist.p 0 Procedure No 26 showlist.p 1 Do No 27 Buffers: policypl.Account 28 29 showlist.p 2 Do Yes 30 showlist.p 8 Repeat Yes 31 Buffers:policypl.Office_Header 32

Each block start has been highlighted along with the lines of interest at the bottom of the report. The above listing shows that the record buffer for Account is scoped to the outer DO FOR Account: block. That there is no transaction scoped to this block. The inner DO TRANSACTION block has a transaction scoped to it. The REPEAT block has both a record buffer (Office_Header) and a transaction scoped to it.

lxix Progress Coding Standards Manual Fast 4GL Systems, Inc.

XREF
X R E F

The cross reference compile option writes cross reference information between procedures and PROGRESS objects, including procedures, include files, tables, fields indices, variables frames and character strings. Developers must use this facility to check the efficiency of their queries. Whenever a query is used, a SEARCH entry will be made in the XREF file. This is followed by the table name and the name of the index used to resolve the query. If the query is unbracketed (i.e. there are no criteria given to narrow down the search) or PROGRESS is unable to use an index to resolve the query then the phrase WHOLE-INDEX appears after the index name. In the latter instance, the index name is the primary index, which only gives the order in which the records are returned. The rest of the query will be resolved by searching through the whole table. This scenario should be avoided.
Example Xref Program
FIND FIRST Account NO-LOCK. /* unbracketed search - no conditions */

/* this next one is bracketed by a non-indexed field */ FIND FIRST Office_Header. WHERE Office_Header.Effective_Date = TODAY NO-LOCK /* this one is bracketed by a field indexed using a 2nd index */ FIND FIRST Office_Header. WHERE Office_Header.Account_No = Account.Account_No NO-LOCK.

lxx Progress Coding Standards Manual Fast 4GL Systems, Inc.

This produces a number of lines, for index usage look for lines with SEARCH in them. As these XREF lines show:
Example Xref Output
Showref.p Showref.p Showref.p Showref.p showxref.p showxref.p showxref.p showxref.p 1 1 3 6 COMPILE showxref.p SEARCH Account main_key WHOLE-INDEX SEARCH Office_Header main_key WHOLE-INDEX SEARCH Office_Header account

The second line relates to the unbracketed FIND statement, this is a valid scenario. The third line shows a bracketed search (using Effective_Date) that cannot be resolved using an index. The primary index name (main_key) indicates the order in which the records will be returned and the WHOLE-INDEX phrases indicates that the whole table will have to be searched to resolve this query. This should be considered a bug as it will cause severe performance problems. The final highlighted line shows a bracketed query that has been resolved using an index (account). This index was inspected and looks suitable as Account_no (the bracketing field) is also the first component in that index.

lxxi Progress Coding Standards Manual Fast 4GL Systems, Inc.

Anda mungkin juga menyukai