Fear and Loathing
Gonzo blogging from the Annie Leibovitz of the software development world.
-
The "need" for Scrum Tools
I got an email from Mike Vizdos about a blog post he was writing up. Mike is the author of a blog called Implementing Scrum. It's a great blog where he posts a cartoon to describe a Scrum concept in a very acceptable way (see below for an example). It's an excellent communication mechanism. I find myself printing out Mike cartoons all the time and putting them up around my office (aka the Scrum room) to hit home the Scrum concepts to people.
Mike recently blogged about Scrum tools and mentioned my own Scrum Tools Roundup post (thanks Mike!). His post talks about the value (or lack of) Scrum tools and I partially agree with him. There are times I've said exactly "Please make sure you update tool X so that we can report our burndown to [someone who is not even in the room]."
I personally just print out the burndowns (we use the Conchango Scrum Plugin for VSTS) and put them on the wall along with a splash screen for the project and the post-it notes that represent the tasks (our task board). We still use VSTS for tracking, but the wall is the conversation piece. Each morning (currently 2 Scrums soon to be 3) we get together and do our daily standup with everyone sort of huddled around the "wall" (a giant 14 foot wall I have in my office that holds all the post-its). People talk about what they did and what they're working on, move stickies around, and all is well.
I agree with Mike in that if you're burning 50% of your time in a project on maintaining a tool, a backlog in a tool (VSTS, spreadsheet, or otherwise) then you're spending about 49% too much time. However as the Scrum Master I keep the tool up to date, the PM uses it (constantly) to report progress to a heavenly body, and I personally try to get the team to not get hit too much with any administrivia tasks. The most any team member should do is to a) change the state of a task to In Progress or Done and b) knock down the work remaining on tasks as they're doing them say from 8 hours to 4 (or 0).
That shouldn't take more than a few minutes a day before the daily standup. Really.
If you're donig more than for sure you're spending too much time and you should read Implementing Scrum on a more frequent basis (and maybe change how you work).
-
A Plugin for a Plugin
Isn't life amazing? These days you can download a plugin (ReSharper) and write a plugin for it (VstsUnit). That's what my fellow plumber James Kovacs did. He was using VSTS for his unit testing but unfortunately the built-in Test Runner for ReSharper didn't support VSTS unit tests, only csUnit/NUnit. So armed with the ReSharper SDK and a few brain cells to kill, he went off to build a plugin for a plugin. Basically it allows you, with ReSharper installed, to run Visual Studio Team System based tests via the test runner. I personally use TestDriven.NET which supports anything you throw at but if you're a ReSharper guy and are stuck with VSTS rather than NUnit for your testing tools, take a look at this freebie. You can download it here.
-
What a craptastic day
And here I was going to blow away a few holes in some drug lords in Crackdown this morning but was faced with this:
Guess it's a call to 1-800-4MY-XBOX and an exchange (or buy a new one which I might have to do). The catch? I think I'm about 1 month over my warranty. I swear to god they must have a timer chip in the XBox as it's been a little flakey the last few weeks and now this.
Sucks to be me.
-
Team City and Windows, no documentation and not a happy combination
Nothing like Friday morning to inflict more pain and suffering from our continuous integration process. Recently we purchased a gaggle of ReSharper licenses from JetBrains. For whatever reason, the person making the deal decided to buy the bundle that included Team City (apparently it's cheaper to buy the bundle with TC than to buy individual ReSharper licenses, but the logic behind that move escapes me). I've seen Team City in the past and it looked interesting but without a demo you can get your hands on, I didn't give it much thought.
Since it's touted as the "Most Intelligent Integrated Team Environment" I went to try this out as a potential replacement for our CruiseControl.NET setup. Boy, was that a mistake.
The install went pretty smoothly and I tried it out on my laptop with a local setup to start. I have to admit that TC has a nice setup. Install software, open site in browser, start configuring projects. That was kind of the first problem. After the install the system just sat there. I wasn't sure if it was done or not or what I was supposed to do next. I took a look in my Start menu for perhaps a Team City menu with at least a README or something but that was a barren sea of nothingness. Finally I just launched my browser and pointed it to the port I installed TC on and was presented with a screen to enter license information. Aha.
Next was setting up a test project. I didn't want to get into a full blown, download source code task just yet so created a new project that I had a solution file for and found that Team City supported MSBuild. So I just pointed it at the .SLN file hoping it would work. Nope. It complained about some node that it didn't support or some such silly thing. I know .SLN files can be launched with MSBuild (we do that now with CC.NET) but looking at the errors, it appears that TC has some kind of wrapper around MSBuild so I guess it can only support specific types of MSBuild files.
This is where the next problem came up. Documentation. There was no documentation shipped with the product and going online there's only a FAQ with a few gems of wisdom available. There is a forum, but you know what's thats like. Post a message, wait a few days, etc. There are places to submit bugs and questions and the response can be pretty good, but again why isn't there any documentation to get setup? The only documentation there is seems very primitive, as in, it replicates what you see on the screens but really doesn't do a good job on what to do when something goes wrong.
Giving up on the MSBuild configuration to launch a solution file, I changed my test project to something that uses NAnt. That seemed okay but then the agent didn't understand what NAnt was and again I went digging to find out what was needed (besides picking it in the list of build configurations). I stumbled across (on another FAQ pages) that you need to create an environmental variable (in TC) called NAntHome and point it to the root where NAnt is installed. Fair enough. Once I figured out where to put this information (in a config file, hey I thought we don't have to setup config files with TC?) it was able to recognize where NAnt was and could launch my project. Looked good but I didn't set it up to run any tests so it was just doing the build for me.
Next was to get rid of the userid/passwords. Again on the FAQ it says you can change over to NT Authentication and sure enough, on the TC install there's an option to flip it over. You do it and it tells you that you're about to be logged off. No problem. When the page reloads, it's now telling me to create a new Administrator account (which I had already done when it was first setup). However I can't seem to create an account using DOMAIN/USER now using any kind of combination of entries.
I submitted a "HELP ME" message to try to revert back to non-NT authentication and got the response but now I'm stuck. Maybe my concept of "using NT authentication" is flawed (at least for this product). I assume that I can turn it on and users won't have to enter their usernames or password to access the system. If I try to add a user to the system while I have it up in non-NT mode, I could try to enter DOMAIN/USER for the name but password is a mandatory field and I'm certainly not going to enter my password here nor ask other people to give me theirs (or get them to create users for themselves which seems like a silly thing). If I flip it over to NT authentication I'll be at the same place again.
Support wasn't very helpful here. The first response was:
"NT auth enables authentication using users registered on the machine where TeamCity is installed (system users)."
Reading between the lines means I have to add a user manually to the machine from my domain? I tried to clarify what I was looking to accomplish, namely creating new users in TC with NT names. The next response was even less than useful:
"Users are created in the user management on your machine, please refer to your OS documentation for details."
Yeah, right. Of course that's what I'm asking. I like totally asked you how to create users in Windows. Again, no documentation on how this mechanism works or what to do here.
Finally I decided to hook it up to source control and pull down a copy of the system. Another problem is that the current release (1.2) only supports CVS, Subversion, Perforce and VSS. No support for TFS. More Googling and I found a EAP release with TFS support and downloaded it. Now I'm one to go in and just run an installer, but if there's a README file or something (especially telling me about upgrades) I read it in case I need to do anything special. Nope. Not in this case so I just ran the installer.
Now I'm currently looking at a Tomcat screen (their web server for TC) producing an error and lots of Java gobbly-gook in the log file saying a bean can't be created or something. Not a happy camper with the "upgrade". I'm sure I could just blow away the previous version with a full uninstall and install the TFS build, but what if I had real projects configured here? I've submitted a message to the guys with my details and hoping they'll get back to me but it doesn't look very good for this product. Here's the initial response to my submission:
"Passed on to the developers, support team doesn't deal with the EAP versions."
Okay, I can understand that. EAP versions are new(er) and maybe not supported by the main people. Still the response is basically useless to me along with the tool at this point. I'm not even going to both submitting a question about how do I use MSBuild with a solution file. I'm sure the answer will be something like "Configure MSBuild on your server" or some other nonsense.
Team City looks like a great product and I'm sure in the Java world and on a Linux or Mac setup it might be the cats meow. I personally just found it painful to get things to work on Windows and .NET projects. CC.NET isn't a picnic for setting up and adding new projects (compared to Team City) but at least it always works and there is documentation out there and a pattern to doing things. Once you setup one project you can practically setup any other.
Basically someday I would hope to see CC.NET implement some of the things TC does, although I'm sure that's not doable from a competition perspective (free vs $$$). Setting up CC.NET and it's projects can be a pain. I have the process down to a few hours for a new CC.NET setup from scratch (that includes setting up all the tools, downloading, etc.) and new projects can be added in under an hour (less if there's a smart build file in the project). Pulling from Subversion, VSS, and TFS is a no-brainer in CC.NET these days and works flawlessly. There are some GUI tools out there that will edit the CC.NET config file for you, but they're in the embryonic stage and it's easier to just edit the files with Notepad++.
Maybe someone will come up with modification to the CC.NET web dashboard to make it a little smarter like TC and allow you to at least create projects, etc. from it but until that happens we're regimented to editing XML files and such (which isn't a horrible thing).
-
Is there a cloning machine in the house?
What a crazy month it's been and I'm just still trying to catch up here. Work is insane as I'm playing lead architect on 3 projects, ScrumMaster on those 3 projects, planning for 2 new projects (including putting on my infrastructure hat to do a 2000 user Vista upgrade). All this while trying to juggle the MOSS 2007 release of my SharePoint Forums, the first release of the Knowledgebase, SharePoint Builder, a SharePoint community site, and get ready for the MVP Summit coming up in a couple of weeks (plus a couple of other projects in the wings that are just starting). I seem to have burnt my candle on both ends, went to the cupboard and used up all the other candles there and still haven't finished. Not sure when I'm going to sleep this weekend but it'll be an interesting few days.
-
VB.NET Version of Web Service Software Factory now available
In addition to the 800,000 RSS feeds I subscribe to I also keep an eye on downloads from Microsoft. This is so I don't miss anything that happens to come out and become the new SharePoint or something. However monitoring downloads from Microsoft is like herding cats. They come in spurts and don't make much sense to me.
For example recently the following downloadables got updates: Guidance Automation Toolkit, Guidance Automation Extensions, and the Web Service Software Factory. What's odd about it is that they were updated in the last day or so, but are still versions from back in June 2006. So what? I'm getting updates because someone edited an entry on a site somewhere. Or is there a real update here or not.
You think something like this was easy. Notify people when a "new" version is available, not just an update to the page that contains the old version. But then I'm prolly asking too much.
BTW, the Visual Basic.NET flavor of the Web Service Software Factory (the title of this blog post) is new and available here.
-
A few good men (or women)
I'm looking for a few good men (or women, but no lizards unless you're that cool one from that Geico commercial). I need a few good experienced intermediate to senior .NET developers in the Calgary area for projects. Short term, long term, or full time, it's flexible but availability needs to be immediate.
As for qualifications a good, solid working base of .NET 2.0 is required along with good development practices (layered applications, separation of concern, thin UI, that kind of stuff). We use the following tools, technologies, patterns and practices so you need a good knowledge of some (or all) of these:
- Scrum
- .NET 2.0
- Composite Application UI Block (CAB)
- Enterprise Libraries
- Smart Client Software Factories (SCSF)
- Test Driven Development (TDD)
- Visual Studio Team System
- Design Patterns/Software Factories
- Domain Driven Design (DDD)
If you're qualified, interested, and avaialble and in the Calgary area feel free to email me with a note about yourself (attaching your CV is optional) and we can chat. Thanks!
This blog entry was brought to you by the letter N, H, L and the number 7.
-
SharePoint Code Camp this Saturday
Please join Robert Holmes and other presenters at an all day event in Waltham, MA on Saturday, February 24th, from 8:30 to 6:00 PM presenting all aspects of the new SharePoint products, WSS 3.0 and MOSS 2007. The main focus will be on the new aspects of the product line, however we will start with an introduction to Team Services (WSS), and work up from there, and our goal is for anyone present for the whole day will leave with the knowledge of what is possible with the product, and the ability to sit down and get started on a new implementation of a SharePoint solution, or extend an existing one. You can review the schedule to see what specific areas are of interest to you, or else spend the whole day and learn all there is to learn.
You can find the code and slides here: http://www.sharepointguy.com/SharePointCodeCamp07/default.aspx.
You can see the content only site, no registration, at: http://www.sharepointguy.com/SharePointCodeCamp07/default.aspx.
Enjoy!
-
ASP.NET 2.0:1, Bil:0
I just spent the better part of the evening chasing down the dumbest error I've ever seen. ASP.NET decided to litter my web.config file in a web app I'm setting up with a reference to stdole.dll (not a web dll nor is it anything I reference directly or even need). I finally tracked down someone who came up with a resolution and explanation here.
Of course I couldn't figure out which assembly that was causing the problem, so I just threw my GAC'd version of stdole.dll into the bin folder of the website. I'm using a few dlls including Enterprise Libraries, but nothing fancy. In any case, if you ever see this crazy message when deploying a website:
Parser Error Message: Could not load file or assembly 'stdole, Version=7.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.
You might want to check out the link above. Either a) manually edit the web.config file [which I'm sure I'll forget one of these days during deployment] or b) toss the file into your bin directory or c) hunt down the culprit and set "Specific Version" to false.
Man, what a @!#!!!%!&! PITA this stupid, stupid, stupid thing is. I'm not sure if I'm peeved at MS for coming up with such a wonderful design, or for me for killing my brain all night over it. Now I feel as foolish as this and this.
Sigh, I need a hug (or a beer, not sure which).
-
Versioning the Microsoft way... with NAnt
I was inspired by a recent blog entry by Jeff Atwood here about how Microsoft versions their products and how the build number is significant. I thought it would be good to post a walkthrough of how to build your own versioning system ala Microsoft but using NAnt. I'm sure some budding geek out there could convert this to MSBuild, but you know my love of that tool so NAnt it is.
First off, NAnt has a great facility for generating that AssemblyInfo.cs file that every project has. It's the asminfo task and basically looks like this:
<?xml version="1.0"?>
<project name="Test" default="UpdateAssemblyInfo">
<target name="UpdateAssemblyInfo">
<asminfo output="AssemblyInfo.cs" language="CSharp">
<imports>
<import namespace="System.Reflection" />
<import namespace="System.Runtime.InteropServices" />
</imports>
<attributes>
<attribute type="AssemblyTitleAttribute" value="ClassLibrary1" />
<attribute type="AssemblyDescriptionAttribute" value="" />
<attribute type="AssemblyConfigurationAttribute" value="" />
<attribute type="AssemblyCompanyAttribute" value="" />
<attribute type="AssemblyProductAttribute" value="ClassLibrary1" />
<attribute type="AssemblyCopyrightAttribute" value="Copyright (c) 2007" />
<attribute type="AssemblyTrademarkAttribute" value="" />
<attribute type="AssemblyCultureAttribute" value="" />
<attribute type="ComVisibleAttribute" value="false" />
<attribute type="GuidAttribute" value="f98c8021-fbf1-44ff-a484-946152cefdb8" />
<attribute type="AssemblyVersionAttribute" value="1.0.0.0" />
<attribute type="AssemblyFileVersionAttribute" value="1.0.0.0" />
</attributes>
</asminfo>
</target>
</project>
This will product a default AssemblyInfo.cs file that looks like this:
using System.Reflection;
using System.Runtime.InteropServices;
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.42
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
[assembly: AssemblyTitleAttribute("ClassLibrary1")]
[assembly: AssemblyDescriptionAttribute("")]
[assembly: AssemblyConfigurationAttribute("")]
[assembly: AssemblyCompanyAttribute("")]
[assembly: AssemblyProductAttribute("ClassLibrary1")]
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2007")]
[assembly: AssemblyTrademarkAttribute("")]
[assembly: AssemblyCultureAttribute("")]
[assembly: ComVisibleAttribute(false)]
[assembly: GuidAttribute("f98c8021-fbf1-44ff-a484-946152cefdb8")]
[assembly: AssemblyVersionAttribute("1.0.0.0")]
[assembly: AssemblyFileVersionAttribute("1.0.0.0")]
Notice however a few things. First is the Guid. We had to hard code that which might be okay, but lets dig into NAnt scripting by replacing it with a real Guid. NAnt also has the ability to let you write embedded code (C#, VB.NET, etc.) via the <script> task, so let's write a small task to do that. We'll just have it generate a new Guid and set a new custom property in the NAnt script that we'll use in our asminfo task. Create a property in the NAnt script to hold our Guid:
<property name="project.guid" value="f98c8021-fbf1-44ff-a484-946152cefdb8" />
Then use that property in our GuidAttribute:
<attribute type="GuidAttribute" value="${project.guid}" />
Finally here's the task to generate a Guid via NAnt (make the default UpdateAssemblyInfo task dependent on this one):
<target name="CreateUniqueGuid">
<script language="C#">
<code>
<![CDATA[
public static void ScriptMain(Project project) {
project.Properties["project.guid"] = Guid.NewGuid().ToString();
}
]]>
</code>
</script>
</target>
Great. We now have a NAnt script that will generate a new version file with a unique Guid everytime. Next we want to tackle the versioning issue.
As described by Jensen Harris here, the Microsoft Office scheme is pretty simple:
- Take the year in which a project started. For Office "12", that was 2003.
- Call January of that year "Month 1."
- The first two digits of the build number are the number of months since "Month 1."
- The last two digits are the day of that month.
Using this we'll need to setup a couple of properties. One is to hold the year the project starts, the other is the build version we want to set:
<property name="project.year" value="2003" />
<property name="build.version" value="1.0.0.0" />
Now we could write a lot of NAnt code as there are functions to manipulate dates, but it's much easier using the <script> task and some C#. Here's the NAnt task to generate the build number using the Microsoft Office approach:
<target name="GenerateBuildNumber">
<script language="C#">
<imports>
<import name="System.Globalization" />
<import name="System.Threading" />
</imports>
<code>
<![CDATA[
public static void ScriptMain(Project project) {
Version version = new Version(project.Properties["build.version"]);
int major = version.Major;
int minor = version.Minor;
int build = version.Build;
int revision = version.Revision;
int startYear = Convert.ToInt32(project.Properties["project.year"]);
DateTime start = new DateTime(startYear, 1, 1);
Calendar calendar = Thread.CurrentThread.CurrentCulture.Calendar;
int months = ((calendar.GetYear(DateTime.Today)
- calendar.GetYear(start)) * 12)
+ calendar.GetMonth(DateTime.Today)
- calendar.GetMonth(start);
int day = DateTime.Now.Day;
build = (months * 100) + day;
version = new Version(major, minor, build, revision);
project.Properties["build.version"] = version.ToString();
}
]]>
</code>
</script>
We get the version in the NAnt script as a starter (since we're only replacing the build number) and then assign values to it (they're read-only in .NET). Then this is written back out to the property as a string.
If this is run today (February 17, 2007) it's been 49 months since the start of 2003 and today is the 17th day. So the build number is 4917.
Here's the finaly output from this NAnt script:
using System.Reflection;
using System.Runtime.InteropServices;
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:2.0.50727.42
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
[assembly: AssemblyTitleAttribute("ClassLibrary1")]
[assembly: AssemblyDescriptionAttribute("")]
[assembly: AssemblyConfigurationAttribute("")]
[assembly: AssemblyCompanyAttribute("")]
[assembly: AssemblyProductAttribute("ClassLibrary1")]
[assembly: AssemblyCopyrightAttribute("Copyright (c) 2007")]
[assembly: AssemblyTrademarkAttribute("")]
[assembly: AssemblyCultureAttribute("")]
[assembly: ComVisibleAttribute(false)]
[assembly: GuidAttribute("a6e7ff79-63ba-443f-8bc3-0c4b43f43ffe")]
[assembly: AssemblyVersionAttribute("1.0.4917.0")]
[assembly: AssemblyFileVersionAttribute("1.0.4917.0")]
And here's the full NAnt script:
1 <?xml version="1.0"?>
2 <project name="Test" default="UpdateAssemblyInfo">
3
4 <property name="project.guid" value="f98c8021-fbf1-44ff-a484-946152cefdb8" />
5 <property name="project.year" value="2003" />
6 <property name="build.version" value="1.0.0.0" />
7
8 <target name="UpdateAssemblyInfo" depends="CreateUniqueGuid, GenerateBuildNumber">
9 <asminfo output="AssemblyInfo.cs" language="CSharp">
10 <imports>
11 <import namespace="System.Reflection" />
12 <import namespace="System.Runtime.InteropServices" />
13 </imports>
14 <attributes>
15 <attribute type="AssemblyTitleAttribute" value="ClassLibrary1" />
16 <attribute type="AssemblyDescriptionAttribute" value="" />
17 <attribute type="AssemblyConfigurationAttribute" value="" />
18 <attribute type="AssemblyCompanyAttribute" value="" />
19 <attribute type="AssemblyProductAttribute" value="ClassLibrary1" />
20 <attribute type="AssemblyCopyrightAttribute" value="Copyright (c) 2007" />
21 <attribute type="AssemblyTrademarkAttribute" value="" />
22 <attribute type="AssemblyCultureAttribute" value="" />
23
24 <attribute type="ComVisibleAttribute" value="false" />
25
26 <attribute type="GuidAttribute" value="${project.guid}" />
27
28 <attribute type="AssemblyVersionAttribute" value="${build.version}" />
29 <attribute type="AssemblyFileVersionAttribute" value="${build.version}" />
30 </attributes>
31 </asminfo>
32 </target>
33
34 <target name="CreateUniqueGuid">
35 <script language="C#">
36 <code>
37 <![CDATA[
38 public static void ScriptMain(Project project) {
39 project.Properties["project.guid"] = Guid.NewGuid().ToString();
40 }
41 ]]>
42 </code>
43 </script>
44 </target>
45
46 <target name="GenerateBuildNumber">
47 <script language="C#">
48 <imports>
49 <import name="System.Globalization" />
50 <import name="System.Threading" />
51 </imports>
52 <code>
53 <![CDATA[
54 public static void ScriptMain(Project project) {
55 Version version = new Version(project.Properties["build.version"]);
56 int major = version.Major;
57 int minor = version.Minor;
58 int build = version.Build;
59 int revision = version.Revision;
60
61 int startYear = Convert.ToInt32(project.Properties["project.year"]);
62 DateTime start = new DateTime(startYear, 1, 1);
63 Calendar calendar = Thread.CurrentThread.CurrentCulture.Calendar;
64 int months = ((calendar.GetYear(DateTime.Today)
65 - calendar.GetYear(start)) * 12)
66 + calendar.GetMonth(DateTime.Today)
67 - calendar.GetMonth(start);
68 int day = DateTime.Now.Day;
69 build = (months * 100) + day;
70
71 version = new Version(major, minor, build, revision);
72 project.Properties["build.version"] = version.ToString();
73 }
74 ]]>
75 </code>
76 </script>
77 </target>
78
79 </project>
Enjoy!