Avoiding Typos via Output Methods
One of the issues with the code generation templates is that they do not test the syntax of the output as you type. I’m a VB coder, and that would be my fantasy, an editor that told me whether my templates produced valid output as I type. That’s nearly impossible to do, so don’t hold your breath.
In the meantime, you may have code like the following where
Private Function MemberGetPrimaryKey2() As String
Return _
<code>
Protected Overrides Function GetPrimaryKey() as <%= ObjectData.PrimaryKey.NetType %>
Return m<%= ObjectData.PrimaryKeys(0).Name %>
End Function
</code>.Value
End Function
Any typos between the <code> elements will result in dozens or hundreds of compiler errors when the output code is incorporated in your project. This is a pain in the neck to deal with, so anything we can do to have less typos is desirable.
When you create a UI for your users, you limit the number of mistakes the user can make via techniques like combo boxes. We can take advantage of Visual Studio’s editor to do a similar thing.
Your output code has logic within subroutines, functions and properties. While this code is trivial in the example above – just a return statement – your code will generally involve more complex logic. It’s important that you see this logic to evaluate it as you’re maintaining templates. The actual function declaration however, is not logic.
I created methods to output the enclosing declarations, as well as other non-logic based structures. This transforms the code above into:
Private Function MemberGetPrimaryKey() As String
Return OutputFunction( _
"GetPrimaryKey", _
Scope.Protected, _
MemberModifiers.Overrides, _
ObjectData.PrimaryKey.NetType, _
Function() _
<code>
Return m<%= ObjectData.PrimaryKeys(0).Name %>
</code>.Value)
End Function
I’ve spread this out for clarity.
You can still typo the name of the method and the word Return. While you can make a bad selection, you cannot make a typo in anything else. And the parameters of the output function remind you of the types of modifiers that make sense. Under the covers, the OutputFunction creates a FunctionInfo object. While I’m not using it here, the OutputFunction method accepts a paramarray of ParmaeterInfo objects if you’re function needs parameters. Again, you can typo symbol names, but nothing else. Of course since the OutputFunction is within the code active in the IDE, you get full Intellisense, information blocks, background compilation and all the good stuff.
I’m using a lambda expression. In this case, it creates an in line delegate used to output the function body. If this template method becomes unduly complex, you could also use VB’s AddressOf operator to call a separate method as a delegate. In this case, the delegate signature I expect has no parameters and returns a string. Since the <code>…</code>.Value returns a string, it’s an effective delegate.
The FunctionInfo object includes an attribute collection. Thus, any attribute you desire to place on the function can be assigned by explicitly instantiating the function info object, rather than using the helper function.
This is quite similar to the OutputClass and OutputRegion methods I’ve showed earlier, but it takes the idea of using explicit method calls in the template to reduce the opportunity for typos in the output.
Output symbol typos are a problem, and you can avoid this through an enum or constants. You’ll use some of these constants across many templates and there will be a lot of them across your templates so I’d suggest you keep things clean by creating classes that contain your symbols. I created a namespace called “Symbols” and classes for Type, Method, Interface, etc. This gives nice clean Intellisense and makes it easier to find symbols in the constant list. Thus the code above becomes:
Private Function MemberGetPrimaryKey() As String
Return OutputFunction( _
Symbols.Method.GetPrimaryKey, _
Scope.Protected, _
MemberModifiers.Overrides, _
ObjectData.PrimaryKey.NetType, _
Function() _
<code>
Return m<%= ObjectData.PrimaryKeys(0).Name %>
</code>.Value)
End Function
That leaves “Return” as the only remaining opportunity for a typo – which is the subject of tomorrow’s post.