5 Semantic names

Package wyz.code.offensiveProgramming offers great functionalities at the cost of a few conditions

  1. semantic naming has to be used for function parameters names
  2. semantic naming has to be used for function return type definition
  3. semantic naming has to be used for test case definitions

5.1 What is semantic naming?

I call semantic naming, the fact that a named object used in the code should provide much more information than a dumb name.

Semantic naming in package wyz.code.offensiveProgramming defines a few patterns to declare class, function, function parameters and function return type names. Table below shows the related patterns and exposes the underlying philosophy.

name category philosophy pattern to comply with
class java like, starts with upper-cased letter, camel-cased [A-Z][a-ZA-Z0-9]*
function java like, starts with lower-cased letter, camel-cased [a-z][a-ZA-Z0-9]*
function parameter or function return type R like, bearing information about type and length constraint See below.

Function parameter or return type names must comply with one of the following patterns

  1. <variableNameCamelCase>_<typeInformation>_<lengthConstraint>
  2. <variableNameCamelCase>_<lengthConstraint>_

First pattern is to be used for monomorphic types. Second one for polymorphic types.

Monomorphic types are types that are homogeneous. A string, a double, a MyObject are good example of such monomorphic types. Pattern allows to not only express concisely the type, but also to express some length constraints if needed.

Polymorphic types are useful as soon as your input or output can take many types, according to your context. For example, a R function may return a double, or a warning, or an error. Polymorphic types always end with ’_’ in their names, to make them easy to identify.

The type information part of the pattern has to match one of the recorded entries of the type factory.

The length constraint part ot the pattern follows the PERL pattern ([1-9][0-9]*(l|m|n)?). Letters mean respectively less or equal, more or equal, 1 or n. The length constraint part is optional.

Look at following table to get more intuitive traction on function parameter or function return type declarations.

input name meaning
x_s an unconstrained vector of strings - might contain no entries
x_s_3 a vector of strings with 3 entries
x_s_3l a vector of strings with 3 or less entries
x_s_3m a vector of strings with 3 or more entries
x_s_3n a vector of strings with 3 entries or 1 entry
flag_b_1 a vector of booleans with 1 entry - a.k.a a boolean scalar
z_ an unconstrained polymorphic type vector named z - Nothing more is known about its content
z_2_ a polymorphic type vector named z of length 2 - Nothing more is known about its content

As you can see, rather easy. An advice, when programming try to use meaningful variable names for first part of the pattern. It will ease your job.

5.5 Get naming balance from an R object

Use package function verifyObjectNames to get the results of a full compliance analysis of names for the provided object.

source(system.file('code-samples/both-defs/good/full/AdditionTCFIG1.R', package = 'wyz.code.offensiveProgramming'))
verifyObjectNames(AdditionTCFIG1())
#> $class_name_compliance
#> AdditionTCFIG1 
#>           TRUE 
#> 
#> $function_name_compliance
#>       addDouble      addInteger  addMultiDouble addMultiInteger 
#>            TRUE            TRUE            TRUE            TRUE 
#>    divideByZero   generateError generateWarning 
#>            TRUE            TRUE            TRUE 
#> 
#> $parameter_name_compliance
#>       function_name parameter_name name_compliance_check
#>  1:       addDouble            x_d                  TRUE
#>  2:       addDouble            y_d                  TRUE
#>  3:      addInteger            x_i                  TRUE
#>  4:      addInteger            y_i                  TRUE
#>  5:  addMultiDouble            ...                  TRUE
#>  6: addMultiInteger            x_i                  TRUE
#>  7: addMultiInteger            ...                  TRUE
#>  8:    divideByZero            x_n                  TRUE
#>  9:   generateError           <NA>                  TRUE
#> 10: generateWarning             x_                  TRUE
#>     semantic_naming_check
#>  1:                  TRUE
#>  2:                  TRUE
#>  3:                  TRUE
#>  4:                  TRUE
#>  5:                  TRUE
#>  6:                  TRUE
#>  7:                  TRUE
#>  8:                  TRUE
#>  9:                  TRUE
#> 10:                  TRUE
#> 
#> $classname
#> [1] "AdditionTCFIG1"
#> 
#> $owns_function_return_type_information
#> [1] TRUE
#> 
#> $owns_test_case_definitions
#> [1] TRUE
#> 
#> $supports_strict_compliance
#> [1] TRUE
#> 
#> $supports_lazy_compliance
#> [1] TRUE
#> 
#> $can_be_typed_checked
#> [1] TRUE
#> 
#> $is_function_fully_instrumented
#> [1] TRUE
#> 
#> $missing_functions
#> [1] "none"
#> 
#> $is_test_case_fully_instrumented
#> [1] TRUE
#> 
#> $missing_test_cases
#> [1] "none"
#> 
#> $sof
#> $sof$frt
#> [1] TRUE
#> 
#> $sof$tcd
#> [1] TRUE
#> 
#> $sof$instrumented_fn
#>      function_name return_value
#> 1:       addDouble          x_d
#> 2:      addInteger          x_i
#> 3:  addMultiDouble          x_d
#> 4:    divideByZero          x_d
#> 5: addMultiInteger          x_i
#> 6: generateWarning          x_w
#> 7:   generateError         x_er
#> 
#> $sof$instrumented_tc
#>       function_name standard_evaluation type_checking_enforcement
#>  1:       addDouble             correct                   correct
#>  2:       addDouble             correct                   correct
#>  3:       addDouble             correct                   correct
#>  4:       addDouble             correct                   correct
#>  5:       addDouble             correct                   correct
#>  6:       addDouble           erroneous                 erroneous
#>  7:       addDouble             correct                   failure
#>  8:       addDouble             correct                   failure
#>  9:       addDouble             correct                   failure
#> 10:      addInteger             correct                   correct
#> 11:      addInteger             correct                   correct
#> 12:      addInteger             correct                   correct
#> 13:      addInteger             correct                   correct
#> 14:      addInteger           erroneous                   failure
#> 15:      addInteger             correct                   failure
#> 16:      addInteger             correct                   failure
#> 17:      addInteger             correct                   failure
#> 18:      addInteger             correct                   failure
#> 19:    divideByZero             correct                   correct
#> 20:    divideByZero             correct                   correct
#> 21:    divideByZero             correct                   correct
#> 22: generateWarning             correct                   correct
#> 23:   generateError             failure                   failure
#> 24:  addMultiDouble             correct                   correct
#> 25:  addMultiDouble             correct                   correct
#> 26:  addMultiDouble             correct                   correct
#> 27: addMultiInteger             correct                   correct
#> 28: addMultiInteger             correct                   failure
#> 29: addMultiInteger             correct                   correct
#>       function_name standard_evaluation type_checking_enforcement
#>                test_case
#>  1: <TestCaseDefinition>
#>  2: <TestCaseDefinition>
#>  3: <TestCaseDefinition>
#>  4: <TestCaseDefinition>
#>  5: <TestCaseDefinition>
#>  6: <TestCaseDefinition>
#>  7: <TestCaseDefinition>
#>  8: <TestCaseDefinition>
#>  9: <TestCaseDefinition>
#> 10: <TestCaseDefinition>
#> 11: <TestCaseDefinition>
#> 12: <TestCaseDefinition>
#> 13: <TestCaseDefinition>
#> 14: <TestCaseDefinition>
#> 15: <TestCaseDefinition>
#> 16: <TestCaseDefinition>
#> 17: <TestCaseDefinition>
#> 18: <TestCaseDefinition>
#> 19: <TestCaseDefinition>
#> 20: <TestCaseDefinition>
#> 21: <TestCaseDefinition>
#> 22: <TestCaseDefinition>
#> 23: <TestCaseDefinition>
#> 24: <TestCaseDefinition>
#> 25: <TestCaseDefinition>
#> 26: <TestCaseDefinition>
#> 27: <TestCaseDefinition>
#> 28: <TestCaseDefinition>
#> 29: <TestCaseDefinition>
#>                test_case