I was asked to speak at the University of Bath a few weeks ago about my experience of how Microsoft Consulting Services approaches software engineering. It hasn’t been that long since I finished my degree but when talking to my old lecturer I realised that the way I look at projects has changed considerably.
It’s been five months since I finished working on the Eye on Earth project but it was a brilliant example for my talk as we came up with a few simple methods of keeping the project agile while enforcing good practice and discipline.
As with most projects I’m involved in, this was a UX driven project. We spent some time with the customers to understand their needs, developing personas and scenarios to articulate them. From these we derived requirements and created wireframes. We were using the beta of Expression Blend 3 which gave us a great opportunity to try out SketchFlow. This was a great experience as it meant the customer could ‘interact’ with our wireframes. The scenarios were then broken down into development tasks and work items.
We ran a series of 4-week iterations comprising of three weeks development and one week of stabilisation. At the start of each iteration we looked at the development tasks and broke them down into work items, with no more than 4 hours per work item. These were then assigned to developers. The work items were linked to the scenarios so we could always check the context of the part we were building.
After the development cycle was complete, we all chipped in for a bug bash. These bugs were triaged and allocated to the team for fixing.
To ensure that the code we checked in to TFS was of a high standard, we used several check in policies (including a couple of custom ones that I put together).
Each project imported a custom targets file which enforced source analysis (style-cop) and code analysis (FX-cop) rules on the projects. We decided that a debug build would still run the analysis but report the errors as warnings. This meant that the developers could see potential problems but could still work normally and run the solution. When the solution was built in release mode, the errors would show up and the build would fail. As a check-in policy meant that only release builds could be checked in, this ensured that all code checked in was source and code analysis compliant (hence why the CA policy mentioned earlier was a backup!)
Here’s a snippet of the targets file:
<Import Project="StyleCop\4.3\Microsoft.StyleCop.Targets"/> <PropertyGroup> <SourceAnalysisEnabled>true</SourceAnalysisEnabled> </PropertyGroup> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <StyleCopTreatErrorsAsWarnings>false</StyleCopTreatErrorsAsWarnings> <SourceAnalysisTreatErrorsAsWarnings>false</SourceAnalysisTreatErrorsAsWarnings> <StyleCopForceFullAnalysis>true</StyleCopForceFullAnalysis> </PropertyGroup>
<Import Project="StyleCop\4.3\Microsoft.StyleCop.Targets"/>
<PropertyGroup> <SourceAnalysisEnabled>true</SourceAnalysisEnabled> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<StyleCopTreatErrorsAsWarnings>false</StyleCopTreatErrorsAsWarnings> <SourceAnalysisTreatErrorsAsWarnings>false</SourceAnalysisTreatErrorsAsWarnings> <StyleCopForceFullAnalysis>true</StyleCopForceFullAnalysis>
</PropertyGroup>
Here’s the bit of code for the Get Latest policy:
public override PolicyFailure[] Evaluate() { int pending = PendingCheckin.PendingChanges.Workspace.Get(VersionSpec.Latest, GetOptions.Preview).NumOperations; if (pending == 0) { return new PolicyFailure[] { }; } else { return new PolicyFailure[] { new PolicyFailure("Please perform a Get Latest before checking in.", this) }; } }
TFS was set up so that a continuous build was run on every check-in. If multiple check-ins took place then the builds were queued so we could easily find the cause of any issues. A dedicated build machine downloaded the entire solution and built it from scratch each time. This may seem excessive but it ensured we were always starting with a clean slate.
Later on in the project, Dominic Green worked some Azure magic so that the solution was automatically deployed to the cloud after a successful build. This meant we could check in our code, and 30 minutes later test it in a production environment!
Looking back on the project, I find it hard to believe that a few simple practices helped us out so much. At times, the developers found it frustrating that the builds took a while or that they couldn’t check in for some reason but it was worth it in the end.
Throughout the six months, we had to keep the project agile – we had many requirement, design and even team member changes to deal with, not to mention the five or six beta technologies we were using.
Our few rules kept us on track and we ended up with a successful project and only two build breaks in the entire six months!