Subscribe
Sign In
|
 Wednesday, August 27, 2008
While reading Chuck's excellent post on the value of both knowing your problem domain before tackling your problem and checking in often, I found myself nodding profusely. I love it... he states: Write tests first! Do it! DO IT NOW. I'd like to add: NOW CHECK IN!! I wish I could...often my problem is *when* to check in. I know I have to do it often, but when? After I finish a task? What if that is a few days away? What is a reasonable amount of time? When I say task I am referring to a TFS work item. Since we are a scrum shop now it is actually a sprint backlog item. I have TDD at my side, and we have CI builds at work. Why not check in after every passing test cycle? To be honest, checking in after every passing test feels like I'm wasting more time doing the check in dance, than I am saving time. Having said that, it appears that this is a widely accepted approach. Martin Fowler suggests otherwise. It appears he is task oriented when it comes to checking in: Now I take my working copy and do whatever I need to do to complete my task. This will consist of both altering the production code, and also adding or changing automated tests. ... With a good build, I can then think about committing my changes into the repository. I think it feels more natural that way. Its like a 'reward' for finishing a task. The feedback loop advantage of TDD isn't hindered by the longer feedback time of a CI build so much. However, I'm often left with sprint backlog items whose scope might mean that I'm programming for days on end. This is the root of check in evil for me. If a work item is so broad that it will take days to complete, then the impetus to check in is diminished such that I can get so wrapped up in the detail of the problem that I will forget to check in. And that's my fault. I'd love to blame it on the process but I can't. Sure the analysis of the product backlog item could have been more thorough, but we don't want to get too far into implementation details at that point or else we waste the whole teams time. I should have the sense upon undertaking a task that has been written up as "Import old Foo data for Foo version 2", to split it up in to its discreet units of work. There are SQL tables to write create scripts for. There is a transformation layer to design and implement. There is deployment to think about. Acceptance testing. So on and so forth. It is *my job* to define the goals on the road to task completion. So I come full circle and refer back to Chuck's post and the idea that we should think about what we are going to do before we go and do it. Coding from hip make pain for coder </grunt> Accept a task and analyse the problem domain. Divide it up into check in sized work items. Eat. Repeat.
 Friday, March 14, 2008
Hey y'all, long time no see. Life has thrown me a few curve balls which impeded my blogability, but rather than boring you with details lets just get into straight into it.
Recently I've had a few queries regarding a check in policy I eluded to in this post. Today I hope to clarify how one might go about implementing a check in policy which ensures that Option Strict is turned on for VB projects.
Rather than rehashing a perfectly good walk through, I suggest you read this article from MSDN to get the basics of Check In Policy creation.
Once we have our check in policy project and have derived a class from Microsoft.TeamFoundation.VersionControl.Client.PolicyBase it is time to start overriding the behaviour of the base rule. Imports Microsoft.TeamFoundation.VersionControl.Client
<Serializable()> _
Public Class OptionStrictPolicy
Inherits PolicyBase
Once we are over that little hurdle we want to:
* Get the set of pending changes that have been selected by the user to check in
* For each pending change determine the project file that the change belongs to
* For each VB project determine if Option Strict has been turned on
* For each project that hasn't got option strict turned on, create a policy warning.
For extra fun I'll do this all with VS2008 & VB9. I love my C# but to be honest VB9 kicks its ass when dealing with XML.
1: Get the set of pending changes that have been selected by the user to check in
Everything from here on out extends the Evaluate method of PolicyBase. Getting the set pending changes selected by the user is a cinch. I've filtered by vb code files, but you could just as easily go for more file types. Public Overrides Function Evaluate() As PolicyFailure()
Dim pendingChanges = PendingCheckin.PendingChanges.CheckedPendingChanges
Dim vbCodeFiles = _
From c In pendingChanges _
Let extension = Path.GetExtension(c.FileName) _
Where extension = _VBFileExtension OrElse extension = _VBProjectFileExtension _
Select c.LocalOrServerFolder, c.FileName
2: For each pending change determine the project file that the change belongs to
This step is a little trickier and basically involves drilling up the folder structure until we find a project file, and then checking the project file for a compilation reference to the pending change. This seems like a good place to refactor into a recursive function...
*SIDE NOTE* Am thinking of starting a petition to all relevant Dictionary makers to make the word "Refactor" a real word. Whose with me?
I'm sure we are all capable of looking for .vbproj files recursively up the folder chain. However we do need to allow for the possibility that there may be two vbproj files in a folder and if so, is our pending change referenced by either of them? To do this I need to go through the project file looking for <Compile> tags that include my pending change. For example in C# we might do it like this var doc = XDocument.Load(XmlReader.Create(projectFilename));
var compileItems = from e in doc.Descendants()
where e.Name.LocalName == "Compile"
select e;
return (from c in compileItems
where c.Attribute("Include") != null && c.Attribute("Include").Value.Contains(filename)
select c).Any();
But since Im using VB today I can do it like this...
Dim doc = XDocument.Load(XmlReader.Create(projectFilename))
Return doc...<Compile>.@Include.Contains(filename)
Not bad...but for this to work I do need to import the namespace of the project file schema, since the syntax that allows for <Compile> is checking qualified names, not local names. Imports <xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3: For each VB project determine if Option Strict has been turned on
Once I have a list of projects that are loosely associated with a check in, I can easily check for the existence of OptionStrict tags in the vbproj file. OptionStrict still defaults to off, so a lack of OptionStrict tags implies the setting is OFF. However it is perfectly valid to have an OptionStrict tag that is set to OFF so I need to account for those. Private Shared Function IsOptionStrictOn(ByVal project As XDocument) As Boolean
Return project...<OptionStrict>.Value = "On"
End Function
4. For each project that hasn't got option strict turned on, create a policy warning.
Creating policy warnings is a breeze and you can return as many as you want, in this scenario I want to ensure that one is created for each project that is in violation of my rule. The final Evaluate function looks like this... Public Overrides Function Evaluate() As Microsoft.TeamFoundation.VersionControl.Client.PolicyFailure()
Dim pendingChanges = PendingCheckin.PendingChanges.CheckedPendingChanges
Dim vbCodeFiles = From c In pendingChanges _
Let extension = Path.GetExtension(c.FileName) _
Where extension = _VBFileExtension OrElse extension = _VBProjectFileExtension _
Select c.LocalOrServerFolder, c.FileName
Dim vbProjects = From c In vbCodeFiles _
Select GetProjectFile(c.LocalOrServerFolder, c.FileName)
Dim strictOffprojects = From p In vbProjects _
Where Not IsOptionStrictOn(p)
Dim policyFailures = New List(Of PolicyFailure)
Dim messageFormat = "Please turn option strict on in the project file: {0}"
For Each s In strictOffprojects.Distinct
policyFailures.Add(New PolicyFailure(String.Format(CultureInfo.InvariantCulture, messageFormat, s), Me))
Next
Return policyFailures.ToArray()
End Function
So there you have it, VB9 to make coding an Option Strict ON policy nice and easy. Seems appropriate doesn't it?
 Thursday, June 21, 2007
In my previous post I described how using some readily available tools and some simple conventions for work item creation can equip yourself with some excellent information about how your team works. In this post I intend to explore some of the custom queries that I have been asked to create in day to day life as a TFS consumer.
One such request was for a query that will tell you, of all the work items you have delegated to others, which ones are outstanding. To achieve this follow these steps to create a TFS query. Having done that you will want to provide the following filters:
- Team Project = @Project
- AND Created By = @Me
- AND Assigned To <> @Me
- AND State = Active
- AND Area Path Under <AreaPath>
- AND Iteration Path Under <IterationPath>
By changing the "AND State = Active" to be "AND State <> Active" one could query the completed and closed tasks. Optionally you could filter out Scenarios using the 'Work Item Type' field. Don't forget that team explorer can easily dump into and out of Excel which can be handy if you need an earbashing list. The query options straight out of the box are 'good enough' for most situations, and you don't have to write any code if that's not your thing.
For those of you wanting a little more than a simple query, e.g. you want parameterisation, I did find that creating your own TFS reports was a reasonably straight forward experience as well. The first thing to do is to create a report model on the TFS warehouse objects (TfsReportDS and TfsOlapReportDS by default). TfsOlapReportDS points to a SQL Analysis Services cube which the standard reports all use. One can spend more than a few hours just looking around in there, so consider yourself warned ;)
Creating the report model is easy enough, just browse to your TFS Sharepoint portal, and find the link to your Report server web interface (typically http://TFSServerName/Reports) and click on the TfsOlapReportDS of TfsReportDS link (the docs say you should favour the TfsOlapReportDS for reporting). Once there you can hit the generate model button and have it generate a reporting model for you. Then just click the link to report builder and start going nuts. I whipped up a non-parameterised report in under an hour that distilled the check-in history of an Area to look like an activity report, using all the wonderful comments our team had provided on each check-in, as a result of the check in policy.

As you can see I pulled in the change set details, the number of lines changed. Using a quick function on the max and min check in date would show how long the entire project took at a glance. Obvious improvements to this would be grouping by scenario and iteration. This report was brought to you courtesy of the Code Churn entity, which is useful for more than just this simple activity report. You can use code churn to ascertain the quality of your code as well.
By using the report designer in Visual Studio, you can start leveraging your SQL skills (of which I have very little) to create more elaborate reports, although I think I shall leave that as an exercise for the reader, rather than going into it here as the principle is largely the same. For further information on using the report services I can highly recommend Bob Meyers SQL Reporting Services blog and a book by Paul Turley, Todd Bryant, James Counihan, Dave DuVarney entitled Professional SQL Server 2005 Reporting Services for those who don't mind reading after a hard days coding.
In summary, developers often concentrate on making sure that each line they write is well crafted, and that's a good thing, so why not make check in time another opportunity to be efficient and useful instead of an inconvenience? There are benefits for developers and project leaders alike, and the key to finding those benefits is by having good data collected at check in time. The analysis tools provided by TFS are powerful enough to satisfy most needs, and if a SQL neophyte like me can whip up a semi-useful report in an hour, imagine what a SQL Jedi could achieve?
 Wednesday, June 20, 2007
In a previous post I described some of the simple things we have used at work to improve our TFS life as developers, and today I thought I would share some finer detail.
One of the single greatest tools I use to combat TFS weariness today is this fantastic outlook add-in by the SRL Team. It has changed the way our company works with TFS, I highly recommend installing it. In short you can create work items (tasks, bugs etc) from outlook items (emails, tasks etc) and also search TFS by keyword or ID.
Another tool of note, which aids those who need to access TFS reports and source on the run, is TeamPlain, which I use at home quite a lot. This gem provides a much better web interface for developers than the standard portal TFS currently provides. Whilst you can't do bulk checkouts very easily, simple one file check-ins/outs are quite doable. I find it particularly useful for creating work items and running reports when I don't have intranet access to work. It's so good, that Microsoft actually bought the company who created it, and is now a free download. Please note, this doesn't suddenly earn you a portal for non licensed developers – you will still need CAL's for users on TeamPlain.
The TFS Administration Power Tool is the only way to fly when you need to setup permissions for new TFS users in a hurry. It streamlines the task of setting up permissions for TFS, Share point and reporting services in one place. Perhaps its greatest feature that puts it over the line for hard core command line users is that you can easily make multiple changes at once. It also displays the activity log for all changes made, in case you need to blame somebody else for some poorly configured permissions. ;)
Lastly, but certainly not least, if you haven't already downloaded it, then do yourself the favour of getting the TFS Power Tools. For starters tftp.exe has some excellent command line functionality for managing all manner of day to day TFS tasks; tree clean, undo unchanged, to name but a few. There is a myriad of commands and it is very easy to pickup. Along with tftp.exe there is the check in policy pack which has some fairly common check in policy examples for you to utilise. If you want to implement your own custom check-in policies, it isn't hard and I suggest you have a look at Marcel de Vries primer on the topic.
On the topic of check in policy, we recently added one more to our front line against bad check-ins: for VB projects option strict must be turned on. <Cue-sniggers-from-the-C#-crowd/> I think it's imperative that any serious VB development be done with Option Strict on (and Option Explicit, but luckily the power of defaults has saved us here.) There was once a time when I thought the idea of duck typing and implicit casting was convenient and I'm certainly not proud of those days. Coming from a C programming background I should have known better, but I was well and truly caught by the Dark Side™.
There are few things worse than being asked to maintain some buggy code, that has Option Strict off, and after turning it on you get an error telling you that the amount of errors that can be displayed has been exceeded.
So how does this all help us to know ourselves better? Do some fancy add-ons to an already confusing product actually make project analysis any easier? The short answer is YES. Basically, the two things you need in order to make effective use of the TFS data warehouse are as follows:
- Some understanding of DML queries (I can tell you, my T-SQL chops are infantile at best)
- A solid set of data
By encouraging your team to create good check-in data with easy to access tools, querying TFS data becomes a much more fruitful experience. If you only have one task to check in against, then querying check-ins really isn't going to give you answers on how long a particular feature took to achieve. Conversely, if you have a rich source control history then ascertaining the amount of time a feature took to implement is a sinch. That's just the beginning; this data store can lead to all sorts of revelations about productivity and quality. It's all about granularity, and it's easy enough to provide. At work we use the following conversion to provide a decent work item tree:
- Product = Area
- Feature or functionality = Scenario
- Aspect of functionality = Task
- Development cycle (design, create, test etc) = Iteration
- Bugs are well, bugs of course.
Areas contain Scenarios, Tasks and bugs are assigned to Iterations. We create related work items from a Scenario when creating a new task or bug, so that they have some link. We don't really bother with Quality of Service or Risk items, but if you feel they apply to your product, by all means use them. We have started to store function specifications into TFS using this convention in order to kill the proverbial two birds. Firstly, it gives us a structured and consistent means of entering a function spec, and also provides a convenient skeleton to create work items from.
The net result is that if Mr. CEO would like to know how application X is coming along, we can immediately ascertain which scenarios have or haven't been satisfied (I.E % completion). If Mr. Lead Dev wants to know how many tasks to add to an Iteration, he can look up the project velocity report (a standard TFS report) to get a good idea of how quickly his team churns through tasks per day.
In my next post I will give some examples of querying against the TFS warehouse and how it can make your life a little easier when the boss starts asking the hard questions.
 Wednesday, June 06, 2007
We've been using Team Foundation Server for well over 12 months at my workplace, and it's been quite a journey. This post is the first in a short blog series about some of the different things we have come to use and some of things we don't bother with.
I honestly believe it has made us better developers in the process, if only for implementing a check in policy. Currently, we have a simple policy; we weren't looking for a mechanical office Nazi. Our implementation includes the following rules:
- Must provide some comments to accompany your check-in. Just some brief detail about the change set.
- Must associate the check-in with a work item, be it bug, task, scenario, quality of service or risk.
- Must enable code analysis on your project. Unfortunately we haven't been quite able to enforce turning all the CA rules on *yet*. However CA must be on with a few of the more important rule sets also enabled.
Summarizing your check in forces you to think about exactly what you are trying to achieve with your change set. It also proves invaluable when the proverbial chairman of the board wants to see an out-of-the-blue-activity-report on a particular project, as happened to us about a month ago. Obviously somebody could type "qwerty" and check in however, I think we can all agree a little bit of honesty with oneself can go a long way in this game.
TFS Work items are the end of To-Do's in code in my mind. I don't like seeing To-Do's in code because they are often little more than unheard cries for help. Unless you are using some proprietary software to aggregate your To-Do's solution wide, they are largely lost. Visual studio doesn't jam them in your face as you open a solution, so if you aren't looking for them, chances are you wont find them until you are deep in some other time consuming task.
A much better approach is to have a repository of things to do, and at some point decide who will do them, and when to do it. TFS provides this functionality in droves. For starters you can create TFS work items directly from your bug list. You can sort, report and assign work items to other members of your team. From the get go, you have everything you need to create and manage a to-do list. Iteration planning is obviously aided by this documented list of required bug fixes and 'version next' ideas, which augment the list provided by your user base.
Having a thriving list of work items means that checking in against a work item (and hopefully marking it as having been finished) completes the circle and provides yet more valuable history information. By enforcing this action at check in time, we ensure we have at least some premeditation of our change set going on. Additionally, we can easily report on change sets for a particular task, and quickly determine just how long it took to achieve a particular feature or solve a particular bug. Once again, such info is invaluable for iteration planning.
Enabling Code Analysis is still, IMHO, a personal choice. I believe it should be on in some capacity, but blindly following code analysis rules as some sort of mantra to better development is foolish. Take unit testing for instance. Some popular testing frameworks would like to see your unit tests as public, non static subs. However, FxCop will invariably spot that no class instances are required for this function, and promptly tell you to mark your test as static (or shared in VB). The CA acolyte who changes his or her entire test suite to static methods will invariably find that the entire suite fails to run. I work on a policy of turning on every CA rule available and if it becomes apparent that a certain rule is demanding something unreasonable for the situation, I turn that particular rule off. FxCop is not perfect. Neither are you, but together we can achieve greatness.
By taking advantage of TFS check in policy, and by embracing some of the simpler aspects of TFS life (creating work items) you will find you can learn all manner of information about how your teams actually works, which can often mean the difference between success or failure. To know your enemy is to conquer them: and we are our own worst enemy.
In my next post I will elaborate on other means by which work items can be organized and created, and some examples of simple TFS queries to get some finer detail about what is going on.
© Copyright 2008 Jim Burger
|