Fear and Loathing
Gonzo blogging from the Annie Leibovitz of the software development world.
-
Dolphins, Humans, and Digital Wristwatches
Yeah, the titles are getting sillier and sillier but that's a direct result of being locked up in a room with John Bristowe for 3 hours consuming pizza, filtered Calgary water, and podcasts. James has taken over the all important but seldom overlooked duties of splicing together the mess that we call a podcast, Plumbers @ Work and put episode 10 online.
Lots of great discussion about OR/M tools like NHibernate and the ADO.NET Entity Framework (they really need a cool, catchy, codename) and game development and stuff. JP is MIA but he'll be back.
You can catch the episode here on our podcasting site Plumbers @ Work and download it directly here to your favorite MP3 device, like an Etch-A-Sketch.
10 whole episodes of greatly outdated material and bits that nobody will ever listen to again. Maybe someday we'll get big and strong and start wearing the big-boy pants and have some useful to say, in the meantime be sure to kill an hour listening to this.
-
Groking Rhino Mocks
If you've been in a cave for awhile, there's a uber-cool framework out there call Rhino Mocks. Mocks are tools that allow you to create mock implementations of custom objects, services, and even databases, to enable you to focus on testing what you're really interested in. After all, do you really want to be bogged down while your unit tests open up a communication channel to a web service that might be there, only to test a business entity that happens to need a value from the service?
Rhino is a very cool framework that Oren Eini (aka Ayende Rahien aka the busiest blogger in the universe next to Hanselman and ScottGu) put together. It recently hit version 3.0 and is still going strong. If you don't know anything about mocks or are interested in Rhino now is your opportunity. Oren has put together an hour long video screencast (his first) that walks through everything you need to know about mocks (using Rhino of course). I strongly recommend any geek worth his or her salt to sit down for an hour, grab some popcorn, and check out the screencast. You won't be disappointed.
You can download the screencast here (35mb, which includes the video and the source code for the demo). You'll need the Camtasia TSCC codec to watch the video which is available here. More info and a copy of Rhino itself can be found here.
Enjoy!
-
Introducing... the Scrum Witch!
My co-worker came by today and dropped off something at my desk. He calls it the Scrum Witch. Here she is:
She's a crazy one alright (and loud). We've had some challenges getting everyone to follow the daily Scrums as side discussions start happening, water cooler gossip, etc. and 10 minute standups turn into 30 minute meetings. We're also all about fun and trying to enjoy our jobs.
So anyone who starts to stray from the Scrum rules (a watered down version from various places like here that we've printed out and put up in the Scrum Room), we unleash the "Scrum Witch" on them. A small button on her back lets out a screaming wail to let the speaker know we're off on a tangent and a reminder to get back to business.
We'll see how it goes over the next few weeks (or until the entire team gangs up on the Scrum Master and beats him to death with, in which case this might be my last post).
-
The old age home for saved Groove account files
I was digging Groove, Microsoft's acquisition from Ray Ozzie and co. before he joined the evil empire and now part of Office 2007, way back in 2005 when I got a copy of the latest version. I also took a copy of my license file (the .grv file) and as a good citizen, backed it up. It sat on an external drive and there it stayed for months. The last saved copy was back in October of 2006.
I finally got around to trying to use the new Groove 2007 (we have a workspace on there for the Plumbers@Work gang) I was rather disappointed with this friendly error message:
Hmmm. Okay, so my license file is too old. Hate to tell you, but I don't have a newer one so this message is about as useless as it gets. Please import a more recently saved version of this account. Besides perhaps being grammatically wrong, what if you don't have a "more recently saved version", which is the pickle I appear to be in.
A few questions in the MVP groups yielded only one unflattering and hopeless response.
"Your screwed"
So I'm asking any Groovers (Groovers? Groovies?) out there. Am I? Is there a way out of this madness? I can't seem to find any contact info on the Groove site and even with all my ungodly MVP powers (read:none) I can't seem to find a way to get Groovin' again.
-
3 Team System Goodies
Stumbled over 3 different goodies for Team System and CodePlex that will be very valuable to me. Hopefully these will be useful to you too.
CodePlex Source Control Client
This is a command line tool which allows users to work offline (in the "edit-merge-commit" fashion). It's not as full featured as what you can get from the web experience or Visual Studio, but will help doing quick edits. This is the initial release so expect a few issues and bugs out of the gate but it does give us something that we can't get from Visual Studio, anonymous access. So non-developers on a project can pull down the source code with the command line client. Next up should be a Tortoise-like interface that will make it even easier to use (but I can dream can't I?)
Team System Prescriptive Guides
This is a plethora of whitepapers, best practices, videos and standards that you can just use in your organization if you're using Team System. No mess, no fuss. Contains guidance on structuring your solutions, custom check-in policies, branching, and migrating from VSS. Very handy!
This is probably the biggest surprise as I didn't see it coming (but then I'm asleep half the time). MS aquired a company that makes a web based client for accessing Team System (TeamPrise) so now they've got a web client for accessing Team Systems (should work with CodePlex but I haven't tried it yet). Best of all, it's free! Great for non-Windows clients accessing Team Systems if that's useful for you.
And I haven't even got through all my feeds yet!
-
Returning Generic Lists from NHibernate
This was an "aha" moment for me this morning as I was building a small spike project to figure out how we can incorporate NHibernate as our data access layer and still be a happy loosely coupled Smart Client.
Beyond the fact that I have to create a class library to hold all my interfaces for my domain (as I need to inject my data provider into the domain repository and can't have circular references to NHibernate, but that's another story) I was finding it frustrating that I was getting ArrayLists back from NHibernate.
Here's a method that gets me back a list of customer objects from the NHibernate session:
1 public List<ICustomer> GetCustomers()
2 {
3 List<ICustomer> customers = new List<ICustomer>();
4 ITransaction tx = null;
5
6 try
7 {
8 tx = Session.BeginTransaction();
9 customers = (List<ICustomer>)Session.CreateCriteria(typeof(ICustomer)).List();
10 }
11 catch (HibernateException)
12 {
13 if (null != tx)
14 {
15 tx.Rollback();
16 }
17 }
18
19 return customers;
20 }
Typical stuff and the example you see everywhere. However I like dealing with a generic List<ICustomer> object rather than an IList (some will argue it's the same thing). The code above compiles fine, but when you run it you get an error as it cannot convert an ArrayList to a List<ICustomer> no matter how hard it tries. A quick check on the Session class in Reflector revealed to me there was a generic List<T> method. One line of code change was all that was needed and voila:
1 public List<ICustomer> GetCustomers()
2 {
3 List<ICustomer> customers = new List<ICustomer>();
4 ITransaction tx = null;
5
6 try
7 {
8 tx = Session.BeginTransaction();
9 customers = (List<ICustomer>) Session.CreateCriteria(typeof (ICustomer)).List<ICustomer>();
10 }
11 catch(HibernateException)
12 {
13 if(null != tx)
14 {
15 tx.Rollback();
16 }
17 }
18
19 return customers;
20 }
Subtle but the change in liine 9 from List() to List<ICustomer)() gets me a collection of List<ICustomer> objects coming back from NHibernate. Silly I know, but something to watch out for as all the examples out there say call List() to get an IList back but this way you can get a generic list of whatever objects you want.
-
Fixing Product Backlog items in Scrum for Team System
For those of us who use Conchango's process guidance package for Visual Studio Team System, Scrum for Team System, life is good. Scrums are easy to track, burndown charts are cool to put up on the wall, and it's a breeze to see immediately where you are anywhere anytime. However there's been some rumblings with the tool for awhile but Conchango has come to the rescue with a fix.
The problem reared it's ugly head for me a month or two ago. I would look at the reports and whatnot on how much work remaining (in hours) there was on our Product Backlog Items (PBIs) for a given sprint. In our case, we had 600 hours left (which seemed about right). However when I looked at all the Sprint Backlog Items (SBIs) and totalled the hours remaining on the tasks, it only came to about 450 hours. This wasn't right and was really affecting our burndown charts and general feel of how much work was left before the sprint ended. Basically the work remaining in a PBI is inconsitent with the total work remaining for all the linked SBIs.
It is possible in “normal operation” for this to happen. The following are the most likely causes of this behaviour:
- Where a SBI is unlinked from a PBI and the SBI still had work remaining prior to being unlinked. Please reduce the Work Remaining to 0 and save prior to unlinking.
- Where an SBI is marked as deleted (v1.0, v1.1). This would not cause resynchronisation, and this can be resolved by installing Scrum for Team System 1.2.
- Where load conditions on the server cause the “eventing service” to timeout, the work remaining in this case would not be updated.
- Where a PBI Work Remaining is edited from within Excel (unfortunately using the Excel add-in for TFS has the potential to overwrite a “read only” field).
After some discussion in the forum and a bit of testing of their tool, my problem is fixed. The command line tool is called the "Scrum Consistency Check" and will identify and resynchronize the work remaining on any project in your Team System that you think might be "out of sync".
It's a command line tool, but you run it from anywhere. The syntax for the tool is:
ScrumConsistencyCheck.exe [server] [project] [refresh (true|false)]
The server is your TFS server name. The project is what project you want to interrogate/update. The refresh is if you want to perform the update or just get a report of what the status is.
Here's a sample output from one of my projects that was suffering:
Check.exe myserver "BRMS" false
Server: myserver
Project: BRMS
Refresh out-of-sync PBI's: falseNumber of PBI's in Team Project: 228
Inconsistent backlog items:
PBI 273, Work Remaining: 8 hours, Children: 13
Inconsistent work remaining, difference: -8 hours
SBI: 772, Sprint: 5 State: Done, Work Remaining: 0 hours
SBI: 756, Sprint: 4 State: Done, Work Remaining: 0 hours
SBI: 748, Sprint: 0 State: Not Done, Work Remaining: 0 hours
SBI: 346, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 282, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 281, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 280, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 279, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 278, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 277, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 276, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 275, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 274, Sprint: 2 State: Done, Work Remaining: 0 hours
PBI 678, Work Remaining: 12 hours, Children: 2
Inconsistent work remaining, difference: -12 hours
SBI: 869, Sprint: 4 State: Done, Work Remaining: 0 hours
SBI: 709, Sprint: 4 State: Done, Work Remaining: 0 hours
PBI 235, Work Remaining: 2 hours, Children: 6
Inconsistent work remaining, difference: -2 hours
SBI: 396, Sprint: 3 State: Done, Work Remaining: 0 hours
SBI: 321, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 320, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 319, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 318, Sprint: 2 State: Done, Work Remaining: 0 hours
SBI: 317, Sprint: 2 State: Done, Work Remaining: 0 hours
PBI 676, Work Remaining: 16 hours, Children: 0
Inconsistent work remaining, difference: -16 hours
PBI 998, Work Remaining: 4 hours, Children: 0
Inconsistent work remaining, difference: -4 hours
PBI 220, Work Remaining: 59 hours, Children: 0
Inconsistent work remaining, difference: -59 hoursHours lost (less in PBI than SBI): 0
Hours lost (less in SBI than PBI): 106Finished! Press <enter> to continue.
Once you run the tool and pass in "true" to refresh the out-of-sync PBIs you should see this:
Check.exe myserver "BRMS" false
Server: myserver
Project: BRMS
Refresh out-of-sync PBI's: falseNumber of PBI's in Team Project: 228
Inconsistent backlog items:
Hours lost (less in PBI than SBI): 0
Hours lost (less in SBI than PBI): 0Finished! Press <enter> to continue.
You can download the tool from here. For support of the tool, please use the forum here. Hope this helps!
-
Return of the Plumbers... finally
Well, 3 of us anyways. Yes, after 4 months of delays and vacations and concealed lizards of many kinds we're back with episode 9 of Plumbers at Work, our .NET community podcast that I do with John Bristowe, James Kovacs, and Jean Paul Boodhoo. JP is away in Edmonton during this podcast, but James, John and I blast out another episode. You can listen to the episode in your MP3 player directly from here. We're taping episode 10 this Wednesday with the full suite of plumbers that hopefully will be online shortly.
P.S. I'm generally a loudmouth and barking out my stuff on the podcast, but this episode I seem to have been muted down quite a bit. Need to yell a little louder into the mic next episode.
-
Adding a splash screen to a CAB application
Been awhile since I blogged as I've been sort of out of it missing the MVP Summit and all. Here's a simple way to add a splash screen to your Composite UI Application Block (CAB) based applications. It's pretty simple to implement a splash screen. This is a basic form that will popup with a logo or whatever of your choosing while the application loads. The code below is based on applications generated with the June 2006 version of the Smart Client Software Factory, but the idea is the same and can be applied to any CAB application.
First, create the splash screen. This will just be a simple Winform you add to your Shell project. Call it ShellForm and give it a splash image to display. it helps if you change a few properties to make it more "splashy":
- Change the StartPosition property to CenterScreen
- Change the ShowInTaskbar property to False
- Change the FormBorderStyle property to None
Now drop a picture box on the form and load up your image. Any image will do, but you'll probably want to size the splash screen to match the size of the image (otherwise some shearing might occur).
Now we need to modify two files. ShellApplication.cs and SmartClientApplication.cs. In ShellApplication.cs all you need to do is change the call to the base class of SmartClientApplication to accept your ShellForm. Change the declaration from this:
22 class ShellApplication : SmartClientApplication<WorkItem, ShellForm>
to this:
22 class ShellApplication : SmartClientApplication<WorkItem, ShellForm, SplashForm>
SplashForm is the name of the class you created for the new form. Finally we get down to the meat of the splash screen. In SmartClientApplication.cs we need to do two things, recognize the new parameter being passed into the class and get the splash screen going.
First add a generic to the declaration of the SmartClientApplication class as TSplash:
25 public abstract class SmartClientApplication<TWorkItem, TShell, TSplash> : FormShellApplication<TWorkItem, TShell>
Then initialize it like the WorkItem:
25 public abstract class SmartClientApplication<TWorkItem, TShell, TSplash> : FormShellApplication<TWorkItem, TShell>
26 where TWorkItem : WorkItem, new()
27 where TShell : Form
28 where TSplash : Form, new()
Add a private member variable to hold the splash screen (using the generic type "TSplash"):
30 private TSplash _splash;
Create the object in the constructor:
35 public SmartClientApplication()
36 {
37 _splash = new TSplash();
38 _splash.Show();
39 _splash.Update();
40 }
After the shell gets created, we want to kill off the splash screen. We'll do this in the AfterShellCreated method of the SmartClientApplication class by adding an event handler when the Shell gets activated. Change your AfterShellCreated method to look like this:
46 protected override void AfterShellCreated()
47 {
48 base.AfterShellCreated();
49 Shell.Activated += new EventHandler(Shell_Activated);
50 }
And create the event handler. The handler will remove the Shell.Activated event and dispose of the Splash form:
57 private void Shell_Activated(object sender, EventArgs e)
58 {
59 Shell.Activated -= new EventHandler(Shell_Activated);
60 _splash.Hide();
61 _splash.Dispose();
62 _splash = null;
63 }
That's it! A cool looking splash screen for your CAB application in about 10 minutes.
Note: There was a long thread here on the GDN forums (moved to CodePlex) on doing this. That technique works as well, and gives you the ability to intercept the "loading" of the application as it goes through it's paces. We're using it for one app, but the technique above is a more simple approach that just gets the job done so you might find it easier to implement.
-
On being a "SharePoint" expert
Recently Rocky had one of his many pearls of wisdom, that of the software development world becoming a specialization due to the complexity of the industry. Let me tell you that a) I agree with Rocky 100% (and more if anyone could agree more than 100%) and b) this is true especially so for SharePoint developers and 2007 (the version, not the year).
Actually, let me quantify that. What is a SharePoint developer? Is it a ASP.NET developer who knows a lot about the SharePoint API or is it a SharePoint developer who knows a lot about the ASP.NET API? The answer is yes.
Take me for example, I really didn't do a lot of ASP.NET development (about a year or so since B1) so other than little apps, the odd web service, etc. I really didn't have an in-depth experience being an ASP.NET developer. When I got the SharePoint itch I scratched it with what little COM+, ASP and structured development techniques I knew (we're talking back in STS and SPS 2001 days, before the .NET version). With v2 and 2003 came .NET and more knowledge of how IIS worked, ASP.NET server controls and all that goodness. Now here's 2007 and we're dealing with ASP.NET 2.0, security and membership providers, master pages, user controls, workflow, and a million other little tips, tricks and gadgets that would drive anyone batty.
It's just too much for any one brain to handle (except maybe Hanselman, but we all know he's not human anyways). And there's more to come! Upgrading from ASP.NET 1.1 to 2.0 was a huge shift for SharePoint (in fact a complete flip of the architecture, literally) but moving to 3.0/3.5 isn't going to be that much of a big deal. It's just a different version of the API, a set of new dlls, some Atlas thrown in. Basically a service pack, not a full blown release. With that will come all kinds of things. How about LINQ for SharePoint? We already have people writing PowerShell servlets that will treat SharePoint sites as folders you can navigate, so querying a SharePoint list shouldn't be any more difficult than using LINQ to query a list of objects.
The future is here and moving fast. Being a SharePoint expert isn't just about knowing all the technologies, layers, and tiers that encompasses SharePoint because frankly that's not realistic. SharePoint is just another layer in the stack, another tool in the toolbox, for us "developers" to work with. Whether we choose to weigh more heavily on the SharePoint API or the ASP.NET one, it's just a matter of what we're trying to accomplish. Being a SharePoint expert is about knowing what's available and making use of it, and getting the guys who really know this stuff inside and out to build it for you (or if you're that guy, build that part yourself).
I think gone are the days where being a SharePoint expert meant you knew every nut and bolt of every piece of the machine. Today, you're lucky if you can get your head wrapped around one part of it.