Back to TTCN-3 Refactoring Catalog

Parameterize Template

Several templates of the same type, which merely use few different field values, are replaced by a single parametrised template.

Motivation

Occasionally, there are several template declarations of the same type which are basically similar, but vary in values at the same fields (source template declarations). These template declarations are candidates for parametrization. Instead of keeping all of them, they are replaced with one single target template declaration where the variations are handled by template parameters. Such a change removes code duplication, improves reusability and increases flexibility. If the names of the source templates convey important information which would get lost by using a single template, their names may be kept by delegating them to the target template. If all template fields are completely the same, use the Remove Duplicate Template refactoring. If the template declarations are similar, but the values vary in differing fields, the Replace Template with Modified Template refactoring may be a better choice.

This refactoring is similar to Fowler's Add Parameter when reinterpreted for the use of templates. However, the mechanics of Parameterize Template have been improved while the mechanics of Remove Parameter do not need such a change.

Mechanics

  • First check that none of the source templates are referenced by another template using modifies and that all of the source templates are located in the same scope and group. Otherwise, the mechanics of this refactoring are not applicable. (Using modifies together with parameterization requires a different mechanics which we have not thought-out, yet. The same applies if source templates from different scopes and groups are replaced by a single target template: in this case scope visibility and imports (e.g. imports restricted to certain groups) need to be taken into account.))
  • Create the parametrised target template declaration within the same scope and group as the source templates by copying one source template declaration. Give the target template a name that reflects the meaning of the non-parametrised template values.
  • Introduce a formal parameter to the target template declaration for each field in which the source template values differ:
    • Add the formal parameter to the target template declaration signature. The type of the formal parameter can be obtained from the type of the respective template field.
    • Inside the target template body, replace the value of the varying template field with a reference to the added formal parameter.
  • Compile.
  • Now, decide whether you like to keep the source template names for delegation (because their names convey important information which would get lost when using only a single parameterized template) or whether you like to keep only the parameterized target template.
    • If like to remove the source templates completely and keep only the parameterized target template:
      • Repeat the following steps for all references to the source template declarations:
        • Replace the reference with a reference to the parameterized target template. As actual parameter values, use the field values from the originally referenced template declaration corresponding to the parameterized values in the target template.
        • Compile and validate.
      • Remove the source template declarations from the code. They should not be referenced anymore.
      • Compile and validate.
    • If like to keep the source templates and want just delegate to the parameterized target template:
      • Repeat the following steps for all source template declarations:
        • Replace the template body with a reference to the parameterized target template. As actual parameter values, use the values of the original template body fields corresponding to the parameterized fields in the target template.
        • Compile and validate.

Example

The following listing shows the unrefactored example. The source template declarations a_firstTemplate and a_secondTemplate differ only in the values of ipAddress.

type record ExampleType {
	boolean ipv6,
	charstring ipAddress
}

template ExampleType a_firstTemplate := { 
	ipv6		:= false,
	ipAddress	:= "127.0.0.1"
} 

template ExampleType a_secondTemplate := { 
	ipv6		:= false,
	ipAddress	:= "134.72.13.2"
} 

testcase tc_exampleTestCase() runs on ExampleComponent {
	pt.send( a_firstTemplate );
	pt.send( a_secondTemplate );
}

The resulting code after applying Parameterize Template using the variant to remove all source templates completely is shown below. A new target template declaration a_parameterizedTemplate is created which has a parameter for the varying ipAddress field in the source template declarations. The references to a_firstTemplate and a_secondTemplate are replaced with a_parameterizedTemplate and their corresponding ipAddress values as parameters.

type record ExampleType {
	boolean ipv6,
	charstring ipAddress
}

template ExampleType a_parameterizedTemplate( charstring p_ipAddress ) := { 
	ipv6		:= false,
	ipAddress	:= p_ipAddress
} 

testcase tc_exampleTestCase() runs on ExampleComponent {
	pt.send( a_parameterizedTemplate( "127.0.0.1" ) ); 
	pt.send( a_parameterizedTemplate( "134.72.13.2" ) ); 
}

The resulting code after applying Parameterize Template using the variant of keeping all source templates and delegating to the new parameterized target template is shown below. A new target template declaration a_parameterizedTemplate is created which has a parameter for the varying ipAddress field in the source template declarations. The bodies of a_firstTemplate and a_secondTemplate are replaced with referefences to a_parameterizedTemplate and their corresponding ipAddress values as parameters.

type record ExampleType {
	boolean ipv6,
	charstring ipAddress
}

template ExampleType a_parameterizedTemplate( charstring p_ipAddress ) := { 
	ipv6		:= false,
	ipAddress	:= p_ipAddress
} 

template ExampleType a_firstTemplate := a_parameterizedTemplate( "127.0.0.1" )

template ExampleType a_secondTemplate := a_parameterizedTemplate( "134.72.13.2" )

testcase tc_exampleTestCase() runs on ExampleComponent {
	pt.send( a_firstTemplate );
	pt.send( a_secondTemplate ); 
}

Back to TTCN-3 Refactoring Catalog