LinkedIn

View Lee Dare's profile on LinkedIn

Search This Blog

Monday, July 21, 2008

Synon 2E - Development Standards (Defensive Programming)

Update: 05/12/2025 - I have created a page for all standards related posts.

Some of these are advanced tips.

Part two in the series and takes a look at defensive programming techniques and how these help you to create reliable programs.

The following a guidelines for creating robust code.

Always check for a divide by zero (runtime) error by checking the divisor field for zero value prior to performing the *DIV operation.

Never move numeric fields into a field with a smaller domain.
With RPG this can cause truncation of the value and with RPG ILE Pre 8.0 will cause an RPG ILE runtime error.

Ensure that your iteration values and counters are large enough to cater for your anticipated maximum.

Ensure that your field sizes for database attributes are sized sufficiently to cater for the number of records anticipated.

Ensure that your arrays are sized to cater for the maximum number of array records anticipated.
Thus avoiding array index out of bounds issues. Remember to balance this with not overly sizing the array and thus causing a performance degragetion.

Always ensure that any substring operations utilising position and length parameters are within the range of the target field. Thus avoiding substring out of bounds.

Remember to check the function options for your function to ensure appropriate behaviour, especially close down program and reclaim resources.

Never use the WRK context in new programs. Use LCL and HLL.
If you choose to fix up old WRK fields, remember to check all other internals within your object and ensure that fields aren't used. This used to be used a trick in the old days to bypass the paramters passing limits. This was pre-arrays and when structure files where a pain.

Avoid HLL User Source and Programs. If you do write user source for RPG first convert program to RPG ILE and write one user source. The sign of a well managed and maintained 2E model is the percentage of HLL code versus generated code. If your models are more than 5% HLL then you have issues and a history of developers who have misunderstood the purpose and philosphies of model based development. IMHO.

Always pass parameters to user source. Do not rely on the generated field names.

Avoid use of CON context as these values are not available for impact analysis and localisation.

Avoid manual source modification. Use a program and the pre-processor directives to amend code automatically.


Source Modification – Special Notes.

Manual source modification must be avoided at all costs. If source is required to be overridden then a source modifying program should be written to automatically perform this function after generation and before compilation using the pre-processor.

In Summary:-

- Do NOT consider source modification unless absolutely necessary.

- Avoid the use of fields that use incremental counters for naming i.e. LCL Context YLnnnn.

- Avoid adding parameters above a field declared as a modified field. Therefore, always try to ensure that your fields that are parameters that are modified are at the top of the parameter declaration list.

- Try to avoid usage of fields higher than 32k. If 64k is required considered looping in 32k blocks as the 64k limit would one day be exceeded.

- Consider a naming standard to help you to easily identify a modified program and its modifying program.

- Consider centralised methods to ensure source modification programs have been successful rather then depend on a developer having to manually check the modified source.

Thanks for reading.
Lee.

Sunday, July 6, 2008

Synon 2E - Development Standards (Performance)

Update: 05/12/2025 - I have created a page for all standards related posts.

This is the first part in a complete series of articles I intend to post regarding development best practices and standards for the CA 2e (Synon) development tool. The aim of publishing the guides is to educate, collaborate and enhance the standards by receiving community feedback. After all, no one person can know everything but the wider community can contribute.

Many of these tips I have learnt over the years and quite a lot have been sent to me by interested parties around the world. A big thank you to you all.

I will publish the complete documents on the 2E wiki (soon) with full acknowledgements. (See my links section below).

In the meantime I will publish some selected extracts on this blog just to get your thought processes flowing.

Performance

There are many considerations when programming for performance in CA 2e. A few are highlighted here. This is by no means an exhaustive list. My next technical post will relate to Defensive Programming techniques......

I'd be interested to hear of others from the community in general and would be happy to include them on this blog and the final wiki document.

Drop unused relations where possible and set others to appropriate level. i.e. OPTIONAL or USER etc. This cuts down unneccessary code and processing as well as making your action diagrams more easily navigable.

Avoid FLD for passing parameters for non command line type programs. Will use less PAGs.

Tactically use *QUIT to reduce I/O. Especially when programs have lots of nested validation logic. Very useful when validating. Use the *QUIT inside subroutines to halt further processing. Provides cleaner message feedback to end user and reduces response times.

Avoid Dynamic Selection Access Paths.

Avoid Virtuals, especially Virtuals with relations to files with Virtuals.
Virtuals have their place. Query access paths or in scenarios where they are always used. Best practice in this area is to avoid virtuals and to get data as appropriate.

Ensure programs do not close down if called iteratively.e.g. in a loop or inside USER: Process Record etc for a RTVOBJ or PRTFIL etc. Typically used for externalised RTVOBJs.

Consider sharing ODPs.(Open Data Paths)

Consider usage of shared subroutines.
Minimise the amount of code and reduces object size and makes debugging easier.

Consider usage of Null Update Suppression within your CHGOBJs. Very useful for batch programs.

Avoid unnecessary selector/position fields on subfile selectors.

Avoid contains (CT) selection on control panels

Ensure arrays are appropriately sized.
Too large they will consume more memory.

Reduce file I/O by loading small reference files that are regularly read into arrays upon opening the program. Good examples here wsould be files like TRANSACTION TYPE or XYZ RULES.

Reduce I/O by only getting reference data only on key change. This will depend on the chosen access path of course.

When writing to an IFS write fewer larger chunks of data rather than multiple small chunks. Overhead is opening, positioning and closing the IFS file.

Pass reference data down through call stack rather than re-retrieve in the lower level function.

Consider physical file access paths for fix programs (version 7.0+) or write SQL to perform the basic updates.

Use OS/400 default values to initialise fields on a database file rather than write a program.

CHG/CRT v CRT/CHG. Use the appropriate one depending on likelihood of the records existence.

Avoid *CONCAT and *SUBSTRING native in 2e for long string manipulation. If concatenating for long strings it is possible to keep a counter of where you are to save the concatenation operation time to identify the current position in the string.

Avoid RTV message to build strings with high usage.

Consider DSPFIL instead of DSPTRN, especially true if de-normalisation is designed in the database with any total duplicated into the header record.

Do not perform a *RTVCND for blanks.
Check for blank first in the action diagram.

Consider a database file field for *RTVCND if approriate.

Be aware of the affect of a scan limit for strict selection criteria as the screen will not pause load processing until the subfile if full or EOF reached. Particularly for large files.

Consider the naming conventions of your access paths to ensure that underlying indexes can be shared when key subsets are apparent and ensure that are built and implemented in the correct order to reduce indexes.

Ensure access paths have correct maintenance option i.e. *IMMED, *DLY or *REBLD.

Thanks for reading.
Lee.