Showing posts with label Context. Show all posts
Showing posts with label Context. Show all posts

Synon 2E Understanding CONstant usages

UPDATE: 06/12/2025 - Linked to a summary post dedicated to deep dive long form posts.

One of my colleagues was trying to track down some (potentially) hardcoded string values/literals.  She had already used the SQL queries in one of my previous posts to narrow down the usages inside messages, however, she was also concerned that there might be some underlying hardcoding via CND and more specifically via CON values.

As a side, IMHO there should be next to no CON usages in a well architected model apart from, values like *BLANK, 0.00 and some tolerance towards values like 12 (months), 52 (weeks), 365 (days), 100 (percentage).  I'd even accept 1,2,3, 9999999 etc.

I draw the line at meaningful literals that could have been scoped conditions (CND) or database values.

My main reason for this is that there isn't a way (via the 2E tool interface) to check for usages of CON values.  Obviously, we can scan the generated source, but then what about all the genuine field names or comments.

Back with 2E!  When generating the source, it somehow lets the generator knows about them and adds them into the code (inline) or as part of a data structure.  Take a look at the bottom of a source listing if you don't believe me.

Here is a sample function using some constants.  Note the 'Create Flatfile' call is passing in 'FLAT FILE CoNsTANT' as CON.

Action diagramming screen CON

And here are the relevant code snippets of generated source i.e. The moves.

Synon AD to RPG

Synon AD to RPG


Followed by the structure of CON values at the bottom.  Note: Sometimes the CON is generated 'inline' at the point of the MOVE.

How RPG handles CON (Constants)


Anyhow, in order for the CON values to be consistently applied, they must be in the 2E model data files somewhere, with the theory being we should also be able to query them.  As CON can only be applied via action diagram text, let's start by looking there in the YMSGACTRFP file.

Synon action diagram database table

It looks like we have some constants referred to in field ELMTTL ** (Element Title - highlighted RED).  This could be a good start but there are some obvious limitations. Whilst it looks like it covers basic *MOVE and *CONCAT field assignments, when we have hardcoded values going into a function call (PURPLE), the CON value isn't reflected in the ELMTTL field.  

**It would appear that the ELMTTL data is used for the AD layout.  Perhaps I will expand more on the complexities of this data in a future post!!!

However, it looks like 2E maintains a surrogate reference for each unique CON value used in the AD regardless of AD syntax used.  (GREEN)

This is awesome, but how are these linked via the function AD?  

To do this, let's take a gander at a subset of the 2E files in the model library. The one highlighted below looks like it could be useful and most likely, a file most dev's didn't even realise existed.  Hands up who has explored the intricacies of the model schema.

Some synon 2E model files

What does the data look like in the table?

Synon CON (Constants)

Bingo, we have our constants.  

Luckily ours are at the bottom of the file :-) for easier blog documentation.  Diving deeper, we have now confirmed that 2E maintains a surrogate reference for each unique CON value and if we refer back to the YMSGACTRFP image above, these are all highlighted in the GREEN section.

So, all that is left for us to do is to identify the CON values we want to analyse, work out what functions they are linked to via the AD code and some pretty cool impact analysis is before us.

Here is a sample SQL retrieving the many different usages of the term 'constant'.  As CON is only ever associated with field @@SUB3, the query is quite straight forward.

Ensuring you have the correct library list.

SELECT DISTINCT b.@@msg, c.OBJNME, b.@@SUB3, a.CON, c.OBJOWN    
FROM YCONDTARFP a LEFT JOIN YMSGACTRFP b ON a.@@CON = 
b.@@SUB3 LEFT JOIN YMDLOBJRFP c on b.@@MSG = c.@@OBJ  
WHERE UPPER(a.CON) LIKE '%CONSTANT%' AND c.CUROBJ = 'Y'                       

This query returns unique records for each of the functions using CON context with the word 'constant', the UPPER() function ensures we don't miss any based-on case differences.  The rest of the query does a basic join to return some additional fields from YMDLOBJRFP (This is the *ALLOBJ or *A model list).  You can add to this query or tidy up names and formatting however you like.

CON Usage query

I hope that this helps someone.

Thanks for reading the
Synon 2E and Plex Emporium by Lee Dare (A developer blog)
Lee.

p.s. This remains one of my favourite posts :-)


Synon 2E It's (ELeM)entary, My Dear Watson

UPDATE: 06/12/2025 - Linked to a summary post dedicated to deep dive long form posts.


I've used this trick a few times so I thought I should share it on the blog before I get run over by a bus.

Often we (developers) are asked to produce or consume data files for integrations with 3rd party systems.  Even with the emergence of web services there are still many many times where the preferred method of interchange is file based, typically these are bulk (high volume) transactional exchanges.  Think payments between banks etc 

For the systems I've worked on we have solved this with .csv delimited inbound and outbound files.  We have also utilised fixed width files, the majority having old school multi-format layouts with a traditional header, detail and footer structure which has some advantages over .csv.

For now, I will also ignore that we could have also provided XML or JSON payloads as part of a real-time integration. 

As you can see, there are numerous ways to skin this cat. However, this is a 2E and Plex blog so for today, let us concentrate on:-

  • How you might build and consume files into a 2E based application. 
  • How can we create a multi-format flat file using purely Synon logic only?

Let's fire up a 5250 session and explore an unsung feature in 2E that helps remove the complexity of building these flat files.

What are we going to build? 


An extract file with a header record, 10 detailed transactional records and a footer which denotes both EOF as well as have a total  for basic validation.  In the real-word this may include hash total etc

An example of what this file data might look like is below.

File format Banking style?


Back in 2E, f
irst define a file with one Known By (Numeric 9.0) should be suffice for most integrations and a second field (Has relation) of 'Flatfile Data' - Type TXT and length of 500 (or whatever length works for your environment). RP4 has better field limits than RPG. 

I've called my file FIXFILP.


Data file 2E sample


Now we need to build the data record, usually you would start concatenating the data values together to meet the design specification of the receiving system and handle those pesky FILLER57 fields etc that always appear from somewhere.

This involves dozens (if not hundreds) of lines of code to concatenate the data.  The resulting action diagram is often difficult to understand and cumbersome to maintain.

What if there was an easier way to build up the data with the ability to easily reorder the fields and cater for changing field lengths.  Well there is, using a neat unsung feature of 2E arrays.

2E keeps track of the last record to be added, changed or read in an array, a sort of cursor I guess.  This is available in action diagram logic hidden in the ELM context. (ELeMent).

The only 'built in' function that can use the ELM context is a *CVTVAR.  

First create an array with the data fields you would like to appear in the dataset, this can be header, detail 1, detail 2, footer etc.  It doesn't really matter for a flat file process.  To keep it nice and simple I have made up some generic fields names with various data types.


Parameters1


Parameters2



Parameters3

I've keyed these arrays based on the Record type of HDR, DTL and FTR.  You can do how best suits your use case.  All the arrays are set with a 'Numer of Elements' of 1 record as I don't need to use the in the traditional sense.  I just need a pointer to an ELM in memory.


Sample AD code

All we then do is call a CRTOBJ over the array to populate the data.  Once in the array, we can use the *CVTVAR to populate a flat file field.  2E handles all the different data types and spits out a well formatted string which you can write to the database/extract file etc

Detail Data

But we are not done.  I've ready other blogs that talk about ELM and they do a pretty good job of explaining the outbound example above.  But not many people realise that depending on whether you are using the ELM context as Input or Output, is the equivalent of constructing or deconstructing the data.  So yes, this method can be used to unpack flat files also. :-)

As long as in the receiving function you have created a shell array record.  You can use ELM to move the data into the array and then standard RTVOBJ functionality to retrieve the record in its deconstructed form.


AD Code

An example below of a couple of screens that I rushed together showing the data string and the subsequent fields.

DSPFIL screen

DSPRCD screen

You simply point the flatfile string to the correct array and 2E will handle everything else.

Thanks for reading the
Synon 2E and Plex Emporium by Lee Dare (A developer blog)
Lee.


Synon 2E - Development Standards (AD & Contexts)

Synon 2E Development Standards - Action Diagram

Synon 2E Development Standards - Contexts

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

Continuing the series of development standards for 2E (Synon). Today's topic is Action diagramming and contexts.
Once again in no particular order.

Beware of a negative list. Do not use a 'negative' LST on a STS field. E.g. If STS field has Val's A,B,C,D then do not create a LST 'Not B' which contains A,C,D. If a new VAL is added to the STS field then the negative LST immediately becomes out of date and also needs amending.
Note: As with Access Paths and File changes, status conditions should be considered a DBA level change and appropriate care and attention taken.

When not to call the *RTVCND. Do not use *RTVCND to get a condition name if the STS field is blank. This is not required as the result should be blank on the screen. Can use a derived field, although these should be discouraged if you are considering thin screen clients and business services for easy migration.

Do not use a *RTVCND in programs that may be converted to other platforms. Feature not supported on other platforms. Not sure on the impact the ADCMS though.

Know how to quit. Never use *QUIT unless you understand explicitly where you are jumping to. Only a few recognised action diagram user points should ever contain a *QUIT. Note, you can quit out of a user defined subroutine. This is a useful technique if you wish to cut down on conditional code.

Pro's
Allows you to strategically exit a subroutine for efficiency i.e. RTVOBJ.
Allows you to suppress PRTOBJ.
Allows you to exit a user defined subroutine. Especially useful for functions with lots of validation logic.

Con's
If used in wrong subroutine can seriously impact the flow of a function.
Care should be taken if code is being copied into other subroutine as the desired affect of the *QUIT may not be the same.
Not directly supported in CA Plex if you are considering a migration.

Do not use *Exit Program in internal functions.

When trying to determine the success or otherwise of a called function you should always check PGM.*Return Code.

Be extra wary of arithmatic operations that might overflow. In particular DO NOT use any tricks to truncate numeric data such as multiplying a 7-digit date by 1 into a 2 byte result field in order to extract the day number. This causes a numeric overflow and may give rise to invalid data. This is especially true (Pre 8.1) for RPGIV generate programs that will also abend with a runtime error that is not a good look to the end user.
Keeping it all in Context.
The following section is about the usage of contexts in 2e.
NLL Context.

NLL context can be used to discard any unwanted output parameters on both internal and external functions.

It will be used predominately on GETs to avoid having to define numerous RTVOBJ functions, each with different parameters. But be aware that a NLL context parameter still creates a usage for that field within the model. Thus you may create lots of spurious field usages. In earlier versions of 2e pre 8.1 the NLL also created NLL fields in the source. This has been resolved and NLL fields are no longer generated.

Pro’s
Cleaner looking action diagram.
In 8.1+ the NLL fields are no longer generated so program are smaller
Easier and quick to default whilst action diagramming.

Con’s

Dumper fields are easier to determine usage for impact analysis as NLL fields are still shown as used.

WRK/LCL context.

Try to use LCL context in preference to WRK context. Unlike WRK context the LCL context is only scoped to the function it's used in. WRK context being scoped to the whole external that the function is generated into.

WRK context should never be used to pass data between function calls, bypassing any parameter declaration.

Be careful about introducing LCL context into existing functions that use WRK context. Mixing the two contexts could be dangerous.

Be EXTRA careful about replacing WRK context. You need to follow through all usages of internal functions that use it to ensure its integrity.

Be aware that LCL context fields are not the same as NEITHER parameters. NEITHER parameters are automatically initialised upon each entry to the function. LCL context fields are only initialised upon program entry and can be used to carry over data between call invocations of the internal function. That is, LCL context can be used to cache function level data.

When reading/writing or processing lots of fields from a given record or model file then PAR context arising from NEITHER parameter access path definitions are preferable to LCL context. PAR context requires a specific parameter declaration that can be queried, and can participate in action diagramming logical parameter defaulting mechanism.

Do not use WRK or LCL context as target of a *MOVE ALL. It doesn't work. You can enter these in the action diagram and 2E will generate a comment but no code will be created.

JOB Context

Care should be taken with the use of the JOB *System Timestamp field. It is only refreshed if moved into a field. Therefore a subsequent query of the JOB context of the field will only be of the last set value. This can equate to Zero.

CON/CND Context

Best Practice - Always use conditions (CND) rather than constants (CON) for non-trivial values. That is, values other than blank or zero. This allows the exact usage of special values to be obtained from the model, and allows translation of condition names. Exceptions are simple values – see below.

CON *BLANK and CON *ZERO are fine for input parameters.

CON is also acceptable for trivial arithmetic operations such as incrementing by 1, sign reversal by multiplying by -1, percentages by dividing by 100, special characters used in *CONCAT such as periods or commas, character position numbers used in *SUBST. National language impact should be considered. i.e. When to use a comma or not. This is especially true for German as they use a comma as the decimal character.

CON.xxxxxxxxxx can also be used to initialise descriptions and text fields in one off initialisation programs.

Note the CON context is not supported in CA Plex and must be converted before any migration can occur.

CON values do no appear in impact analysis.

CON values cannot be exposed for use via the NLS product.

If you have any questions or enquiries about anything published on this blog, please do not hesitate to contact me. I welcome all comments and opinions.

Thanks for reading the
Synon 2E and Plex Emporium by Lee Dare (A developer blog)
Lee.