Thursday, July 17, 2008

How Did You Get Started in Software Development?

After a post from little brother (well ten minutes younger, he is my twin) regarding his history in computers, I thought I would follow suit.

Like Rhys, my history started with trying to install games and getting them to either run, or run faster. My first computer exposure was an Amiga 500 at the age of 8 in primary school. We had a computer club with 4 members: A nerdy teacher, my mate, my mate’s older brother and me. We did nothing but learn to format floppy disks and play some flight simulator. We then got an Apple II gs at home which was used for basically printing out pretty thing we made in its word processor and dot matrix color printer. It always was running low on memory which at them time meant nothing to me as I thought all the memory was on the floppy disk. Then we upgraded to a PC. besides the CD drive I couldn't for the life of me figure out why this was an upgrade. Everything seemed worse than my 5+ year old Amiga. Then some gave us an illegal copy of doom and we never looked back to Amigas and apples (till recently). Yes we did end up getting a real copy of Doom by the way. Ironically stealing game software for a 13 year was a real introduction to IT. Zipping files across 8 disks, modifying AUTOEXEC.Bat and CONFIG.SYS files was the real first steps into IT. From there I took some Computer studies classes in High School. We learnt QBasic, HTML, Databases & Gate Logic. It was a really cool intro to programming (instead of word processing or IT admin).

University – Or lack of.

From high school I progressed to Uni. I started with CompSci, Physics and Calc. My grades were alright, but I really hated it. The material was kinda fun but didn’t feel like it was applicable to anything. So with some good advise I took up an Diploma in Business Programming. I know it sounds very dorky, but was leagues better than the crap I was being feed at Uni. Once I finished that full time year long course I had written an asp web site running off an Access database in my spare time. Looking back it is actually ok code. www.northsport.co.nz

Jobs – FTE to contractor

My first two jobs were post Y2K eCommerce companies. I was lucky to work with a range of talents which taught me my first lessons in corporate life. Conduit was an ASP + SQL Server 7 development shop. This is where I came to grips with (D)HTML, javascript, css, SQL Server, SPs, integration. I followed my mentor Jerome from my first job to my second at his company Neotek. Neotek was an amazing experience and cemented a wide range of skills I had started to pick up at Conduit. Neotek was an early adopter of .Net and had a fantastic product offering which constantly amazed clients with its speed (especially its pricing model).

My sporting career lead me to Perth. While there I continued to help Neotek with small stand alone projects and picked up a contract building ad hoc websites for Pretzel Logic, a local company. Pretzel was fun as most of the work was 12 week projects that I could dive into get, get done and move on to the next site. From there I moved to contracting for a Bank. This is where I am now. Working for the Bank has proved to be bitter-sweet. We were (very) early adopters of WPF, CAB & WCF which has been awesome to get dirty with new technologies. However big banks move slowly and are full of politics. Bugger.

So Rhys, there is my spiel.

Serialization != XmlSerializer

I have seen some interesting code in recent months around serialization. It appears that an old habit that any serialization would be done with the XmlSerializer, has turned into serialization has to be done with the XmlSerializer.

Now while XmlSerializer is great, it has some pitfalls. Notably for this post, it can’t serialize object graphs with recursive references. To illustrate better consider an Order object with a collection of OrderLine objects. Each of the OrderLine object has a property that referenced the Order it belonged to. Now in .Net this is no problem and can be kind-of handy to have Orders know about their OrderLines and then be able to get back to the Order from the OrderLine. However this is hard to describe in XML (at least in a standardized way) as XML is inherently hierarchical.

[Serializable]
public class Order
{
    private Collection<OrderLine> _lines = new Collection<OrderLine>();
    public int OrderNumber { get; set; }

    public Collection<OrderLine> Lines
    {
        get { return _lines; }
    }
}

[Serializable]
public class OrderLine
{
    public string ItemCode { get; set; }
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public string Description { get; set; }
    public Order Parent { get; set; }

    public OrderLine()
    {
    }

    public OrderLine(string itemCode, decimal unitPrice, int quantity, string description, Order parent)
    {
        this.ItemCode = itemCode;
        this.UnitPrice = unitPrice;
        this.Quantity = quantity;
        this.Description = description;
        this.Parent = parent;
    }
}

I also thought it would be interesting to consider the impact of best practices regarding properties that are collection types.  It is considered to be best practice in .NET code to only provide a getter on properties that are collections.  [see Framework Design Guidelines 8.3.2]

This however throws a wobbly when used as a DTO with WCF. Now my assumption here is that to be interoperable with other systems (thinking Java), a getter and a setter would need to be provided to allow serialization and then de-serialization over the wire.

From my observations, this constraint has somehow been perceived to apply to all serialization. I have seen setters being applied to objects where there is no need but for the misinformed notion that it is required for serialization. The thing that really surprises me is that it is so easy to verify your assumptions regarding these problems. So, lets play!

1st up:  Serializing Hierarchies (well really collections)

If we take a simplified version of the code above where the Parent property is removed so we just have an object with a collection property. This serializes fine. I also do not need to provide a setter for my collection property.

Order myOrder = new Order();
myOrder.OrderNumber = 1;
myOrder.Lines.Add(new OrderLine("ABC", 10, 1, "First Item"));
myOrder.Lines.Add(new OrderLine("ABCD", 4, 1, "Some content"));
myOrder.Lines.Add(new OrderLine("ABD", 10, 4, "This Item"));
myOrder.Lines.Add(new OrderLine("ACD", 166, 1, "Test"));
myOrder.Lines.Add(new OrderLine("BCDE", 24, 9, "Last Item"));

System.Xml.Serialization.XmlSerializer oXS = new System.Xml.Serialization.XmlSerializer(typeof(Order));
System.IO.StreamWriter ostrW = new System.IO.StreamWriter(@"C:\SavedOrder.xml");
oXS.Serialize(ostrW, myOrder);
ostrW.Close();

2nd Test: recursive graphs (adding the Parent property back in)

If we add the parent property back in and set it correctly we will get an InvalidOperationException when we try to serialize it. Now to me, this is not a time to throw our hands in the air and start coming up with wild work-arounds for how to serialize our object. My first question would be “Does this result of the serialization have to be human readable?” if the answer is no then Binary Serialization works a treat.

This little helper method will serialize any old thing to disk for you.

public static void SerializeToBinaryFile(Object entity, string path)
{
    Stream stream = new FileStream(path, System.IO.FileMode.Create);
    IFormatter formatter = new BinaryFormatter();
    formatter.Serialize(stream, entity);
    stream.Close();
}

Now its not exactly production quality code but it proves a point.

If the answer to the above question of readability was yes, then we may have to ask some other questions of our requirements. It is very likely that we are leaking our domain model into another layer. If serialization is required to saved to disk then the disk can be considered a repository and may require a less specific model. The same can be said it serialization is for communication between systems. Both these scenarios would have no requirement to have the recursive nature of our model described. Our implementation with the recursion can be implied from the raw data.

For a working example of this code download this C# file.

SerializationSpike.zip

Wednesday, June 25, 2008

Static vs Dynamic Resources

In WPF you can use either reference a resource statically or dynamically. Most documentation floating around was fairly vague on what each system gave except for there was a slight performance penalty of choosing to access a resource dynamically. One analogy is that Static is like compile time look up and Dynamic is like run time. Terrible analogy.

Using StaticResource will evaluate the resource once, the first time that access is made i.e. Not at compile time.

Provides a value for any XAML property attribute by looking up a reference to an already defined resource. Lookup behavior for that resource is analogous to load-time lookup, which will look for resources that were previously loaded from the markup of the current XAML page as well as other application sources, and will generate that resource value as the property value in the run-time objects.

A DynamicResource will be evaluated every time the resource is required.

Provides a value for any XAML property attribute by deferring that value to be a reference to a defined resource. Lookup behavior for that resource is analogous to run-time lookup.

So when would either be used? Considering performing a resource lookup dynamically carries a higher cost, you would prefer to use StaticResource. However what benefits does dynamic look up bring? Basically if you want to perform Skinning or any other type of system that could change the resource after it has been loaded then you should use Dynamic resolution. Now if that is just not the case for your WPF application then just stick with StaticResources. However I think that might be a wee bit short sighted.

As a guideline I believe that anything in the immediate context can be referenced statically. This basically includes any resources defined in the same XAML file that references them. If the resource is defined externally to the XAML file then Dynamically reference it.

   1:  <Window.Resources>
   2:    <local:EnumValueToDescriptionConverter x:Key="enumValueConverter"/>
   3:  </Window.Resources>
   4:  <ListView 
   5:       ItemsSource="{Binding Path=Users}"
   6:       ItemContainerStyleSelector="{DynamicResource myStyleSelector}" >
   7:    <ListView.View>
   8:      <GridView>
   9:        <GridViewColumn Header="Id" DisplayMemberBinding="{Binding Path=Id}" />
  10:        <GridViewColumn Header="UserName" DisplayMemberBinding="{Binding Path=UserName}" />
  11:        <GridViewColumn Header="Status" DisplayMemberBinding="{Binding Path=Status, Converter={StaticResource enumValueConverter}}" />
  12:      </GridView>
  13:    </ListView.View>
  14:  </ListView>

Here we define an Enum Converter on line 2 and reference it statically on line 11. The style reference in line 6 refers to a style external to the XAML file so I reference it dynamically.

Monday, June 23, 2008

Move to Apple hardware

Time for a new laptop was on me and I have been weighing up on which piece of hardware to get. Basically I was considering another Sony Vaio, a Dell, possibly an ASUS and a Mac.

I pretty much discounted Sony as I was not happy with my last purchase which was a Sony. It is hard to put my finger on it but the whole experience was not quite right. It was light, fairly quick had quite a nice screen, but it had quirks. Cut/copy paste never worked properly?!? It –always- took two pastes for anything to actually paste. Often using drag to move or copy something crashed explorer quite often. Start up and shut down was getting pretty slow. On the flip side, when all was running it was fine for developing in VS and SQL, and, general performance for building and running apps was good.

I used to have an ASUS and was always happy with it except for its weight and battery life. To be fair this was mainly because it was a desktop replacement. I did pick up the ASUS laptop for a very good price when I did get it but the brand does not appear to be as popular here in Australia.

Dell just bothers me that it is all online. I know I am in the IT space and even spent many years in the e-commerce space, but I want to touch it, look at it and evaluate it.

15inMacBookPro Which leads me to Apple. The big reason with considering the apple is the feedback I have had. A number of people (that I work with and just read their blogs) have made the shift. Assuming you are and MSDN subscriber, you basically get two platforms for free. You get the confidence of high quality hardware. You also get all those treats that just come with OSX (Gargeband!). The real choice I was left with was which mac to get; MacBook or MacBook Pro? In the end I decided I wanted the slightly higher spec hardware from the MacBook Pro but found it very difficult to justify the large jumps in price for the extras on the higher spec’ed machines ($700 to get0.1 Ghz cpu increase and 215Mb more VRam). I ended up getting the Basic MacBookPro with an upgrade to 4GB of ram. Initial tests on Vista Ultimate running on Bootcamp have a performance index of 5.0 which thumps my old Sony score of 3.4.

Thursday, June 12, 2008

CurrentCulture vs CurrentUICulture

I have been guilty of using the CurrentUICulture where I shouldn’t. I made the assumption that the CurrentUICulture would be the thing I want to use to do things on my UI like formating and displaying a date. *WRONG*!

After one of the guys at work asked me why his FxCop told him off for not passing a IFormatProvider into his string.Format(..) I told him to just pass in CultureInfo.CurrentUICulture. Well I was wrong. We are in Australia and it started formatting his dates as mm/dd/yyyy not dd/mm/yyyy. A quick Google showed me the error of my ways. Basically always just use CultureInfo.CurrentCulture. The CultureInfo.CurrentUICulture is actually used by ResourceManager to identify which resource dictionary to use to show text to the user. Now this is great for Globalization but not to be used for localization. Gee don’t they sound like the same thing….?

WPF updates on Database changes

When using WPF in a smart client environment it always seemed natural that with a local datastore I should be able to listen to data changed events from the database. I have bundled a couple of systems together in a spike* to show that it is possible. Note the style implemented here is only useful where the database has one user (ie a smartclient application).

*spike is my way of excusing awful code.

VisualClue

I have taken the databinding goodness from WPF that automatically updates thanks to INotifyPropertyChanged. I have thrown a little visual clue in to show the data that has been modified. The row that was updated glows yellow.

Next I use a dictionary of WeakReferences in my repository to only hand out pointers to “Customers” in the dictionary. As they are weak references its not a big overhead to store them.

Next I use the service broker technology available from SQL 2005 up. The great thing here is that it is available on SQL Express which is perfect for Smart Client applications. Basically I add a trigger to each table (only customer at the moment) and add all the modifications to a queue as XML data.

Last I have a class that listens to the database called  RepositoryNotification. It basically runs in the background thread and using the Service broker queue technology it waits for triggers to place XML on the queue and then returns it as data. This all works great. At the moment the code that translates the xml is just awful so my apologies up front.

WpfWithBoundRepositoryCache.zip

Note this quick spike currently only supports one row updates at a time (due to my crappy XML de-serialization) and doesn't support inserts or deletes. Inserts and deletes could possibly require some “business logic” to identify if the new row should be shown or the deleted row to be removed.

--Edit

Adam Machanic has a brilliant tutorial on Service broker for those interested. Most of my SQL code was ripped from these tutorials. I think it was supposed to be a 3 part series but I can only find part 1 and part 2.

Thursday, June 5, 2008

CAB Module Configuration

One of the issues we face when developing a composite application is where module specific configuration belongs. There seems to be three approaches to the problem.

  1. Put it all in the shell’s app.config. If this is the answer one may want to question why the application is a composite one.
  2. Have a build task that merges module config into the app.config
  3. Have each module just deal with its configuration in isolation.

Option three is my personal preference as I think this lowers the requirements on possibly already complicated build/deploy routines and gives a level of isolation I associate with a composite application. If we were on the web platform we could just create new application domains for sub domains or sub-directories. How can we give similar isolation for client applications?

The .Net framework give us the ability to get config setting very easily from the executing assembly’s config using good old System.Configuration.ConfigurationManager. (still annoys me that System.Configuration is a seperate assembly to reference).

However using the  ConfigurationManager in the default manner is of no use in the composite application world. We have to look to some of its other features to get what we need.  ConfigurationManager provides a (somewhat misleading) method named OpenMappedExeConfiguration.  It actually allows access to non executable assemblies ie a dll. In this example we use the standard of a “.config” suffix to an assembly name to identify the module config.

    ExeConfigurationFileMap map = new ExeConfigurationFileMap();
    map.ExeConfigFilename = this.GetType().Assembly.Location + ".config";
    if (File.Exists(map.ExeConfigFilename))
    {
        _configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
    }

Now our _configuration variable can be used in a similar fashion to ConfigurationManager. We have access to our old favorite properties AppSettings and ConnectionStrings. We also can get config sections by using the GetSection method.

Hope this little insight helps building your composite applications in a little bit more isolation.

*Thanks to Grae for the base code.