Upcoming MSDN User Group Tour of Manitoba and Saskatchewan
Fresh off a quick tour of Ontario, I'm getting ready to head off to Manitoba and Saskatchewan to talk to the .NET User Groups out there. On Tuesday the 4th of December I'll be in Winnipeg .NET User Group talking about Brownfield Software Development Techniques. The next day, Wednesday the 5th, I'll be in Saskatoon talking to the Saskatoon .NET User Group about an Introduction to Alt.NET. On the 6th I'll be in Regina showing the Regina .NET User Group some of the new language features in C# 3.0 and .NET 3.5.
If you're in any of these cities on those dates, drop in and see us. It's usually a good time and often there's a beer or two after.
Ontario MSDN mini-tour wrapup
I'm home from a 3 day junket through south and eastern Ontario. I'd like to take the time to wrap up the three events here. First huge thanks go out to MSDN Canada and their endless support of the community through the speakers bureau. As a user group leader I know that getting speakers from different cities and regions into a local group can be very instrumental to sparking a communities interest in a technology, methodology or technique.
East of Toronto .NET User Group
Big thanks to Chris Dufour for setting going through the process to make this meeting happen as well as providing transportation to and from the hotel for me. The folks at this event really got into the topic (C# 3.0 and .NET 3.5) and they asked a lot of good questions. The group also wins a prize for the biggest coincidental event occurrence I've ever heard of. I spoke on the new framework the day that it RTM'd. I've put the bits for the code we worked through up here for download. I've also done some screencasts on this topic before which can be found here, here and here.
Metro Toronto .NET User Group and the Toronto Visual Basic User Group
Thanks here goes to Graham Marko and Rob Windsor who setup the meeting. After a taxi driver tried to take advantage of my western ignorance (even I know not to try to make a left turn onto Bloor at an uncontrolled intersection at 5pm on a week night), I managed to find my way into the building and get on with the meeting. The session was supposed to be an introduction to Alt.NET and move on to implementing some of the ideas and concepts around it through the use of CCNet and nAnt. Part way through the meeting it became obvious that the attendees were much more interested in OO practices, design patterns, MonoRail and TDD so I went agile and suggested that they vote between those topics and the CCNET/nAnt one. So instead of the original abstract for the talk we ended up with a very different subject for the last hour to hour and a half. As I mentioned in the session, the code that I was using for the demo isn't ready for release yet. It will happen in the next couple of months and at that time you'll see about it here and I'll be letting the UG leaders know so that they can inform you too. So out of that presentation you can only get the slide deck which can be found here.
While in Ottawa I had planned on presenting the same Alt.NET/CCNet/nAnt topics that were originally planned for Toronto. Because of the success I had with the topic change for the second hour of the presentation in Toronto, I figured I'd throw that option out to the attendees in Ottawa too. Although a little shy during the vote on the topic change, most of the people did want to see the same stuff I had presented on in Toronto. To my surprise, when I started the application up to give a quick overview of the business problem being solved, it immediately gave me the yellow screen of death. I've often seen people screw around with their code immediately before a presentation only to have it not work at all or as expected when needed, and I've always chastised them for their actions. Well wouldn't you know that I spent 4 hours working on that code between the two presentations only to have the same thing happen. Luckily for me it only took a minute to determine that I was missing a concrete implementation that Windsor was looking for. Another lucky thing for me was that people wanted to see some TDD and this gave me the perfect opportunity to show the process of writing a test that won't compile, getting it to compile with the test failing, and then making the test pass. It also gave me a chance to make ReSharper dance which was another topic that people wanted to see. In another good coincidence, Orest had a couple of ReSharper licenses to give away at the end of the night to attendees. Like in Toronto, I will be releasing this code but it will happen when I'm confident that it has met the goals I want to achieve. The slide deck is exactly the same as it was for Toronto and can be found here.
Overall the trip was a great experience. The people at the groups were great, the attendees asked some fantastic questions and the topics were welcomed with great enthusiasm. I learned some lessons from doing this for sure. One of the biggest lessons was that there is a huge appetite for the fundamental skills that Alt.NET pushes. Thanks to everyone who came out and generated the excitement in the rooms which had me feeling like I could present for another 2 hours on the same topic even after finishing my allotted time.
Object conversion fix
I forgot to put the link to the downloadable source code for the Object Conversion post that I did yesterday. I have fixed that post and downloads are available here.
Object conversion
A while back JP posted about how he likes to use a different set of objects for transferring data to the UI layer (Screen Bound Dtos) than the ones that he has implemented in the domain model. This is my preferred way to manage data flow as well. I find that it allows me to push data to the UI in only the context that is required for the one screen that I am working with at the time.
As part of a couple of discussions I had last week, I showed the implementation that I used on my last big project and which now has become the standard starting point for anything I work with. If you don't want to read this any further I'll tell you now that the implementation uses an ITranslate<From, To> interface that is applied to a base class (BaseTranslate<From, To>) which then is inherited by any class that needs to offer translation capability. You can download the source from here. Note that the source doesn't include the assemblies for the Castle Windsor container that is used in the code.
What I was originally trying to solve with this translation code was a the existence of code that called for translation in the following way
Client client = ConvertToDomain.Instance.ConvertClientDto(clientDto);
Address address = ConverToDomain.Instance.ConvertAddressDto(addressDto);
The main problem that I was trying to solve was that all conversions were implemented in one of two classes (one for Domain to Dto, the other for Dto to Domain) each which had around 10,000 lines of code. I wanted to have the translation code moved out into separate classes so that we had more adherence to the Single Responsibility Principle as well as increasing the testability of each one of the translations.
What I came up with was an interface that I called ITranslate that we could implement on any class that contained translation code. The interface looks like this
public interface ITranslate<From, To>
{
To For(From from);
IEnumerable<To> For(IEnumerable<From> fromList);
}
What we get is the ability from every translation class to convert objects one at a time or many at a time. When I first implemented this I had no need for the conversion of many objects at once. In my implementations of this since I have added the "many" translation and in doing so I noted that the "many" translation almost always looked exactly the same. It was a foreach loop over the fromList and in that loop the single translation was called and yield returned. To get rid of this code I'm now creating a BaseTranslate class that looks like this
public abstract class BaseTranslate<From, To>:ITranslate<From, To>
{
public abstract To For(From from);
public IEnumerable<To> For(IEnumerable<From> fromList)
{
foreach (From from in fromList)
{
yield return For(from);
}
}
}
Now my translation classes implement the BaseTranslate class instead of the ITranslate interface. My concrete implementations now only contain code that is specific to that one scenario. Here's an example of a concrete implementation for Client and ListClientDto objects
public class ClientToDtoTranslator:BaseTranslate<Client, ListClientDto>
{
public override ListClientDto For(Client from)
{
ListClientDto listClientDto = new ListClientDto();
listClientDto.Id = from.Id;
listClientDto.Name = from.Name;
listClientDto.City = from.BillingAddress.City;
listClientDto.Province = from.BillingAddress.Province;
return listClientDto;
}
}
When I initially was getting a guy at work to do all of this refactoring (I think there was something like 200 conversions stuck in those 2 original classes) we decided to use a factory to dispense the appropriate translator depending on the To and From types that were passed into the factory object. The factory had all instances of all the concretions stored in a Dictionary<From, Dictionary<To, ITranslate<From, To>>> structure. The guy writing this cussed me up and down (Hey Ted!) because of the overhead that we had to manage in the factory. Eventually we found that it was just too much as we had translators that required other translators inside of them. If things weren't ordered properly in the constructor of the factory, converters would just throw null reference errors all over the place. Ted managed to figure out how to over come this, but in the end it wasn't pretty and every time I think about it I feel dirty.
Since then I've decided that using an IoC container is the way to go. As you'll see in the sample code, I'm using Castle Windsor and it's given me a very clean implementation. For this sample I've decided to create the instance of the Windsor container in a singleton. If I were doing this in a real project I'd probably put it somewhere else, but for simplicities sake this is what I did here. What you end up with is a Windsor config file that has something that looks like this in it (this is the entry for a ClientToClientDtoTranslator)
<component id="ClientToClientDtoTranslator"
service="IglooCoder.Spike.Translations.Core.Translators.ITranslate`2[[IglooCoder.Spike.Translations.Core.Model.Client, IglooCoder.Spike.Translations.Core],
[IglooCoder.Spike.Translations.Core.Dtos.ListClientDto, IglooCoder.Spike.Translations.Core]], IglooCoder.Spike.Translations.Core"
type="IglooCoder.Spike.Translations.Core.Translators.ClientToDtoTranslator, IglooCoder.Spike.Translations.Core" />
It's ugly, there's no doubt about it. The nastiness comes from the fact that I'm going to be calling the container looking for an object that implements ITranslate<Client, ClientDto> and the notation for generics is just gross. Regardless, I will need to have one of these entries in my Windsor configuration file for each of the concrete implementations that I have in my application. My only complaint about this is that you loose a little bit of refactoring power because you now have the class and interface names in strings.
What I was striving for was a minimalist code implementation that also exposed a clean API for developers to work with. Below is the one and two line calls that the developer can work with. I prefer the one line implementation, but it's developer preference I think.
ListClientDto dto = Container.Instance().ResolveFor<ITranslate<Client, ListClientDto>>().For(client);
ITranslate<Client, ListClientDto> translator = Container.Instance().ResolveFor<ITranslate<Client, ListClientDto>>();
ListClientDto dto2 = translator.For(client);
That one line hits the IoC container which resolves the type to return and then it uses the For(...) method to do the final translation.
I'm not sure if this will work in a lot of scenarios, but the four or five times I've needed to do something like this it has worked quite well.
Air Canada Coach
I'm flying to Toronto on Air Canada right now. I rarely fly AC because my experience has shown the seats to be uncomfortable and the service to be sub-par. I skipped the lines in the airport (and thus the experience of dealing with an AC representative) by using the self check-in kiosks littering Edmonton International. If you have nothing but carry on, I suggest these as I was into the airport and on my way to the security line (at a much slower pace than I was asked to in Winnipeg) in about 3 minutes.
I digress though. I'm sitting here in row 21 which is firmly in the middle of coach on this particular airplane (Airbus A320) but each seat has it's own seat back entertainment system. The system offers TV, Movies and satellite radio via a decent touch screen interface. The thing that truly amazes me though is that beside the screen there is a fully operational 110V plug (only 2 of the three seats on each side of the aisle have them) plus a USB jack (I assume this is for a feature on the music side that allows you to play your own play list). If I had a poorer battery the plug would be very handy. I used to think that power outlets were the domain of the pretentious first class. Today I feel a little bit special....I'm sure that will wear off though.
A Tale of Travel Gone Good.....I think
Unlike most people, my travel experiences, especially flying, have been of the positive variety. Every so often I have something disturbing or inconvenient happen, but rarely have they caused problems or too much angst. This week I was out in the Mecca of western Canadian civilization, Winnipeg. My flight there was uneventful and even could be rated good as I met an old college roommate that I hadn't seen in 10 years. The story really starts today with my flight back to Edmonton.
When I initially booked my flights I realized that I was going to have to be in the office for the vast majority of the day today and thus a later flight was going to be required. As direct flights to anywhere other than Flin Flon and Moose Factory are rare, I decided that I was okay with traveling through Calgary with a short layover. So I had mentally prepared myself for this set of flights and was quite comfortable with them.
I left work and arrived, like a good little traveler, at the Winnipeg (International?? and no D'Arcy, Brandon doesn't qualify it for international status) Airport about 1hr and 45min before my departure time. This was going to be great for me. I'd sit in the departures lounge, decompress from an intense week and work on some mindless tasks that I had outstanding before I boarded. As I entered the airport I heard the following announcement over the public address system:
This is a final boarding call for passengers on WestJet flight XXX to Edmonton.
I know that I'm not on this flight as I figured there was no way I was going to make it to the airport in time to catch it. Because of that, I have no worries. I just wander up to the self check-in kiosk and push in my credit card so I can get my boarding passes. They system gives the card back along with the onscreen message "Your credit card could not be read. Please try again." So I try again. Same message. I tried four more time, each time changing the location of the magnetic stripe just in case the complete lack of a diagram showing which location is correct was sick attempt at humor by the gate agents. Each time I get the same error. So I move over to the wicket and head up to the counter (no line up) to get my boarding passes. I tell the agent which flight I was on and she says "Well, your plane to Calgary is running about 1 hour late". I immediately say "I guess that means I won't make my connection then right?" This agent didn't even hesitate when she responded with "Yes, you won't be able to make that connection and I don't have another flight to put you on in it's place". I'm thinking that this is fantastic. I've gotten the one agent who actually isn't going to jerk my chain, will tell me straight up what the situation is and will probably work hard to get me home.
Here's where it starts getting really interesting.
This agent (I really wish I had her name 'cause she deserves all the thanks in the world) decides to run off and grab the 2-way radio from one of her co-workers. She calls off somewhere and asks if the direct flight to Edmonton has pushed back yet. When they tell her no, she hammers the shit out of her keyboard, grabs a boarding pass and says "Follow me...and run!" At this point I've been in the airport for about 10 minutes since hearing the "final" boarding call for the direct flight to Edmonton.
Off we go. The two of us running up and escalator and over to the security clearance line. This lovely little lass heads through some top secret employee only door and says she'll meet me on the other side of security, but hurry. So I hit the line at a dead run, pulling my laptop and liquid & gels out for a separate tray. I turn the corner and what do you know, there's a line of about 20 people. I ask the security dude if I can cut up front as I'm in a rush only to hear this over the public address system:
If there is a Mr. Donald Belcham in the terminal please make your way immediately to Gate H for the on time departure of your aircraft.
This is the first time I've ever heard my name called of the airport public address system and it jacks my heart rate up another 10 beats per minute (now totally somewhere between 700 and a bajillion per minute). This security guy (very nice and polite by the way) says, "I can't help you cut the line, but if you can convince the other people in the line to let you cut places then go ahead." So I start by asking people individually if they mind (we Canadians are very polite in stressful situations). All of them are kind enough to say yes....then the stress hits and I just start asking one person in each part of the line, skipping 5 or more people each time. Apparently my progress was too slow for the WestJet agent and she sends another security guard into the line to pull me out and shove me through the line. So I'm up at the X-ray machine, stuff gets in the trays in record time and I'm into the metal detector.
Well folks, if you didn't know it already I've had a few wrecks in my life. Needless to say, those wrecks have it so I always set off the metal detector. So I walk through the detector, straight to the wanding station and assume the standing-spread-eagle pose that they request. Wand lady (not so talkative, unlike the rest of the people I ran by on my way to this point in the airport) starts going over my body and sure enough the resounding beep starts popping up in different places. "Yep, that's a metal plate from a rodeo wreck in '97"...."That's a screw from a wreck in '98"...."That's a plate from my time in the astronaut service"....okay...that one isn't true.
Anyways, while I'm explaining all the beeps there are 2 WestJet agents trying to determine what is mine on the X-ray out belt and get it packed up and ready for more running. Wand lady hits my midsection and the wand goes off..."Are you wearing a belt sir?"..."Yes"..."Please undo it"....so I do and thankfully these pants don't immediately succumb to gravity. Wand lady gives me the green light to leave and the WestJet agents head off at a run. So picture this. Two very attractive, blonde WestJet agents running through a mostly empty airport with a computer programmer, belt undone, appearing to be chasing them at top speed. I'm sure it looked far worse than it was....really....I was trying to catch the plane this time.
We hit the gate, they check my photo id against the boarding pass just incase I'm not the same person that has been chasing them through the airport all the way from the point I got the boarding pass. Off I go down the jetway to board the plane, which is still waiting at what must be 15-20 minutes after I heard that first "Final Boarding" call on may way into the building.
I get on the plane and am saved the indignity of having to walk to the back past all the people who are thinking "We made it here on time, why didn't his fuckwad leave enough time like we did? Some people are so unprepared and inconsiderate." My seat is in row one and, of course, there is no under-seat storage so the flight attendants walk up and down the aisle looking for any place to put my carryon luggage.
After that it was a good trip, the guy next to me just about cried he was laughing so hard when I told him what had happened. All I have to say is that I owe one WestJet agent in Winnipeg a huge thank you. I wish I could remember her name so that I could write a formal thank you and commendation for her supervisor.
Lest We Forget
I feel unquestionably blessed to live in a country that has a military heritage as strong as we Canadians have. From The War to End All Wars, to the Second World War, Korea, the countless and thankless Peace Keeping missions and most recently Afghanistan. Like Tom, I too have served with the CF and perhaps it is because of this that I feel such a bond with the people who have in both the past and present chosen to serve.
To those who have served in the past, thank you. We owe you a debt of gratitude that can not be repaid with words.
To those in the CF who are currently training for and stationed in Afghanistan, we thank you. Trent and the guys and gals of Lord Strathcona's Horse C Squadron and everyone else who are currently operating in Afghanistan, stay safe.
Going to Winnipeg...
For those of you that aren't privy to the Fountain Tire television ads here in Canada, that is the final line in one of them. Yep....Winnipeg. If you're in the City of....what the hell is Winnipeg the city of? Looking at the official city website, there's no mention. Maybe they're the City of Flooding-Every-One-Downstream. Or they're they City of Rebellion. Maybe they're the City of Red River Carts. Who knows.
Anyways, if you're in Winnipeg on the night of the nights of the 12th, 13th or 14th of this month, drop me an email and we'll setup a geek dinner or something.
Ontario Speaking Tour
I'm booked up for the end of November to be in Ontario doing a whirlwind speaking tour.
On the Monday the 19th I'll be at the East of Toronto .NET User Group speaking on the new features in .NET 3.5 and C# 3.0. The abstract and registration links can be found here.
The following night (Tuesday, November 20th) I'll be speaking for the Metro Toronto .NET User Group in combination with the Toronto Visual Basic User Group. That presentation will be on Alt.NET development practices and principles. Registration and abstract can be found here.
My last stop on this trip will be in Ottawa on Wednesday the 21st of November at the Ottawa .NET Community. The presentation that night will be on Alt.NET development practices and principles.
Drop by one of these events and introduce yourself. Throw rotten vegetables if necessary.
A good Alt.NET primer
Wally McClure just released a great podcast on Alt.NET. He interviews David Laribee who articulates the mantra behind the movement (practices and principles over tools and frameworks). I have to say that I didn't get the chance to meet Dave when I was in Austin, and I'm a little disappointed now that I've heard this. This interview certainly shows him as a very articulate and passionate person. Here's hoping that I get the chance to have a conversation with him at the next Alt.NET Open Spaces Conference.
If you're new to the Alt.NET world, or if you're an old timer, take the time to listen to this podcast.
Premature Optimization and Mental Masturbation
For the last few days I've been thinking about some things that were said in a system design conversation that I had. To set the tone, we were talking about a greenfield web application that was to be written using the Microsoft development stack.
The conversation headed down a rabbit trail that covered beliefs in a number of different areas including the age old Stored Proc vs. Parameterized SQL. That's one argument that I'm sure all of us have seen batted around enough to be able to speak clearly, professionally and with authority on. The discussion point that caught me off guard was where object inheritance was linked to performance degradation. I'd never heard this argument made before. I was confused. I was flabbergast. I was speechless....well....almost. Above all, I was left curious. Does inheritance cause performance problems in .NET code?
Like any programmer worth the donut they eat in the coffee room every morning, I Googled the question. Of all the results that were returned only two were remotely interesting. First there is a page on MSDN about Asp.NET Configuration File Hierarchy and Inheritance, which, while interesting and addressing performance, isn't related to object inheritance. The second was a post by David Boschmans which discusses Code Reviews with a focus on Performance. In that post he discusses the use of inheritance with .NET attributes, which, again, is quite interesting, but not what I was looking for.
So Google draws a blank for me. I own Visual Studio, I'm currently between contracts and I haven't yet purchased Halo 3 so I figured what the heck, let's do a little experiment. First I wrote a little bit of code that had an Animal class and a Dog class which inherited from Animal. All that I had was a property of Animal.Legs which was not overridden in the Dog class. The timed code tested looping over 50 million instances each of the Animal and Dog classes and performing the following line of code:
foreach(Animal animal in animals)
{
int i = animal.Legs;
}
or
foreach(Dog dog in dogs)
{
int i = dog.Legs;
}
What I found was that over the span of running each of those loops for 50 million items and averaging each one over 10 different runs, the Animal typed loop took approximately 1.054 seconds and the Dog typed loop took approximately 1.037 seconds. The difference between the two and then apportioned to each of the 50 million items is hardly worth the math (0.00000000034 seconds per item) to consider it a problem for the average LoB application that we see written.
So I figure that there may be something to a deeper nesting of inheritance so I added a Shepherd type (inherits from Dog) and a GermanShepherd type (which inherits from Shepherd surprisingly enough). None of these classes override the Legs property on Animal. I performed the same test again, this time comparing Animals to GermanShepherds. The average run time for the Animal loop was 1.038 seconds and the average for the GermanShepherd loop was 1.018 seconds. The difference (0.0000000004056 seconds per item) was once again indiscernible for the average LoB application.
Finally I wanted to try something with some different types in the loop. I compared the standard loop for Animals against the following loop against a list of GermanShepherd objects.
foreach(Animal animal in germanShepherds)
{
int i = animal.Legs;
}
Of all the tests this is the one that I expected could possibly run with a noticeable difference. Like the others, 50 million items and 10 sets later the Animal loop averaged 1.028 seconds and the Animal against German Shepherd loop averaged 1.018 seconds. Once again the difference per item (0.0000000001872 seconds) is negligible.
So out of all that I've proven that the points I made in the discussion about inheritance performance degradation were well founded. Inheritance does not appear to have any significant effect on the performance of simple code. Now, these are trivial examples and they may have some flaws, but the discussion I was having was centered around the idea of inheritance and simple properties causing problems.
As I've noticed with people from certain technical backgrounds, performance is made a paramount and primary concern. While I agree that performance can be a concern, and that basic performance measures are needed, I can't buy into a though process that makes performance an overriding concern *until* it has been proven to be an overriding problem.
Performance can reach the forefront of my thought process in two scenarios. First, performance is a stated requirement of the application acceptance. In that case I'd still defer the performance question until it has been proven that it can't be met. The second situation is where performance is obviously not acceptable. User style testing by a developer that is only just bearable is probably a sign that performance concerns should start rising up the list of risks. While in the conversation that triggered this whole thought process we hashed out the system usage numbers and the rough estimates were only about 3000 hits per day. Finding that out in the conversation told me that this was never going to be an issue regardless of what any research found.
Please don't take these test results as gospel. They were hacked together in a short period of time and didn't test a very good spread of situations or concerns. For me it was more about satisfying curiosity in the simplest way possible.