Generally speaking, you will want to automate the generation of the Traceable Layer code as much as possible. This greatly reduces maintenance, and helps to ensure that the Traceable Layer matches the Functional Layer. Note that code generation is not the primary purpose of this paper; and thus an in depth discussion of it is beyond the scope of this paper. However I am touching upon it here so that people are aware of it, and that I strongly encourage its use as part of Traceability.
Manually Generated Code
Some parts of the code should be manually generated. These sections are the parts that never change, or need very specific behavior. The aspects I have found that should be manually generated are:
- Special Case Code
Factories, once written, very rarely change, and thus do not necessarily need the overhead of automating their creation.
Constructors also rarely change, and thus writing them manually is not an issue.
Special Case Code may exists such that there are additional requirements that prevent automated code from properly generating the Traceable Layer wrapper function. In this case, you will need to write the code manually.
Automated Code Generation
Automating the code generation is a significant time saver when working on classes that are continually changing. Without automation, then it becomes very easy to not update the Traceable Layer. For C#, you should look into Text Template Transformation Toolkit (T4).
One question that should be decided early on is if each Traceable Layer class should have a separate text file to generate it. While it is very possible to iterate over an entire project, and simply generate a corresponding Traceable class for every Functional class, I have found that some code required a more fine grained approach, thus I chose to create use a separate file for each class.
Another question is how often the automation code should be run? It is possible to have it run every time you build the solution, though this may require you to download additional SDKs. You may also opt to have it only run when needed. See Verification below for more details.
Reflection allows you set up code that iterates over the properties and functions of a Functional Layer class, and then automatically generate the override wrappers for the corresponding Traceable Layer class.
The reflection code should also allow skip lists such that specific properties and functions will not be automatically generated. Some examples include ToString(), GetHash(), or Special Case Code.
The skip list mechanism should should have a macro level exception list, as well as allow each individual Traceable class to specify elements it wants to skip. This way, you can automatically skip all overrides of ToString(), but also skip specific functions in one class, and not affect another class.
This is similar to a the Skip List, but instead of not producing any Traceable code, it would cause the output to be masked in some manner. For example, with customer data, you most likely do not want the social security number in the output. With a masked data list, you would have the offending property or function generate code such that the data was replaced with all "X"s or other character.
I have found that it is a best practice to write unit tests that compare each Functional Layer class with the corresponding Traceable Layer class. What the unit test checks for is that every property and function in the Functional class has a corresponding element in the Traceable class.
If you are regenerating the Traceable each time the solution is built, these unit tests provide a nice verification that the build worked correctly. If you are regenerating the Traceable classes manually, then these unit tests will provide a nice reminder to regenerate specific files of the Traceable Layer anytime the API of a Functional class is changed.
Next: Code Analysis