Showing posts with label SELRCD. Show all posts
Showing posts with label SELRCD. Show all posts

Thursday, September 8, 2016

Under the covers of the SELRCD function type


Hi,

This blog touches on the design challenges when using select record (SELRCD) function type and makes some recommendations for best practices.  Disclaimer:  These are from personal experience and may not cover all scenarios.  I would be happy to hear of any ideas/improvements that can be made to this post.

SELRCDs can cause quite a few issues if you are not aware of the quirks of how Synon generates the code.

Let's cut straight to the problem domain at hand.  In my sample model you will see that I have two files declared.  You will see that "Lee's File" Refer to "Lee's Reference File" which will mean that if I have a PMTRCD or EDTFIL etc over Lee's file we will be able to prompt for the reference data.


The functions I have over the reference file are as follows, I have removed the default EDTFIL and renamed the database primitive functions inline with our internal development standards.

 The main file has numerous test functions so I have filtered on Edit file only.


The screens (Edit File and Select Records) in the blog post have been tidied (ever so slightly) to ensure that all the fields fit nicely on the screen.

I have generated up the code for the EDTFIL.

Reviewing the generated code.

By default you will see that Synon has generated code to call the SELRCD function upon prompting the field and Synon has chosen my SELRCD based on the reference file.

You will also notice that the parameters for the SELRCD have been defaulted to fields based on the RCD context of the calling program.  In this instance it was an EDTFIL.


This is pretty standard and works a treat.

Now we will add a few additional SELRCDs, you will see these below.  Note the naming of these was deliberate in order to ensure that they appeared after 'Select Lee's Reference Fi'.


In terms of impact analysis you will notice that the SELRCD is showing no usages although we have generated code above that proves the object is called.


This is due to implicit code generation that is automatically added if the field is a result of a foreign key constraint AND is input capable AND a select record exists on the reference file.  If you deleted the SELRCD at this stage and generated the code again the prompt and call logic will not be generated.  Give it a try!


Above is a screen image of the default Synon setup.  Notice the two subfile options at the bottom of the screen.  S allows you to select the SELRCD that should be used, T clears this value and leaves the generator to choose the default SELRCD.


After taking the S option and selecting my SELRCD from the reference file you will see that this is indicated above.  Because we have made an explicit reference to the SELRCD in the device design it will now appear as a usage within Synon.


You will see below that the generated code is as before which is great :-)


In order to help with the blog narrative, please now deselect the SELRCD by taking the subfile option T for default behaviour.   This will clear the reference to the dedicated SELRCD.


Now we will create another SELRCD (again deliberately named).  You will see that it sits above the current (default) select record for the EDTFIL.


If we generate the EDTFIL again we will see that the outcome is no longer the same. The generator now puts a call into the higher ordered SELRCD on the reference file.  We didn't intend for this to happen and a developer doing a regeneration could easily pick this up without knowing.  Quite dangerous....


In this instance, as the keys on the SELRCD are identical there is NOT too much to worry about.  However, in the real world 2nd and subsequent SELRCD functions will typically be over an alternate access path with a different key structure or may have additional parameters or specialist action diagram functionality which may not be the preferred default behaviour.

In order to demonstrate this let's add some fields to the model which we will then associate with a new SELRCD function.


Create yet another SELRCD function over the referenced file.  Note again I have named it deliberately so it appears at the top of a refreshed EDIT FUNCTIONS panel.


I have extended the parameters for this SELRCD to add our five new fields.


Let's generate up the EDTFIL once again and look at the generated code.

Ouch!!  Houston we have a problem.

You will see below that all of the new parameters have been defaulted to CON.  This is because the fields were not found in context for the relationship. i.e. in this case, not part of the RCD context. And because this is a warning message only it may go unnoticed.  Preferably Synon should mark these as errors and only allow the correct context ones to generate correctly i.e RCD example above.

Also we have now picked up yet another SELRCD.  One can conclude that anytime a new SELRCD is added and it appears higher up in the EDIT FUNCTION panel the next time a referencing function is generated it will generate code to call the new SELRCD and not the previous one.  Imagine a highly reference file and the chaos this could bring.


We can do somehing to help here.  Whilst we cannot get at the parameters at the point the implicit call to the SELRCD is made, we can put these fields in the context and populate them accordingly.

Add the fields to the 'Subfile Record' format RCD.  You will notice I set these to hidden.


Then in the action diagram you can set these values using a standard *MOVE built-in function.



Generate the function once more and the generated code now shows the moved and also defaults to the RCD context meaning that you no the parameters are populated with your values and NOT CON blank or Zero.



But I remind you at this stage that these were warnings in the code only.  How many people check the generated source for warnings.  I don't, do you?

Another way to do this is to switch off default processing and take control of the prompting yourself in the action diagram coding.  Back in the EDTFIL function again set the relation checking to 'USER'.




Note: This switches off all referential integrity checking so in the real world you'll also need to add action diagram code for the OPTIONAL/MANDATORY as well as foreign key constraints.  For the purposes of this blog I am only focused on the prompting and calling of the select record.

You can then monitor for prompting on your field and call ANY SELRCD function you think is appropriate.


With this method you get a nice parameter interface for the SELRCD and more importantly it is obvious to another developer that you are initialising the fields for an explicitly called SELRCD rather than an implicitly called on.  Some comments might be useful if you choose the other method.


This highlights the many options you have for calling a SELRCD and should help you decide what is best for your model, team etc.

Once last issue with SELRCDs.  I mentioned earlier that Synon (by default) will chose the highest SELRCD based on the referenced file.  Due to no usages showing it is possible that code will be generated to call an object that hasn't been created or has been removed by a developer thinking it is not used.  This will mean you'll get a 'resolve to object' call error which isn't a good look.


Best tip is to generate up a standard SELRCD for each reference file and implement it at the time the file is created.  If you decide that a file doesn't need prompting, then remove ALL SELRCDs from the file so this code doesn't get generate implicitly.  As you can see from above the code will get generated if the function exists regardless of whether the object exists or not.

Best Practices Summary

  1. Come up with a naming convention for the default SELRCD so that it is first in the list on the EDIT FUNCTIONS panel.  We use '*SLT xxxxxxxxxxxxxxx'.
  2. Always ensure you generate up and implement ALL SELRCD functions.
  3. Always keep the default SELRCD keys the same at the RTV access path.
  4. Always name 2nd and subsequent SELRCD so they appear lower in the EDIT FUNCTIONS panel.
  5. It is recommended you set explicitly the SELRCD you want to call either by the 'S' option or via action diagram coding.
  6. Never delete any SELRCD objects without checking the generated source files or by exploring all file references.

Thanks for reading.
Lee.

Sunday, March 8, 2009

2e Development Standards - Screen Functions (Part II)

Part 2 in the series around screen function types will concentrate on the Select Record (SELRCD) function type.

This is often overlooked as a valuable function as it always appears to be generated on your behalf by 2e when you create a file. However, it has a few useful quirks that require a little thinking and I have often seen everly complicated logic added to them due to a lack of understanding where a simple workaround works quite nicely.

Below I summarise some of the key points when using the SELRCD:-
In general there should only be one SELRCD record per file, the default. I propose you rename your default select per for to '*SLT filename'. (See posts on naming standards). However, there may be occasions when it is necessary to select by a variety of different styles, or by a different key value. For example, where the primary key is a surrogate#.

These reasons may justify having more than one selection program, probably built over different ACPs. All other selects other than the default must be name SLT name and not *SLT name. This ensures correct ordering in the file. If using a different access path I would name them 'SLT By access path'.

The *SLT function is named this way as it will be used by the generator when building implicit field prompting code. The routine is also used to validate a record existence in relation checking. (The check restirction within functionaity). As such a default select must be first on the file and also never have its parameter interface changed unless the keys to the file changes.

CA:2E always regards the first SELRCD it finds on the model file as the default. If an alternative SELRCD should always be called for certain relation checks then that should be assigned via the Access Path relation settings. This situation might arise when a file refers to itself. E.g. Horse Refers to Horse for Mare and Horse Refers to Horse for Sire. At the relation level for the access path it is possible to set a default select record for each relation. Therefore the ordering considerations for the generator to substitute a select record are Function Level – Access Path Level – File Level (First on alphabetically on file).

The standard SELRCD should only perform a selection facility. That is, X=Select. However, a display option may be necessary in some cases as is F9 to Add a record.

Selection logic is usually performed one entity level at a time. Therefore if the SELRCD is for a lower level entity, e.g. 'Owned by', then the high order part of the key(s) will normally be RST.

The standard SELRCD should not pass back values other than the selected key. Validation and passing back of attributes is best left to standard RTVOBJ functions since the user may bypass a selection prompt and enter key values directly.

The SELRCD should not be modified to do anything unusual. If a user exits with *Exit key the default SELRCD will always exit program with return code Y2U0016='no value selected' and also send the same completion message. This processing should not be altered.

The parameter key values passed back should have NOERROR set. This is because CA:2E does not treat a 'no value selected' exit (Y2U0016) as an error when called implicitly. But it would be an error if called explicitly in an action diagram.

Closedown option should be set in the context that the program would be called.

If a SELRCD is not sufficient because of action diagramming restrictions then a DSPFIL may be used instead. But it should have a naming convention of 'SLT By or filename'. It should follow the same logic that a SELRCD would do, i.e. Same parameter definition and same action diagram style. This is often used if additional processing like F9 = Add is required.

The advantages of the DSPFIL method is it allows increased flexibility. But if you do choose this approach then this function will never implicitly be used and developers need to handle the output parameters. That said you could template this kind of function.
Tip

Using a Neither MAP input parameter does allow you to set CTL values for additional filtering.

Thanks for reading.
Lee.