This is the fifth presentation at the LCNUG, almost half a year. It's been great to see the new group up and running.
Thursday, October 30, 2008
Sunday, October 12, 2008
House repairs provide a lot of good software analogies. Once during a big rain storm, our window started leaking. It was a newly installed window, and it had never leaked before. Well, obviously a leaky window can become a huge problem if left unfixed. So, I went out sometime later, sprayed the window with the hose to try to get an idea of where the leak is (I was not, and still am not, a house repair expert), and to my great frustration - the window did not leak. Of course I wanted to reproduce the problem, narrow it down to the exact cause, and then make a quick fix - just like I would in a software project. I didn't want to rebuild the whole thing.
So, here is a "critical feature bug" (the leaky window), which occurred in "production" (during the actual rainstorm), but I cannot reproduce in my "development environment" (sunny day with my spraying the window with a hose). It was a non-reproducible bug. However, I couldn't just ignore it or look the other way, I needed to ensure that it didn't happen again (given that it's my house, I need to take "ownership" of the "project"). It's the kind of thing that drives a software project mad.
In this case, I just 'blindly" resealed things - checked the siding, exterior frame, interior, etc... And the window never leaked since. If it does end up leaking again, then I'll probably need to call an expert, much like how some doomed software projects sometimes call in a star consultant to troubleshoot their obscure bugs.
Thursday, October 9, 2008
Xml is the defacto way to store data in files - whether it's build instructions as an MSBuild script, a Domain Specific Language based on code-generating from an xml file, a config file, or something else.
So, your xml files are storing lots of mission-critical information. They're getting huge, being modified by tons of developers, and getting hard to maintain. It's time to refactor them. Here are several ideas to refactor your xml files (much of this is demonstrated in MSBuild):
Create a variables section. For example, MSBuild has a
section, where each inner node can define a new variable. You can then reference those variables elsewhere throughout your script like so: $(myVar).
Allow importing of files. Often you'll want to either split a big file into smaller ones, or reuse a single file many times (for example, put all your global variables into a separate file, and then re-import it everywhere).
Related to this, allow chunks of xml to be automatically included in other chunks with some sort of "include" syntax. In other words, ensure that the xml file itself is refactored. MSBuild allows you to call other targets with a
task. Or, say you have a test script that's generated from xml, and every test needs to repeat your "login routine". Define the login routine in one xml snippet, and allow it to be re-included in all the other snippets.
Have the xml structured to automatically determine relationships. For example, if you have a parent-child relationship of data (here is the menu, here are all the pages accessible from that one menu), then consider using Xml's natural hierarchy (a
Provide some way of an extension method or hook. In MSBuild, you can define your own custom tasks and dynamically load them.
Create special syntax for domain-specific concepts. For example, the MassDataHandler takes xml snippets, and converts them to SQL insert statements to assist with database unit testing. A common problem for inserting SQL statements is handling the identity columns. In this case, if you prefix the value with an '@', the MassDataHandler automatically knows to go lookup its identity value.
Create templates for default values, which other xml nodes can override. For example, the MassDataHandler allows you to run SQL inserts, one xml node per database row. But say five rows all have the same values for something (like they're all children of the same parent), then it provides the ability to have a "default row" which defines the default values. Other xml nodes can then override these default values.
I guess you could say there are design patterns for good xml. As Xml becomes more and more prevalent, I expect that "Xml Design Patterns" to become more prevalent too.
Wednesday, October 8, 2008
Say you have an automatic process calling some executable, and you want to get information back from that executable to use in your own code. Ideally you'd be able to call a class library that you could just reference, but what if no such class library is available (it's a different development platform like Java vs. C#, or it's a black box third-party component). Is there any way to salvage the situation?
Some developers would stream out the console output to a string, and then write a bunch of ugly parse code (even with regular expressions), and get their results that way. For example, let's say you use Subversion for your source control, and you want to search the history log. For the sake of argument, assume there's no friendly C# API or web service call (it's a local desktop app you're calling), and you need to parse command output. (If anyone knows of such an API, please feel free to suggest it in the comments.) You can run a command like "svn log C:\Projects\MyProject", and it will give you back console output like so:
r3004 | username1 | 2008-09-26 10:47:19 -0500 (Fri, 26 Sep 2008) | 2 lines
Solved world hunger
r3000 | username1 | 2008-09-06 14:10:56 -0500 (Sat, 06 Sep 2008) | 2 lines
Invented nuclear fusion
Ok, you can parse all the information there, but it's very error prone. A much better way is if the console app provides an option to write out its output as a single XML string. For example, you can specify the "--xml" parameter in SVN to do just that:
2008-09-26 10:47:19 -0500
Solved world hunger
2008-09-06 14:10:56 -0500
Invented nuclear fusion
Obviously, that's much easier for a calling app to parse. If you need to bridge a cross-platform divide such that you can't just provide the backend class libraries, outputting to xml can be an easy fix.