Monday, November 10, 2008

More Xml Design Patterns

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/more_xml_design_patterns.htm]

 

Last month I mentioned some tips for structuring xml, which could be seen as the start of primitive Xml Design Patterns. Here are three more ideas.

 

Strongly-typed nodes

 

Say you have a node, which can have several different groups of attributes. For example, you're making a test automation DSL, and you need to assert that various conditions are met. You may have a basic assert, a correct-page assert, and a text-search assert:

The schema for this becomes messy - you'll have one node (Assert) with all possible attributes. Your interpreter will need to infer which action to take based on the current attributes. Validating the xml file also becomes error-prone. It's doable, but messy. Compare that to this:

.Page pageName="myPage.aspx" />

.Text textToFind="EmpId123" isRegex="false" isCaseSensitive="false" />

This approach has essentially three nodes: Assert, Assert.Page, and Assert.Text. This effectively gives you "strongly-typed nodes". Your interpreter instantly knows which type of node, and therefore what action it expects and how to validate its attributes. Your schema becomes simpler because each node type has only the relevant attributes. This isn't always the best approach, but it can be a good one in certain cases.

 

 

Serializing complex objects to attribute strings

 

You can serialize almost any object to Xml, but the question is what is the best way to do it? For example, you could serialize an array as a bunch of nodes:

   

        12

        35.5

        40

        9

   

However, this is somewhat bloated. A more concise way is to serialize it to a string, and then store the results in an attribute:

You could serialize an array as a CSV list: "1,2,3".

You could serialize a name-value pair: "name1=value1;name2=value2" (this is what MSBuild does)

You could even have a mini DSL, like the Silverlight path expressions: "M 10,100 C 10,300 300,-200 300,100".

 

The main thing this approach requires is an easy way to serialize and deserialize the object to a string. If you've got that, then this technique becomes very reasonable.

 

 

Abstract complex objects to inner content

 

Silverlight uses Xaml markup to describe the UI. Xaml allows a lot of style markup.

 

You can create a simple ellipse, shading the entire thing a solid blue.

Fill="Blue" />

However, you can also give it a more advanced two-color gradient shade by abstracting the "Fill" markup to the inner nodes of the ellipse. Specifying a single attribute is great when you can serialize all the necessary info to a single string, else you can leverage the more-powerful inner xml nodes (per a Jesse Liberty tutorial).


   
     
        
        
     

  

This allows the best of both worlds - the single-line common case, and the more advanced case.

Thursday, October 30, 2008

LCNUG: Gorking the ASP.NET MVC Framework

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/lcnug_gorking_the_aspnet_mvc_framework.htm]

Yesterday, Derik Whittaker presented at the LCNUG about the MVC pattern. I had a last-minute family emergency come up, so I couldn't make it, but it looked good.

This is the fifth presentation at the LCNUG, almost half a year. It's been great to see the new group up and running.

Sunday, October 12, 2008

Real life: the leaking window

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/real_life_the_leaking_window.htm]

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 Design Patterns

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/xml_design_patterns.htm]

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 filea 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

    node with a bunch of child nodes). You could also use the natural order of the xml nodes to determine the natural sequence that the data appears (like the order of the pages).

  • 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

Having Console apps write out Xml so you can parse their output

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/having_console_apps_write_out_xml_so_you_can_parse_their_out.htm]

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:


       revision="3004">
    username1
    2008-09-26 10:47:19 -0500
    
      Solved world hunger
    

  
       revision="3000 ">
    username1
    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.

Monday, September 29, 2008

Death by a thousand cuts

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/death_by_a_thousand_cuts.htm]

A single paper cut won't kill you, but a thousand of them probably will. That's what people mean by "death by a thousand cuts". This is how many software projects die - it's usually a hundred little things that pile up, and whose combined pain becomes unbearable. It's the runaway bug list, the brittle test script that gets abandoned because it's too hard to maintain, the endless tedious validation on a details page, the component with the fuzzy interface, the buggy deployment, all the little features that just don't work right, etc...

 

This is why continuous integration, unit tests, automation, proactive team communication, code generation, good architecture, etc... are so important. These are the techniques and tools to prevent all those little cuts. I think that many of the current hot methodologies and tools are designed to add value not by doing the impossible, but by making the routine common tasks "just work", so that they no longer cause developers pain or stress.

 

Sure, you can write a single list-detail page, any developer can "get it done". But what about writing 100 of them, and then continually changing them with client demands, and doing it in half the scheduled time? Sure, you can technically write a web real-time strategy game in JavaScript, but it's infinitely easier to write it with Silverlight. Sure, you can manually regression test the entire app, but it's so much quicker to have sufficient unit tests to first check all the error-prone backend logic.

 

The whole argument shifts from "is it possible" to "is it practical?" Then, hopefully your project won't suffer death from a thousand cuts.

Sunday, September 28, 2008

Real life: How do you test a sump pump?

[This was originally posted at http://timstall.dotnetdevelopersjournal.com/real_life_how_do_you_test_a_sump_pump.htm]

Back when we moved into our home (a while ago), this was our sump pump.

As home-owners knows, sump pumps are very important because without one, your basement gets flooded. That causes at least tens of thousands of dollars of damage, as well as potential loss of any personal items in your basement - for example all your electronic equipment or books could get ruined due to water damage.

 

In other words, it's a big deal, i.e. an important "feature" of your house. So the natural question as a new home-owner is "how do I ensure that this mission-critical feature actually works?" Obviously I didn't want to wait for a real thunderstorm and power outage to find out if everything would be ok. While I had heard the buzzwords ("make sure your sump pump works and you have a battery backup in case of a power outage"), and I had been on previous "teams" (i.e. my parent's house, growing up as a kid) that had successfully solved this problem, when push came to shove, I was certainly no expert. For all I knew, this could be the best sump pump in the world, or a worthless piece of junk. However, I knew the previous owners of the house, they were great, so I assumed that the sump pump was great too, and everything would be okay.

 

Eventually, I figured out how to test it by contacting some "domain experts" (previous house owners), who explained the different components to me. I then "mocked out" a power outage by simply unplugging the power plug (as opposed to waiting for a real power outage, or even turning off my house power). I then lifted the float to simulate water rising, and listened for a running motor. I checked a couple other things, and became confident that the feature did indeed "work as designed". I was told that is was actually a very good setup because it had a separate batter charger, and two separate pipes out, so they were completely parallel systems (kudos to the previous owners).

 

The number of analogies between me needing to test my sump pump, and a user needing to test a critical feature of a software project, are staggering. It's a reminder to me how real life experiences help one understand software engineering.