Best Practices - Controls on Updated Properties
The purpose of this document is to provide best practices for controls.
- If the validity of a property is not linked to the value of another property that can be modified in the same transaction, the control can be done on the control rule of the property.
- If the validity of a property depends on the value of other properties, the control must be done globally at the class level.
The reason for this rule is that you cannot assess in which order the properties have been entered and controlled. If you want to perform such controls immediately after data entry in order to enhance the user experience, you can add code to the UI layer attached to the representation. However:
- The entry order might not be the one you expect.
- You have to perform a global control, as the corresponding code can be invoked in service mode. You still have to make sure of the validity of the rules in this mode.
Example: If you want to make sure that no duplicate values exist on the row of a grid, you can specify it in the global control code for the main class. One option would be to use the following code:
If uni(this.COLLECTION(1..maxtab(this.COLLECTION)).MYKEY)<>0 # A duplicate key exists for the row ARET= Fmet this.ASETERROR .... # Place here the right error message End ARET Endif
However, this code is flawed because the deletion of lines in a collection is managed logically by setting a value equal to [V]CST_ADEL
or [V]CST_ANEWDEL
in the ASTALIN property of the collection. This means that trying to insert a new key corresponding to a previously deleted value will also display the error.
The following code should be used instead:
Local Char KEY(20)(1..) Local Integer LINES, CURLIN, L_INDEX, I, J # Let's make a list of the existing codes For CURLIN=1 to maxtab(this.COLLECTION) If this.COLLECTION(CURLIN)<>Null and find(this.COLLECTION(CURLIN).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0 LINES+=1 KEY(LINES)=this.COLLECTION(CURLIN).MYKEY L_INDEX(LINES)=CURLIN Endif Next CURLIN # Now we can test the unicity of the codes J=uni(KEY(1..LINES)) If J<>0 # A duplicate key exists for the row I=find(KEY(J),KEY(1..J-1)) # L_INDEX(I) is the first duplicate key position, and L_INDEX(J) the second position ARET= Fmet this.ASETERROR .... # Place here the right error message End ARET Endif
You can write the following code in the script associated with the collection:
Local Char KEY(20)(1..) Local Integer LINES, CURLIN # Let's make a list of the existing codes For CURLIN=1 to maxtab(this.APARENT.COLLECTION) If this.APARENT.COLLECTION(CURLIN)<>Null and find(this.APARENT.COLLECTION(CURLIN).ASTALIN,[V]CST_ADEL,[V]CST_ANEWDEL)=0 LINES+=1 KEY(LINES)=this.APARENT.COLLECTION(CURLIN).MYKEY Endif Next CURLIN If uni(KEY(1..LINES))<>0 # A duplicate key exists for the row ARET= Fmet this.ASETERROR .... # Place here the right error message End ARET Endif
However, this would be risky from a performance point of view because it would be repeated on every line in service mode.