developer power tools
TRANSCRIPT
Power Tools for the Modern ProgrammerRegular Expressions, Reflection, Code Generation
Introduction • Leverage advanced practices to build
adaptive business solutions• Boost your own productivity by reducing
repetitive tedious code• Improve quality and consistency by
reducing repetitive error prone code
What We Will Cover
• Power Tools
• Sample Application
• Further Ideas
• Sources for More Information
Power Tools
• Regular expressions Take string manipulation to the next level
• Reflection Interrogate and manipulate code metadata at run time
• Code generation Make the computer write its own code
• Design patterns Leverage best practices in your designs
Overview - Reflection
• Create adaptive solutions
• Simplify code complexity
• Ease maintenance
• Ease deployment
• Solve configuration management issues
Overview Regular Expressions
• Regular expressions are to string as math is to numbers
• Simplify and optimize string manipulation
• Use editing tools to simplify creating regular expressions
• Document! Document! Document!
Overview Code Generation
• Obtain language independence with the CodeDom
• Use meta data to drive the code generation • Use meta data to provide code documentation• Standardize repetitive tasks with consistent
implementation
Overview Patterns
• Leverage emerging best practices
• Leverage existing documentation
• Don’t go over board
The KISS Principle still applies
Sample Problem
• Parse fixed length record file
• Parse with multiple purposes at different times (Load in a database, display on a document, display in a web page, etc)
• Need to parse multiple file with different formats
Sample Format
• Customer order tracking file
• Customer Record
• Order Record
• Order Item Record
• Address Record
Customer
• CST Record Identifer
• 23 Characters Customer ID
• 25 Characters First Name
• 25 Characters Last Name
• 3 Characters Age
Order Record
• ODR Record Identifier
• 8 Characters Order Date
• 8 Characters Required Date
• 8 Characters Shipped Date
Order Item Record
• ITM Record Identifier
• 25 Characters Product ID
• 5 Characters Quantity
• 5 Characters Unit Price
• 4 Characters Discount
Address Record
• ADR Record Identifier• 60 Characters Street Address• 75 Characters City• 2 Characters State• 5 Characters Zip Code• 4 Characters Zip Plus 4
Very Easy Regular Expression
“CST(?<CustomerID>.{23}(?<FirstName>.{25})(?<LastName>.{25})(?<Age>.{3})”
Regular Expression Notes
• Verify that the input string starts as expected
• Allow any character for the specified number of times
• Use named explicit capture groups
Defining Record Objects
• Define a Constructor expecting a string to parse
• Define read only strongly typed property for each element in the record
Building the Record Object
• Metadata storage
• Generation Process
• Provide documentation
Metadata
Document
PK DocumentID
DocumentName
Record
PK RecordID
FK1 DocumentIDRecordNameRecordPrefixComment
RecordElement
PK RecordElementID
FK1 RecordIDRecordElementNameDataTypeCharacterLengthSequenceComment
Generation Process
• CodeNamespace• CodeTypeDeclaration• CodeConstructor• CodeMemberProperty• CodeMemberMethod• CodeVariableDeclaration• CodeAssignmentStatement
Documentation Process
• Simple reports
• Documentation is accurate because it drives program execution
Reflection to Reduce Complexity
• One measure of complexity is the number of paths through the code
• Multiple paths may lead to redundant code• Multiple paths may lead to confusing flow control• Multiple paths may lead to higher maintenance
requirements
Identifying Record Objects (Hard Coded)
• Separate case statement for each record type• Brittle dependency on the file format• More complex formats lead to more complex
parsing• Parsing a different format requires a different
parser
private void HardCodedParseLine (string inputLine){
string prefix = inputLine.Substring (0,3);object parsedObject = null;switch (prefix){ case "CST": {
parsedObject = new Customer (inputLine);break;
} case "ODR": {
parsedObject = new Order (inputLine);break;
} . . .}DisplayObjectDetails (parsedObject, tvwResults);
}
Identifying Record Objects (Reflective)
• Single path through the code
• Code complexity stays constant even as file format complexity increases
• Same parser can handle parsing files with different formats
private void ReflectiveParseLine (string inputLine){
string prefix = inputLine.Substring (0,3);Type parseType = (Type)mTypes[prefix];Object [] parameters = {inputLine};if (parseType != null){
object parseObject = Activator.CreateInstance (parseType, parameters);Common.Helpers.DisplayObjectDetails
(parseObject, tvwResults);}
}
Visitor Pattern
• Create enhanced flexibility with events• Define an event that will be raised when a record
object is identified• Calling objects “visit” each discovered object by
subscribing to the event• Separation of responsibilities
– Parser knows how to identify record objects but not what to do with them
– Visitors know what to do with the record objects but not how to find them
Further Ideas
• Load the Record Object types through reflection or from a config file instead of hard coding them into hash table
• Use reflection to identify the method to be called from the event handler specific to each record object type
• Generate and compile the record objects at run time for the ultimate in flexibility
Sources for More Information
• Reflection– http://www.oreillynet.com/pub/au/1073
• Regular Expressions– http://www.ultrapico.com/Expresso.htm– http://weblogs.asp.net/rosherove/articles/6863.aspx
• Code Generation– http://www.ondotnet.com/pub/a/dotnet/2003/02/03/codedom
.html