Should FMStandards pages be written with a single, "ideal" practice in mind, or should we refactor them as a collection of patterns (with certain patterns being "recommended")?
A good example of the difference is illustrated below using the Line endings with semicolons
section of the Indenting & white space article. There are many good solutions to this in the community, and while developers are apparently quite passionate about their choice, there aren't extremely strong reasons to pick one over the other -- it really is a matter of personal preference (see also: bikeshedding).
Personally, I think it would be great to move in the direction of a patterns library, providing taxonomy and nomenclature for many of the ways you might see it done, and guiding people to choose from one or more recommended patterns.
¶ Line endings with semicolons
Don't include a space in front of the semicolon when a line of code is considered functionally "complete". This is done in order to provide a "continuation clue" about the code being read. See the following example. Note that line 11 includes an If() statement which uses multiple lines 11-15. The space after the test parameter of the If () function indicates the function has not been "completed" or "closed". Compare this to lines 3-5 where each variable declaration of the Let() function is considered completed.
Let ( [
// Add names of accounts which are valid developer accounts
~developers = List ( "" ; "" );
~version = Get ( ApplicationVersion );
~isGo = PatternCount ( ~version; "Go" ) = True;
// Account for foreign versions using comma
~versionNumber = GetAsNumber ( Substitute ( ~version ; "," ; "." ) );
// Add a "developer" extended privilege to groups which are valid developer groups
~extendedPrivileges = If ( ~isGo or ~versionNumber ≥ 11 ;
Evaluate ( "Get ( AccountExtendedPrivileges )" ) ;
// else
Evaluate ( "Get ( ExtendedPrivileges )" )
)
];
PatternCount ( ¶& ~developers &¶ ; ¶& Get ( AccountName ) &¶ ) ≥ 1
or PatternCount ( ¶& ~extendedPrivileges &¶ ; ¶& "developer" &¶ ) ≥ 1
or
If ( ~isGo or ~versionNumber ≥ 11;
Evaluate ( "Get ( AccountPrivilegeSetName )" ) = "[Full Access]";
/*else*/ Evaluate ( "Get ( PrivilegeSetName )" ) = "[Full Access]"
)
)
¶ Calculation Formatting
There are several ways you may choose to format your calculations. The most common approaches include Left-Aligned (or Line-Beginning) Semicolons and Right-Aligned (or Line-Ending) Semicolons. Both these approaches improve readability and maintainability compared to other patterns you may encounter.
¶ ⭐ RECOMMENDED: Right-Aligned (Line-Ending) Semicolons
Don't include a space in front of the semicolon when a line of code is considered functionally "complete". This is done in order to provide a "continuation clue" about the code being read. See the following example. Note that line 11 includes an If() statement which uses multiple lines 11-15. The space after the test parameter of the If () function indicates the function has not been "completed" or "closed". Compare this to lines 3-5 where each variable declaration of the Let() function is considered completed.
¶ Example
Let ( [
// Add names of accounts which are valid developer accounts
~developers = List ( "" ; "" );
~version = Get ( ApplicationVersion );
~isGo = PatternCount ( ~version; "Go" ) = True;
// Account for foreign versions using comma
~versionNumber = GetAsNumber ( Substitute ( ~version ; "," ; "." ) );
// Add a "developer" extended privilege to groups which are valid developer groups
~extendedPrivileges = If ( ~isGo or ~versionNumber ≥ 11 ;
Evaluate ( "Get ( AccountExtendedPrivileges )" ) ;
// else
Evaluate ( "Get ( ExtendedPrivileges )" )
)
];
PatternCount ( ¶& ~developers &¶ ; ¶& Get ( AccountName ) &¶ ) ≥ 1
or PatternCount ( ¶& ~extendedPrivileges &¶ ; ¶& "developer" &¶ ) ≥ 1
or
If ( ~isGo or ~versionNumber ≥ 11;
Evaluate ( "Get ( AccountPrivilegeSetName )" ) = "[Full Access]";
/*else*/ Evaluate ( "Get ( PrivilegeSetName )" ) = "[Full Access]"
)
)
¶ ⭐ RECOMMENDED: Left-Aligned (Line-Beginning) Semicolons
Each line after the first begins with an appropriate semicolon. You may also use other syntactic punctuation (e.g.,
()
,[]
) to create a strong visual indicator for indentation levels.¶ Example
Let (
[ // Add names of accounts which are valid developer accounts
~developers = List ( "" ; "" )
; ~version = Get ( ApplicationVersion )
; ~isGo = PatternCount ( ~version; "Go" ) = True
// Account for foreign versions using comma
; ~versionNumber = GetAsNumber ( Substitute ( ~version ; "," ; "." ) )
// Add a "developer" extended privilege to groups which are valid developer groups
; ~extendedPrivileges = If
( ~isGo or ~versionNumber ≥ 11
; Evaluate ( "Get ( AccountExtendedPrivileges )" )
// else
; Evaluate ( "Get ( ExtendedPrivileges )" )
)
]
; PatternCount ( ¶& ~developers &¶ ; ¶& Get ( AccountName ) &¶ ) ≥ 1
or PatternCount ( ¶& ~extendedPrivileges &¶ ; ¶& "developer" &¶ ) ≥ 1
or If
( ~isGo or ~versionNumber ≥ 11
; Evaluate ( "Get ( AccountPrivilegeSetName )" ) = "[Full Access]"
/** ELSE **/
; Evaluate ( "Get ( PrivilegeSetName )" ) = "[Full Access]"
)
)
¶ Compact Calculation
Minimize whitespace and use short variable names.<...etc, etc, etc...>
¶ Example
Let([//Addnamesofaccountswhicharevaliddeveloperaccounts~developers=List("";"");~version=Get(ApplicationVersion);~isGo=PatternCount(~version;"Go")=True//Accountforforeignversionsusingcomma;~versionNumber=GetAsNumber(Substitute(~version;",";"."))//Adda"developer"extendedprivilegetogroupswhicharevaliddevelopergroups;~extendedPrivileges=If(~isGoor~versionNumber≥11;Evaluate("Get(AccountExtendedPrivileges)")//else;Evaluate("Get(ExtendedPrivileges)"))];PatternCount(¶&~developers&¶;¶&Get(AccountName)&¶)≥1orPatternCount(¶&~extendedPrivileges&¶;¶&"developer"&¶)≥1orIf(~isGoor~versionNumber≥11;Evaluate("Get(AccountPrivilegeSetName)")="[FullAccess]"/**ELSE**/;Evaluate("Get(PrivilegeSetName)")="[FullAccess]"))
¶ Comparison of Recommended Patterns
¶ Use Right-Aligned Semicolons when
- you are Todd Geist
- your team has agreed to do it
- you prefer fewer visual distractions
- you like counting parantheses and brackets
¶ Use Left-Aligned Semicolons when
- you are Wim Decorte
- your team as agreed to do it
- you prefer a strong visual indicator of indentation levels
- you hate counting parentheses and brackets