Sunday, 24 May 2009

Tech Day #5 – My First Look at WPF

So, I wanted to do something a bit fresher and possibly more interesting for TD#5. I have been cramming a lot for my next MS exam of late, so wanted to just have some fun and not really think about anything :)

I therefore scanned my Tech ToDo list and and through I would go for WPF. Silverlight is quite high on my list, so I thought it would be good to get a high-level look at WPF in general (since I have not yet worked with XAML).

So, let’s rock and roll!

Getting Started/Initial Setup

Of course I already have VS 2008, but if not, go and download the VS2008 Express Edition in your language of choice (VB or C#).

I also use O’Reilly Safari, so I had a look on there for any WPF books. I came across Pro WPF in C# 2008 (Matthew MacDonald), so I added that to my library and began reading while nomming down on my breakfast.

As always, there is some sample code for the tech day, not much for this one that is really functional since I am really playing with some basic ideas.

Let’s crack on and see what I learned!

Default Files

Once I had created the WPF application I thought I would take a look at what the project template had churned out for us. These really look very similar to a basic WinForms application. You get an “App.xaml” which is the same idea as “Program.cs” (essentially the bootstrap for the application). This will be the entry point for the application which will spin up the code that we implement.

Obviously there are some different references in our project. Remember that WPF is a completely different rendering engine to WinForms. While you will see that some of the concepts are similar (Brushes and the like) it is actually a completely different code set and hierarchy. Similar to WebForms vs. MVC – we still have the power of the .NET Framework itself, just a different way or processing things high up in the UI tier.

Layout

In Pro WPF in C#' 2008 (from now on “the book”) it was very clear from the outset that the layout model is very different to what we are used to in the WinForms world. Layout in WPF is designed to be flexible and flowing. This means (for the most part) “bye bye Top and Left”. Rather than defaulting to a fixed size/co-ordinate system WPF works around we use a more web-like document flow where we specify sizes and margins and let the rendering engine sort it out.

XAML Markup

I thought I would be worried once I sat down with the XAML since I thought “great, another language to learn”. Thankfully, I was incorrect in this assumption. Those of us that have worked/work with ASP.NET should be pretty comfortable with XAML since we are used to the way markup is parsed and used to spin up actual objects that do things. Those from WinForms may find it a little alien at first, but you should get the hang of it pretty quick. Just think “new” when you see “<”. For example:

   1: <someTag value="this is some txt" />

Could equate to the following C#:

   1: var st = new someTag()
   2:  { Value = "this is some text."; }

Once you get your head around the fact that markup can actually do stuff (as opposed to pretty dumb HTML) it' becomes pretty straight forward.

Attached Properties

I also found that a fair few of the controls follow the Attached Properties model. Normally, in order to make controls work together you may need to start messing with code at both ends as well as alter the way in which the controls are initialised.

For example, lets say we had a control that adds sprinkles to other controls, we may need to controls to it to get the sprinkles added to it:

   1: <Sprinkler Name="mySprinkles" Type="HundredsThousands">
   2:  <myDonut Name="nomnom" Type="Ring" />
   3: </Sprinkler>

While this may look fine, what if we were producing a page that had 1000 donuts that all needed sprinkles? We would suddenly need to start creating lots of spinklers which could be expensive. Not to mention the fact that we may actually want to put the donuts in a DonutBox!

Now, lets think about this, of course the sprinkler needs to know about the donut(s) we want to sprinkle, but do we need to “put the donuts in the sprinkler” (logically rather than physically)?

Consider the following:

   1: <Sprinkler Name="mySprinkles" Type="HundredsThousands" />
   2:  
   3: <myDonut Name="nomnom" Type="Ring" Sprinkler="mySprinkles" />
   4: <myDonut Name="homer" Type="Ring" Sprinkler="mySprinkles" />
   5: <myDonut Name="omgiatethebag" Type="Filled" Filling="Jam" Sprinkler="mySprinkles" />

See the difference? We just added a “Sprinkler” property to the donut classes that takes a Sprinkler, right?

Wrong!

The properties are actually added to the donut controls by the Sprinkler. This is very similar to the Extender Provider model employed in WinForms (e.g. the ToolTip Component). This enables us to create controls that extend other classes/controls in a non-obtrusive and clean way. Attached Properties are an improvement over Extender Providers since the methods called are static you don’t need to actually have an instance of the class floating around.

What’s really cool is that you would then think that the Sprinkler is somehow maintaining a list of the donuts it is sprinkling, right? Possibly, but it doesn’t need to because the donuts themselves actually store the property value. This is because all controls derive from DependencyObject.

User Controls

I was really pleased to see that User Controls are just as quick and easy to create in WPF. These are much the same as Win/WebForms User Controls with the obvious difference being that the designer works with XAML.

One thing I would note is that since the layout of WPF applications is a bit more dynamic and free-flowing, I would suggest testing your controls thoroughly in a number of different host forms to ensure everything looks good when resizing etc.

Animations

Even though I have not really produced much in the way of an “application” at this point (as in something that performs a function/fulfils a purpose) I didn’t really feel like WPF would be that much more of a mystery to me. I am more than capable of Google’ing for specific details on certain controls etc. I therefore thought I would spend a bit of time playing with some of the cooler things that WPF has to offer. Animation is obviously a big part of this.

When I first started looking at animation, I did get a bit confused I think this may be because a few of the articles I came across were really not very good at breaking things down. I will do my best to explain the animation to you in a way that means you don’t have to go back to Google like I did :)

The Storyboard

Imagine you are creating a reel of film. You have a ton of smaller film strips spliced up and you want to tape them all together in one kick-ass movie. Think of the Storyboard as the thing you are taping them to.

The Storyboard orchestrates a sequence of animations for you. Animation sequences are added to a Storyboard and then you (as the director of course) shout “Action!” and the sequence starts rolling.

So, before we do anything, we must create a Storyboard:

   1: var storyboard = new Storyboard();

Now we take a break and grab a coffee after all that code.

Animate What?

Let’s say for sake of argument our animation of choice is the good old “fade out”. Traditionally in WinForms we would probably add a Timer to the form and then tell it to reduce a Controls opacity on each Tick, but surely there is a cleaner, smarter approach with WPF?

Indeed there is. Opacity is a property of the “double” type. So what we really need is something to wrap up the Timer and reduction of a double value over time. Enter the DoubleAnimation. This is exactly what he doctor ordered and exactly how animation is done in WPF. We manipulate the properties of controls over time to animate it.

For example:

   1: var animation = new DoubleAnimation()
   2: {
   3:     From = 1.0,
   4:     To = 0,
   5:     Duration = new TimeSpan(0, 0, 1)
   6: };

Creates a animation that can be used to alter a double value from 1.0 to 0.0 over one second.

Sounds Great – I Can Still See the Control Though?

Of course, we have not actually bound it to a property of a control yet! All we created was the logic of the “fade” (reduction in opacity over time).

   1: Storyboard.SetTargetName(animation, myCtl.Name);
   2: Storyboard.SetTargetProperty(animation, new PropertyPath(OpacityProperty));
   3: storyboard.Children.Add(animation);

We have a few things to note here:

  • There are two calls to static Storyboard methods.
  • There is then a single call to an instance method.
  • We have introduced something called a PropertyPath.

The PropertyPath is basically a roadmap to a property value. What we are doing in the code is pretty simple:

  1. Setting the high-level target for the animation to the Control by using it’s Name property.
  2. Setting the actual property for manipulation by creating a PropertyPath.
  3. Adding the animation to our main storyboard instance.

MAKE IT SO!

Right, we have now actually create all that is required to fade out a control. All we need to do is fire off the process with this (rather large) code snippet:

   1: storyboard.Begin();

The storyboard will then do it’s job and execute the animations it contains.

One thing I really like about the above code (not sure if you noticed) is that there are no direct references required. Animations are very generic so we could easily wrap up the “FadeOut” code into something like:

   1: public static void FadeOutControl(FrameworkElement control)
   2: {
   3:     // Fades Out a Control Over 1s.
   4:     var storyboard = new Storyboard();   
   5:     var animation = new DoubleAnimation()
   6:     {
   7:         From = 1.0,
   8:         To = 0.0,
   9:         Duration = new TimeSpan(0, 0, 1)
  10:     };
  11:     
  12:     Storyboard.SetTargetName(animation, control.Name);
  13:     Storyboard.SetTargetProperty(animation, new PropertyPath(OpacityProperty));
  14:     storyboard.Children.Add(animation);
  15:     storyboard.Begin();
  16: }

We can then simply fade out control using:

   1: FadeOutControl(myBtn);
   2: FadeOutControl(somePanel);
   3: // etc...

Excellent!

Animations and Multithreading

After completing the above I thought I would see what it would be like to have a control fade out and then actually be removed (so controls reflow and reposition to fill its space).

This then ran me in to a problem which I think is important so I will quickly cover it here:

Animations run in a separate thread to the main application.

And rightly so, if they did not, your UI would freeze up while a control fades out. Sexy UI’s are great provided they do not come at a productivity cost. Fade outs are cool but would quickly piss me off if I lost minutes every day waiting for a control to fade out slowly.

In wanting to complete my goal I added code like:

   1: FadeOutControl(myCtl);
   2: myPanel.Children.Remove(myCtl);

Which seems fine at a quick glance, but now think about the animation running in a separate thread. When this is executed, the animation will begin, but the main thread of execution will continue, removing the control from the Window. So, the nice animation will start but then the control quickly disappears.

This can be solved by hooking up to the Storyboard.Completed event like so:

   1: storyboard.Completed += 
   2:  new EventHandler(storyboard_Completed);

You can then remove the control from the Window in the event handler:

   1: void storyboard_Completed(object sender, EventArgs e)
   2: {
   3:   FadeToGonePanel.Children.Remove(myCtl);
   4: }

Jobs-a-goodun!

In Summation

I had a lot of fun with this tech day, was nice to be working with something fresh while being rebellious and doing something that is to do with my next exam :) I personally have the feeling that the WPF team took a lot of lessons learned from WinForms and then brought some great stuff to the table to bring about a real nice platform to work on.

My only (at time of writing!) peeve is with the designer, why-oh-why is there no Events list in the properties Window?! If I just want to browse the Events I need to either go to MSDN or scan through a massive Intellisense list! Silly!

I hope those of you getting started with WPF in your own Tech Days/study got something of use out of this post!

Oh, I almost forgot. You may be thinking “not a lot of code for a whole day, Rob” – you would be correct.. I actually started playing with a new WPF-based project – more may follow soon :)

Links:

Tuesday, 5 May 2009

Tech Day #4 – SQL (For Developers)

Looking at current trends in the market, with companies wanting to downsize and squeeze all they can from their staff – it has becoming increasingly more obvious that most developers are doing a LOT more database work.

This has been my “Achilles heel” for quite some time, however it has never really been an issue since there has always been people at work that I can call upon to give us a hand. However, I am not a fan of leaving weaknesses unchecked, so here I am and here is SQL on my Tech ToDo..

Why the “For Developers”?

I think my biggest problem (and I am sure I am not alone here) with SQL is that I am a developer first. I often struggle with SQL because I think in a more procedural fashion, whereas SQL is set-based. This is a real mental shift in how you approach problems.

Before we get cracking, this post is NOT geared towards complete SQL n00bs. You should be comfortable with the basics.. SELECT, INSERT, UPDATES, DELETES and JOINS etc.

Getting Started

Go ahead and grab the sample code from my codepit. In there you will find a SQL service database file called “Data.mdf”. CREATE A COPY OF THAT AND THE “DATA.LDF” FILE. You can then mess with the data to your hearts content :)

In order to access the data, you will also need to attach the database to a SQL server service instance. So if you don’t have SQL server installed, grab the Express Edition (it’s free).

You may find it easier to work in MSEE, so you may want to sit in that rather than Visual Studio.

In the database, you will find a few tables with some random data in (thank you random name generator for the help!). These tables will be used throughout the post, data loss is likely to occur, hence the reason for the backup :)

Procedural vs. Set-Based

The Scenario

We have had some changes to the staff table. We have some new staff members as well as a couple of promotions. We need to update the staff table with the new information.

The Procedural Way

The C# developer in me thinks along the lines of this (ProceduralThinking.cs):

   1: // Get the New/Amended Records
   2: var records = GetNewAndAmendedRecords();
   3:  
   4: foreach (var record in records)
   5: {
   6:     if (record.Exists)
   7:         UpdateRecord(record);
   8:     else
   9:         InsertRecord(record);
  10: }

Where the “UpdateRecord” method would perform an UPDATE query, and the “InsertRecord” an INSERT INTO. This could equate to [roughly] the following SQL (ProceduralThinking.sql):

   1: -- Create a Table with New/Updated Records
   2: DECLARE @records TABLE (
   3:  ID int,
   4:  FirstName varchar(50),
   5:  LastName varchar(100),
   6:  Salary int,
   7:  Role int
   8: )
   9:  
  10: INSERT INTO @records VALUES (0, 'Rob', 'Cooper', 1000000, 5); -- Yeah, Right.
  11: INSERT INTO @records VALUES (0, 'John', 'Guido', 30000, 2);
  12: INSERT INTO @records VALUES (2, 'Rachel', 'Jackson', 14750, 1);
  13: INSERT INTO @records VALUES (9, 'Jon', 'Caton', 32000, 4);
  14:  
  15: -- Iterate Through the Records
  16: -- INSERT/UPDATE as necessary.
  17: DECLARE @id int;
  18: SET @id = -1;
  19:  
  20: WHILE (@id IS NOT NULL)
  21: BEGIN
  22:     SET @id = (SELECT TOP 1 ID FROM @records);
  23:     IF (@id IS NOT NULL)
  24:     BEGIN
  25:         IF (@id = 0)
  26:         BEGIN
  27:             INSERT INTO Staff (FirstName, LastName, Salary, Role)
  28:                 SELECT TOP 1 FirstName, LastName, Salary, Role FROM @records;
  29:         END
  30:         
  31:         ELSE
  32:         BEGIN
  33:             DECLARE @firstName varchar(50);
  34:             DECLARE @lastName varchar(100);
  35:             DECLARE @salary int;
  36:             DECLARE @role int;
  37:             
  38:             SET @firstName = (SELECT TOP 1 FirstName FROM @records);
  39:             SET @lastName = (SELECT TOP 1 LastName FROM @records);
  40:             SET @salary = (SELECT TOP 1 Salary FROM @records);
  41:             SET @role = (SELECT TOP 1 Role FROM @records);
  42:             
  43:             UPDATE Staff
  44:             SET FirstName = @firstName,
  45:                 LastName = @lastName,
  46:                 Salary = @salary,
  47:                 Role = @role
  48:             WHERE
  49:                 ID = @id;
  50:         END
  51:     END
  52:     DELETE TOP (1) FROM @records;
  53: END

Sure, it looks nasty and it also takes a bloody long time to write! This method is known as “RBAR” or “Row By Agonising Row” (as you can see, for a good reason!).

The Set-Based Way

Think about it like this, we have two sets of data, the data we are updating (the Staff table) and the data we are updating it with (the @records temp table). We need to tell SQL server to mash these two sets together in a way that works as desired.

Looking at the data, we know the following:

  • New records that need to be INSERTed have an ID of 0, since they currently do not have one.
  • Existing records have their ID set to the record ID in the Staff table.

So, the “ID” column in the temp table is really the “hook” that distinguishes how we are supposed to act:

  • All records in the @records set with an ID of 0 must be inserted.
  • All records in the @records set with an ID that is non-zero must be updated.

So, let’s see if we can re-work the above (SetBasedThinking.sql)

   1: INSERT INTO Staff
   2:     SELECT FirstName, LastName, Salary, Role FROM @records
   3:     WHERE ID = 0;
   4:     
   5: UPDATE S
   6:     SET FirstName = R.FirstName,
   7:         LastName = R.LastName,
   8:         Salary = R.Salary,
   9:         Role = R.Role
  10:     FROM Staff S
  11:     INNER JOIN @records R
  12:     ON S.ID = R.ID;

See what we did? We simply performed the desired operations based on the data as a complete set. That is set-based.

I also came across this great post on “thinking set-based” and highly recommend reading it.

INSERTS – Just the One Please

Those on the ball with the above may have noticed something.. What if I was to execute the above script more than once?

We would have a problem. The updates would be fine (assuming the data is still current) however, the INSERTS would execute again, adding duplicate data to our database. Let’s revisit the SQL (SetBasedThinkingRevisited.sql):

   1: INSERT INTO Staff
   2:     SELECT FirstName, LastName, Salary, Role FROM @records R
   3:     WHERE ID = 0 AND NOT EXISTS
   4:     (SELECT * FROM Staff S
   5:         WHERE S.FirstName = R.FirstName AND
   6:             S.LastName = R.LastName AND
   7:             S.Salary = R.Salary AND
   8:             S.Role = R.Role);

Here we have added an NOT EXISTS clause. EXISTS will basically return “true” if the statement passed to it returns one or more records. Our SELECT within the EXISTS is pretty mundane since it is a simple data set, but would probably be a lot easier if we had more realistic data in there (e.g. we could simply look up a SSN).

Common Problem Scenarios

Selecting the “nth” Record

We need to know who has the third-highest salary in the company, can you quickly query the database to find out?

Now, this sounds REALLY easy right? In C# you might see code like the following (NthRecord.cs):

   1: var records = GetRecordsBySalary();
   2: int thirdHighest = records[2];

Here the problem is odd, the problem is because SQL is set-based, it has no concept of an individual row and it’s relationship to rows preceding and following it.

We could quickly establish the top three highest salaries by using this straightforward query:

   1: SELECT TOP 3 * FROM Staff
   2: ORDER BY Salary DESC

We could then use that set and turn it on it’s head, and only retrieve the top record like so (ThirdHighestSalary.sql):

   1: SELECT TOP 1 * FROM
   2: (SELECT TOP 3 ID, FirstName, LastName, Salary, Role
   3: FROM Staff ORDER BY Salary DESC) sort
   4: ORDER BY Salary;

I have been told that this is the correct way to do things pre-SQL2005, but with 2005 comes a better way for us to do things (ThirdHighestSalary2005.sql):

   1: SELECT TOP 1 ID, FirstName, LastName, Salary, Role FROM
   2: (SELECT *,
   3:     ROW_NUMBER() OVER(ORDER BY Salary DESC) AS _RN
   4:     FROM Staff) as S
   5: WHERE _RN = 3;

Here we are using a “Window Function” to figure out the row number of the set. We then take the results of the sub-query and only want the third row, so we filter based on that. NOTE: I am very new to window functions so please bear with me with any queries! Be sure to read the MSDN documentation on OVER and ROW_NUMBER.

Variables

I’m not going to regurgitate the SQL data types here, that would just be silly. But there are a few points I would like to make with regards to working with variables in SQL.

Strings are [almost] Limitless in C#

Always keep in mind that in many databases strings have a limited length.. In C# we are not really used to hitting limits with strings since we rarely run in environments starving of memory. Some weird errors can occur if you do not validate input against allowed field length before saving data.

OO is Great For Data Representation SQL is Great for Manipulation

Working with data on the fly within SQL can be real cumbersome. In C# you can easily create structs/classes to act as DTO’s and then quickly create a method to new up one based on input. In SQL, we do not have that luxury as well as it being tiresome to create standard variables (both DECLARE and SET required). Try to get everything you need sorted before hitting the SQL layer. Keep the process simple. Input in, sets out. Keep SQL for doing data-access. Do the heavy-lifting in C# where it’s easy and you have rich support. Leave SQL to just doing what it has to. READ: KEEP YOUR DAMN BUSINESS LOGIC OUT OF THE DATA ACCESS LAYER!!

Temp Tables Rock, Use Them!

Temp tables are fantastic for working with masses of data input. I have found myself using knocking together the code to churn out the SQL to create a new temp table based on objects. See FormattingCSOutput.cs in the sample code. I threw that together in <5 mins (in Snippet Compiler)and it allows me to quickly populate temporary tables to work with when testing/debugging SQL. This can easily piggyback off of your stubs for your unit tests to quickly get you testing your SQL and not messing around with trying to get dummy data to work with. You also have the obvious safety net of not actually making any changes to the data.

To Wrap Up..

  • I am not a SQL guru – far from from it. The above may not be “best practice” but as a developer I try to find ways to help keep me productive and as error-free as possible.
  • I do not intend to be a SQL guru – Companies need to stop penny-pinching and realise that if they want a great developer, they are not going to a great DBA as well (unless they are really, really lucky). Hell, I have heard horror stories of DBA’s that are worse DBA’s than developers – even if you lose a few milliseconds in your data access layer, you still get a kick-ass product right? ;)
  • I have found today useful just to write more SQL. I made so many screw ups (especially on the procedural vs. set-based stuff) as well as just having to double-check syntax. While this may not be a comprehensive guide, it has not been a waste of a day.
  • I am already thinking about righting a nice little C# generic helper to just take an object and dump the SQL to create a temp table :)
  • I still have a great deal to learn about SQL, but I’ll be a bit more pro-active and organised about using it now. I have a slightly better understanding of what SQL is good for, and what it is not good for. A small step forward is better than staying stationary.

I think I would have to say the realisation I got from today is this:

Write more SQL, just don’t try and write EVERYTHING in SQL.

Pick your shots ;)