Readability, maintainability
Topics:
No unused declarations/objects or useless code
A project should contain no unexecutable paths, no "dead" (unnecessary) code, and no unused type declarations or variables.
Unused program elements in a project quickly lead to confusing code structures. During maintenance and extensions, the readability of the code can be greatly enhanced if the project only contains program elements that are actually used.
Static Analysis:
Verify using the following Static Analysis rules:
- SA0001: Unreachable code
- SA0002: Empty objects
- SA0031: Unused signatures
- SA0032: Unused enumeration constants
- SA0033: Unused variables
- SA0035: Unused input variables
- SA0036: Unused output variables
The rule SA0033 is also included in the license-free variant Static Analysis Light.
Also note the possibility to disable Static Analysis rules and naming conventions locally via pragma or attribute for checked locations where a specific rule/naming convention should no longer be reported (see also: chapter Pragmas and Attributes in TE1200 PLC Static Analysis). Ideally, you should comment on local deactivation with an appropriate explanation.
For example, you can disable the rule SA0002 for intended empty bodies of function blocks locally for this FB body by {analysis -2}
.
No unexecutable paths
Negative sample:
IF FALSE THEN // NON COMPLIANT
F_DoSomethingUsefulHere(); // will never be executed
END_IF
Positive sample:
IF bTest THEN // COMPLIANT
F_DoSomethingUsefulHere(); // it's just a sample
END_IF
No "Dead" (unnecessary) code
Negative sample:
FUNCTION F_Sample_neg : INT
VAR_INPUT
nA : INT; // Variable a in term y = a*a + b
nB : INT; // Variable b in term y = a*a + b
END_VAR
VAR
nTemp : INT; // Used for temporary calculation of a*a
END_VAR
nTemp := nA * nA; // NON COMPLIANT: nTemp will not be used later
F_Sample_neg := nA * nA + nB;
Positive sample:
FUNCTION F_Sample_pos : INT
VAR_INPUT
nA : INT; // Variable a in term y = a*a + b
nB : INT; // Variable b in term y = a*a + b
END_VAR
F_Sample_pos := nA * nA + nB; // COMPLIANT: no dead code in this sample
No "magic numbers"
Do not use "magic numbers".
Alternatively, constants or other fixed values can be used for comparisons or assignments. Texts such as output or comparison texts should be stored in constants, for example, and not defined directly in the source code.
Note also the following topic of the programming conventions:
Negative sample:
PROGRAM Sample_neg
VAR
nValue : INT; // Sample INT-variable that is used for comparison
bValueOk : BOOL; // Indicates if the value of sample INT-variable is OK
END_VAR
// NON COMPLIANT: A "magic value" is used for comparison
bValueOk := (nValue = 125);
Positive sample:
PROGRAM Sample_pos
VAR
nValue : INT; // Sample INT-variable that is used for comparison
bValueOk : BOOL; // Indicates if the value of sample INT-variable is OK
END_VAR
VAR CONSTANT
cValueOk : INT := 125; // Used to validate the sample INT-variable
END_VAR
// COMPLIANT: A constant variable is used for comparison
bValueOk := (nValue = cValueOk);
No multiple use of the same names
Avoid using the same names more than once. This includes the following cases:
- The name of an enumeration constant compared to the name of a variable
- Names of objects among each other
- The name of an object compared with the name of a variable
Static Analysis:
Verify using the following Static Analysis rules:
The rule SA0027 is also included in the license-free variant Static Analysis Light.
Same notation in declaration and implementation
For reasons of uniformity, readability and maintainability, you should use the same notation of program elements and variables in the declaration and in the implementation.
Static Analysis:
Check with the help of Static Analysis rule:
General program elements for the following samples:
FUNCTION F_Sample
Negative sample:
PROGRAM Sample
VAR
bTest : BOOL;
END_VAR
--------------------------
IF btest THEN
f_Sample();
END_IF
Positive sample:
PROGRAM Sample
VAR
bTest : BOOL;
END_VAR
--------------------------
IF bTest THEN
F_Sample();
END_IF
Avoid empty statements (;)
Avoid empty statements (;) so as not to expand the code unnecessarily. If an empty statement is absolutely necessary to clarify a particular case, the empty statement should be on a separate line. Additionally, you should comment why this program branch is empty.
Static Analysis:
Check with the help of Static Analysis rule:
General program elements for the following samples:
PROGRAM Sample
VAR
nTest : INT := 10; // Test value used in sample
END_VAR
Negative sample:
IF nTest = 10 THEN
; // NON COMPLIANT without a useful comment
ELSE
nTest := 10;
END_IF
Positive sample:
IF nTest = 10 THEN
; // COMPLIANT with a comment: In case that nTest is equal to 10, no action is needed. This status is intended.
ELSE
nTest := 10;
END_IF
Each assignment in separate line of code
Each assignment should be in a separate line of code. Thus, assignments should not be in conditions and allocation operators should not contain subexpressions.
Static Analysis:
Check with the help of Static Analysis rule:
General program elements for the following samples:
PROGRAM Sample
VAR
bVar1 : BOOL;
bVar2 : BOOL;
nA : INT;
nB : INT;
nC : INT;
END_VAR
Negative sample:
// NON COMPLIANT: assignment in condition
IF bVar1 := bVar2 THEN
DoSomething();
END_IF
// NON COMPLIANT: more than one assignment in a single line
nA := nC * (nB := nC + nC);
Positive sample:
IF bVar1 = bVar2 THEN
DoSomething();
END_IF
nB := nC + nC;
nA := nC * nB;