Saturday 15 May 2010

Easy Like Thursday Morning

So it was Thursday morning. I was tired and looking forward to the weekend (weekends are Fri/Sat here).  But I knew that if I didn't get this automated build going before the weekend arrived I just wouldn't be happy. All weekend it would be at the back of my mind  (not ncessarily because I'm that work-conscious or obsessed, I'm just built that way, maybe a little OCD or something I don't know)  So I eventually get things up and running, compilation, database build, test data set and all tests passing, green light - woo-hoo!  I'm proud of myself, got this licked before I clock off for the weekend - ain't it rewarding sometimes being a developer?  And it only took me about 4 days to do, and the nightly and weekly builds shouldn't be much more than...hold up.....lets go back a wee bit here....four days?  FOUR. DAYS.?!?

Yep, you read it right.  I was patting myself on the back after taking four days to get my automated build going.  Something that normally takes me a couple of hours, possibly a day at most if the build is convoluted and I'm having a bad day. And I'm self-congratulating after a P.B. four dayer?  And then it hit me like a dull blow to the back of the head. What the heck have I got to celebrate about?  You see I was too busy basking in the pleasure of achievement after so much pain of failure, to immediately realise how ridiculous this was.

Let me explain...

Recently I started my first proper working project in Studio 2010.  This is good for me, I'm usually at least a year behind the release year of Microsoft development products by the time I adopt/migrate. 

Warning: this maybe where the sun stops shining in this post.

To my dismay I'm using the Team System suite of tools (due to technology policy restrictions in my working environment) which means TFS, TF Build, SharePoint, etc.  I want to make it clear before I go any further that I'm not a Microsoft basher - goodness knows they don't need another to add to the pile and besides, I've been working with the MS toolset all of my professional life - I just normally prefer to use other tools to help me with my .NET development.

(For the record when I refer to TFS here I am talking about source/version control. I'm not sure if this is corrrect or if TFS is the full bhuna server product. That confuses me also, and life is simply too short for me to trawl through the MS marketing guff just to clarify). I've used TFS on a client site before when the client insisted on it.  I swore never again. Of course that was unrealistic working on service contracts but it did hurt at the time. A lot. Fowler's post on version control tools sums up nicely where TFS sits in the grand scheme of things, and I couldn't agree more.  Anyways, here I was again but I resolved to make the best of it.  It was the 2010 TFS - perhaps the newest version had improved? Bearing in mind I'm only 2 weeks into using TFS this time, here are the highlights of my experience so far, judge for yourself:
  • We had compatibility problems with TFS 2008 and TFS Team Build 2010, so we had to install TFS 2010 onto a new server before getting started proper;
  • There is a machine name size limitation on Server 2008 that gives you problems with TFS.  Sure, there is a warning when you apply your new machine name, but when you try to configure TFS it simply doesn't allow for you to point the TFS database to another instance of SQL Server.  Not until the machine has been re-christened at least (and not a hint of this being the reason in sight). There shouldn't be a warning, just a size limit on machine name and this could all be avoided;
  • Synchronisation.  This is what gave me the nightmares from my previous experience. Synchronising between your local workspace and the repository confuses the hell out of me with TFS.  Am I alone?  Well other team members were also having the same problems immediately.  On a colleague's machine on first checkin some files were deleted from the local workspace before commit.  Thats some files by the way.  Not all, only some.  I'm sure there was something common with why these files were deleted and not others, but I couldn't figure it out, and the developer in question was too busy crying into his hands to care;
  • TFS has the concept of site collections - source control paired with SharePoint to give a "single collaborative working environment" (or something to that effect). Each project therefore has a collection.  You can assign users to individual collections or as administrators to the whole site.  If you want to assign a user to a collection it seems you can only do this via Integrated Windows Authentication. A simple username and password would do for source control surely? Or even the option to choose between the two. Its not a biggy, but it doesn't encourage flexibility either;
  • And onto my favourite.  I spent a half hour on this one alone trying to figure out what was going on so that I wouldn't repeat the mistake again. I didn't, and I probably will. It's little ditties like this one that contribute to four days of suffering.  Another synchronisation issue (at least I think it was).  I had a folder in my solution that I couldn't remove.  Not a solution folder, but a folder that is normally created on the local filesystem by Studio.  I couldn't remove it or delete it as it was being held onto by another process.  Which was strange because there wasn't a local copy on the filesystem and there wasn't a copy in the repository.  So nevermind why I can't remove it or what process is holding onto it, why is it actually still there in the first place?? (By the way, can anyone explain to me what the difference is to Studio between remove and delete?  And then can anyone tell me why I should care?)
I'm sure the synchronisation issues are naivety, a simple lack of experience of the tool, that will dispate gradually with daily usage, but should it be this hard?  Subversion is a great example of how less is more with source control.  TFS seems to me to be a greate example of just the opposite. 

Onto TF Team Build. 
Getting the architectural proof-of-concept up and running was relatively straight forward (I like the RUP terminology for this one, although a friend and ex-colleague has a nice analogy and term for this). We are using ASP.NET MVC 2.0 for the first time and my experiences of this so far are very positive (I hope to blog about this soon).  So even with ASP.NET MVC, getting the build up and running with unit and integration tests passing locally using MSBuild was easy.  Then on to making this happen on the server...

It seems compiling and executing unit tests on the integration server using TF Team Build is straightforward. Building your database however is not.  I originally had a simple SQLCMD batch file which kicked off my database build and another for inserting my test data for data layer integration tests.  These batch files were reliant on relative paths and the batch files being copied and executed from a particular folder.  On the server, this was difficult to achieve.  It seems that Team Build likes moving and organising binaries in different folders for the purposes of build agents and controllers. And binaries seem to be treated differently from supporting files and folders.  No, I don't know why either. After what seemed like an eternity wrestling with the fact that the build on your server does not behave exactly like it does on you local development PC I eventually succumbed to Visual Studio's way of doing things with database development - database projects.

This is my first experience of database projects so I'm not 100% sure on them yet, but it did allow me to compile my database project like all other projects in my solution.  I initially thought this was good, but then I realised that compiling my database project didn't mean building my database as I interpreted it.  It meant "compiling" (deriving) my database scripts from the local copy of my database.  I still had to deploy my database.  Fair enough, my incorrect interpretation of the terminology.  Again, this was ok locally as accessing this deployment is a menu option of the Build menu for database projects, and as a project I can configure it to deploy after compiling when compiling and executing the whole solution.  But this is locally.  On the server, the behaviour is different....again. So I'm essentially back to square one because my server build is different from my local build.  I eventually resolved this issue after initially banging my soft head against a hard wall and then figuring out about XAML build templates with Workflow Foundation for executing server builds. Thats all great if you have XAML and/or WF experience, but if you are like me, its a pain that I don't feel I have to endure just to get something as fundamental as my automated build to behave on the server the same way it does on my development machine (cue more of head and wall meeting at substantial velocity).

By this point I stupidly think I'm close to getting a fully working build only to discover that something different and additional has to happen to populate my database with test data after deploying it.  Again, locally this is configured in the same way within Visual Studio under Database Test Configuration (its even on the same form!), but on the server build this is separate special case and has to be configured as such.  The end result is that I improved my understanding of XAML and build process templates, if only a little and at considerable pain, but I did get a populated database for my automated build.

This brings me up to my false moment of elation with my fully automated build for continous integration using VSTS on Thursday morning.  That took me a painful four days (did I mention that already?)

Earlier I referred to preferring other tools. I prefer them not simply because they are not Microsoft-based, but for a number of valid reasons:
  1. They are unintrusive - once my automated build is up and running, I only use CruiseControl (my CI tool of choice) for feedback. Thats the way it should be.
  2. They are cheaper -  the majority of the other tools I stated that I prefer happen to be open source based.  You can't get more cost-effective than free.
  3. They just work - I don't normally burn a week configuring fighting a CI build.  It usually takes about 2 hours.  Again, thats the way it should be.  My time would be better spent solving complex design issues, not scaffolding problems like these.  Another way of looking at it is this:- try using this as the justifiable reason next time you are late with delivery and see how much your customer cares about the complexities of your build tool.
I have 3 issues with the Microsoft toolset that get me really perplexed:
  1. The first is that this can so easily be avoided.  The other tools I have referred to and use don't make things this difficult, why should Microsoft?. 
  2. Do Microsoft use these afore-mentioned tools to support their own development?  The frequency of Silverlight releases makes me think otherwise (for the Silverlight team at least).  If they do, why aren't we furnished with great examples of complex and convoluted scripts and recommended configurations?  Convention over configuration seems to be the way to go.  Don't Microsoft agree here?
  3. Thirdly (and this is fundamental) what are Microsoft saying to their developer community?  It can't be that they don't agree with good practices such as Continuous Integration because recently I've come across some of their blurb about TDD and CI.  Making the compilation and deployment of your database part of the full CI build is essential, not optional or a pipe-dream.  Why then is it so convoluted (and/or secretive) to make it happen?
As I said before, I'm not anti-Microsoft (as much as this post indicates to the contrary) and maybe my limited understanding of these tools means that I may be getting things wrong or miscontrued. If I am, I welcome being informed of better ways to do this. Maybe I just never found them in my rush to get something working inside 4 days ;-)

(Its not me in the picture, personally I suspect its Tom Green. Thanks to FotoSearch for use of the image.)