Fear and Loathing
Gonzo blogging from the Annie Leibovitz of the software development world.
-
Have you tried out Planning Poker?
I'm a big fan of the Planning Poker technique for estimating. It basically is a process where everyone in the room gets together with cards and estimates effort for user stories. Each card has a number on it (a modified fibinacci sequence) of 0, 1, 2, 3, 5, 8, 13, 20, 40, and 100. Then everyone reveals their estimate for a given story at the same time. Any estimates on the fringe are challenged and justified and an estimate is arrived, then the process is repeated for the next user story.
Mike Cohn and the Mountain Goat Software people have put together a fabulous website to solve a problem with planning poker, that is the one of remote users. It doesn't help planning poker if the users are off in another city so planning poker, the site solves that. You create an account (free and only requires 4 fields of information) and log in. Then someone creates a game and everyone participates online. Its a great way of doing this, and you can export the results to HTML and CSV at the end of the session. There's even a 2 minute timer that you can invoke once you've discussed enough about a story and a ready to estimate. Some people have even used it internally by everyone bringing their laptops to the session rather than even using physical cards.
So check out Planning Poker for yourself as it might be useful in your next planning session. Here are some screenshots that walk you though creating user stories and estimating them with the planning poker site.
When you log into the site you can view the active or complete games. Complete games can be re-opened if you need to do them across a few days:
To create a new game, click on the link and fill in the name and description. If you have stories already ready to estimate, you can paste them into the field here from a spreadsheet. The first row should contain the field names.
To add a story for estimating, just enter it in the form As a/an <role>, I would like to <function> so that <business value>. There's also room for notes that might be something you want to capture but make it light, this isn't the place for requirements gathering details here.
Once you've added a story, the estimating game begins. Select a card from the screen for that story.
Then you can accept or play again with that estimate. Your estimate shows up along with others (if they're logged into your game).
If you were wrong with your original estimate or there's debate on something and you really do agree it's larger/smaller, click play again and select a different estimate.
When all the estimates are done and the game is complete you can view all of the estimates online.
Finally if you want to take this information elsewhere, you can export it HTML for viewing/publishing/display or to a CSV file for importing into another tool.
Note that Planning Poker doesn't work very well under IE7 on Windows XP but the guys are working on it. I flipped over to use Firefox for the screenshots and use FF when I do my sessions using the tool.
-
Feeds not working on weblogs.asp.net
Not sure what the problem is but if you subscribe to my feed (via my feedburner url, http://feeds.feedburner.com/bsimser) you may have noticed that the feeds around here haven't been updated. In fact there's no new feed since May 1st.
The feedburner feed is stagnant but what's more disturbing is that feedburner is working correctly, it's the source of the feed from Community Server and weblogs.asp.net that isn't updating. I checked the private feed (sans feedburner) and it also shows May 1st as the last post.
I sent a note off to the weblogs.asp.net guys but haven't heard back. I'm posting this here in the hopes that someone on weblogs.asp.net is seeing the same problem (and it's not just me) and maybe something gets done about it.
Maybe I forgot to pay the rent on my site? ;)
Update: I've been clicking on other peoples RSS link and not seeing items from the past week for many blogs. So either the feeds are not getting through on my end (DNS problem? I doubt it) or something is messed up on weblogs.asp.net/Community Server.
-
Source Code Posted for SharePoint Forums Web Part
As I continue to cleanup my projects on CodePlex, I've posted the latest version of the source code for my SharePoint Forums Web Part. This is version 1.2 that was released in August (better late than never?).
If you're interested in contributing/enhancing the project please do so. Right now I'm juggling a bunch of projects with lots of team members so it might take some time to get you added to the team if you're interested. If you are interested in modifying the codebase then Scott Hanselman has a great blog entry here on creating patches. You can simply submit a patch file to me (via email) and I'll add it to the codebase. This way you don't have to sign up for a CodePlex account and go through setting up all those tools. Your choice but please consider contributing to the project.
The source code does not include the 2007 version as that will be released under the Community Kit for SharePoint project (CKS) which also lives on CodePlex (surprise surprise). I'm donating the 2007 version to CKS but in reality just simply having it hosted under that project. It'lll be the same Web Part however hopefully we'll have some more bodies working on it under CKS.
You can download the source code directly from here (sort of direct since direct file links don't work anymore on CodePlex) or through a TFS client (Teamprise, Team Explorer, etc.) if you're signed up on the site via the latest change set here.
-
Change Sets Restored on CodePlex for Tree Surgeon
For those that have been playing along, CodePlex suffered a bit of a hiccup awhile ago and some data was lost.
The Tree Surgeon project was one of the casualities (along with some of my other projects). The CodePlex team got the work items restored, but the change sets and source tree was lost. Luckily we had two backups, the zip file and I had several local copies of it on various hard drives and backups. I've rebuilt the latest change set on Code Plex so you can hook up and grab the source if you're a member of the team to work on things (or just grab the latest change sets as we get more work done).
I'm just spending some time tonight to update other projects and get new or updated source code uploaded to CodePlex so watch for more announcements over the next few days.
Thanks!
-
Generic List Converter Snippet
A useful little class that you might find you need someday. It converts a weakly-typed list (like an IList of items) into a strongly typed one based on the type you feed it.
It's super simple to use. For example let's say you get back an IList<People> from some service (a data service, web service, etc.) but really need it to be a List<People>. You can just use this class to convert it for you.
I know, silly little example but just something for your code snippets that you can squirrel away for a rainy day.
1 public class ListToGenericListConverter<T>
2 {
3 /// <summary>
4 /// Converts a non-typed collection into a strongly typed collection. This will fail if
5 /// the non-typed collection contains anything that cannot be casted to type of T.
6 /// </summary>
7 /// <param name="listOfObjects">A <see cref="ICollection"/> of objects that will
8 /// be converted to a strongly typed collection.</param>
9 /// <returns>Always returns a valid collection - never returns null.</returns>
10 public List<T> ConvertToGenericList(IList listOfObjects)
11 {
12 ArrayList notStronglyTypedList = new ArrayList(listOfObjects);
13 return new List<T>(notStronglyTypedList.ToArray(typeof(T)) as T[]);
14 }
15 }
-
6 Months of Sprints - A Visual Record
I thought I would start off the week by airing my dirty laundry, that laundry being one of the projects I'm Scrum Master and Architect on.
It's been 6 months of month long iterations and the project is currently on hold as we shifted resources around to a fewer "higher" priority ones. I'm looking back at the iterations and the burndown charts that we pulled out (via Scrum for Team System).
It's not pretty but it's real and it's interesting to see the progress (or sometimes lack of it) along the way. Here we go...
Sprint 1
The sprint starts and we're not off to a bad start. In fact, it's one of the better sprints we had, even if it was the first. A little bit of churn the first few days but that's normal. In fact it was a collision between myself and the PM who decided to enter all the tasks again his way. After a few days we got that part straightended out and the rest of the sprint seemed to go pretty well. I was pretty happy so far.
Sprint 2
Another sprint that didn't go too badly. The team (myself and one developer) had some momentum and we were moving along at a nice pace. However technical debt built up already and we ended the sprint with about 40 hours of work left. Still overall I was pretty happy and we seemed to have got our stride. We also picked up a new team member so there was that integration that had to happen, but it worked well for the team.
Sprint 3
Third sprint, 3 months into the project and we were moving along. Sometime around the middle of the sprint we were going like gangbusters and realized we were going to end early. That's the big dip around the 17-20th of November 2006. Once we got back on the Monday (the 20th) we decided to add more work to the sprint, otherwise we were going to be twiddling our thumbs for 2 weeks. It worked out well for this sprint as we finished without too much overhead (about 12 hours but some of that was BA or QA work which didn't directly affect the project).
Sprint 4
Ugh. This is ugly but bonus points for the first person to know why (other than who was on the team). The main cause for the burndown to go flatline here is the Christmas. Yup, with people on holidays and not really wanting to end the sprint in early January right when everyone got back, we decided to push the sprint out a little to make up for the lost time over the Christmas season. In addition to this, the first week of this sprint one of the main developers came down with the flu and was out of commission for almost a whole week. That crippled us. By the 22nd or 23rd of January we decided we had to drop a whack of scope from the sprint (which is the sudden drop at the end you see) and we would have to make it up the next sprint, somehow. Even with that adjustment we were still running about 225 hours over at the end of the sprint. Not a good place to be to start your next iteration.
Sprint 5
Doesn't look good for the team that was doing so well. This sprint started off with a couple of hundred hours of deferred backlog items, then ballooned up with more technical debt and decomposition of new tasks. The team was larger now but we obviously took on more than we could chew. In fact I remember going in saying that but I was shot down by certain PTB that said "it'll work itself out". Don't believe them! If your burndown charts are looking like this the first week in (and you can tell that the first week in) you'll certain to not succeed on an iteration. Hands down. I like to take a CSI approach to iterations, let the facts show what's going on not peoples opinion. If your burndown is burning up, you need to make adjustments and not "ride it out" because unless you have magical coding elves come in late at night (and I'm not talking about geeky coders who like to keep odd hours) then you're not going to make it, and it's pretty obvious.
Sprint 6
This sprint was just a death march. 800 hours of work which included 80 hours for a task we outsourced to a different group (which really turned into 200 hours of work as that person just didn't turn in any kind of idea for how long it would take) and probably 200 hours of technical debt that's been building for 4 months. We actually got a lot done this sprint, about 200 hours worth of work which isn't bad for 3 developers, 1 QA, and 1 BA but it looks bad here.
This is how we ended the project until it went stealth. No, we didn't shut the project down because the progress was horrible. As I said, it slipped down the priority chain and we, as an organization, felt it was better to staff a project with 4-6 developers and bring it home rather than 2-3 developers keeping it on life support.
Hopefully this reality trip was fun for you and might seed a few things in your own iterations. Overall a few things to keep in mind on your own projects following Scrum:
- No matter what tool you use, try to get some kind of burndown out of the progress (even if it's being drawn on a whiteboard). It's invaluable to know early on in a sprint what is going on and where things are headed.
- If you finish a sprint with backlog items, make sure you're killing them off the first thing next sprint. Don't let them linger.
- Likewise on technical debt, consider it like real debt. The longer you don't pay it down, the more interest and less principle you end up paying and it will cost you several times over.
- If you're watching your sprint and by the end of the first week (say on a 2-3 week iteration) you're heading uphill, put some feelers out for why. Don't just admire the problem and hope it will go away. It might be okay to start a sprint not knowing what your tasks are (I don't agree with this but reality sometimes doesn't afford you this) but if you're still adding tasks mid-sprint and you're already not looking like you're going to finish, don't. It doesn't take a genius to figure out that if you can't finish what you're got on your plate you shouldn't be going back to the buffet.
- Be the team. Your team is responsible for the progress of the sprint, not one individual so you succeed as a team and fail as a team. Don't let one individual dictate what is right or wrong in the world. As a team, if the sprint is going out of control, fix it. If a PM says "don't worry" when you can see the iceberg coming, don't sit back and wait for it to hit, steer clear because you know it's coming.
-
Welcome to Magrathea
Our 11th episode of the best damn podcast in the greater Calgary area, Plumbers @ Work, is now online.
In this episode, we talk about Silverlight, the Calgary Code Camp, Silverlight, GoDaddy refunds, Silverlight, Rhino Mocks, Silverlight, the Entity Framework, Silverlight, and Halo 2. We finally wrap up the show by talking about Silverlight.
You can view the details and links for this podcast here or directly download the podcast into your favorite ad-ridden, battery draining, lightweight, podcast player here.
Magrathea? Maybe I should have called this post "09 F9 11 02 9D 74 E3 5B D8 41 56 C5 63 56 88 C0" just to get in the game.
-
INVEST in your stories with SMART tasks
An oldie but a goodie that I thought I would share with the class.
For user stories:
Independent
Stories are easiest to work with if they are independent. That is, we'd like them to not overlap in concept, and we'd like to be able to schedule and implement them in any order.
Negotiable
A good story is negotiable. It is not an explicit contract for features; rather, details will be co-created by the customer and programmer during development. A good story captures the essence, not the details. Over time, the story may acquire notes, test ideas, and so on, but we don't need these to prioritize or schedule stories.
Valuable
A story needs to be valuable. We don't care about value to just anybody; it needs to be valuable to the customer. Developers may have (legitimate) concerns, but these framed in a way that makes the customer perceive them as important.
Estimable
A good story can be estimated. We don't need an exact estimate, but just enough to help the customer rank and schedule the story's implementation. Being estimable is partly a function of being negotiated, as it's hard to estimate a story we don't understand. It is also a function of size: bigger stories are harder to estimate. Finally, it's a function of the team: what's easy to estimate will vary depending on the team's experience.
Small
Good stories tend to be small. Stories typically represent at most a few person-weeks worth of work. (Some teams restrict them to a few person-days of work.) Above this size, and it seems to be too hard to know what's in the story's scope. Saying, "it would take me more than month" often implicitly adds, "as I don't understand what-all it would entail." Smaller stories tend to get more accurate estimates.
Testable
A good story is testable. Writing a story card carries an implicit promise: "I understand what I want well enough that I could write a test for it." "Testability" has always been a characteristic of good requirements; actually writing the tests early helps us know whether this goal is met. If a customer doesn't know how to test something, this may indicate that the story isn't clear enough, or that it doesn't reflect something valuable to them, or that the customer just needs help in testing.
For tasks:
Specific
A task needs to be specific enough that everyone can understand what's involved in it. This helps keep other tasks from overlapping, and helps people understand whether the tasks add up to the full story.
Measurable
The key measure is, "can we mark it as done?" The team needs to agree on what that means, but it should include "does what it is intended to," "tests are included," and "the code has been refactored."
Achievable
The task owner should expect to be able to achieve a task. Anybody can ask for help whenever they need it; this certainly includes ensuring that task owners are up to the job.
Relevant
Every task should be relevant, contributing to the story at hand. Stories are broken into tasks for the benefit of developers, but a customer should still be able to expect that every task can be explained and justified.
Time-Boxed
A task should be time-boxed: limited to a specific duration. This doesn't need to be a formal estimate in hours or days, but there should be an expectation so people know when they should seek help. If a task is harder than expected, the team needs to know it must split the task, change players, or do something to help the task (and story) get done.
From Bill Wake XP123.com
-
Reconsituting Domain Collections with NHibernate
We ran into a problem using NHibernate to persist our domain. Here's an example of a domain object; an Order class with a collection of OrderLine objects to represent the line in each order placed in the system. In the system we want to be able to check if an order exists or not so we use an anonymous delegate as a predicate on the OrderLine collection:
7 class Order
8 {
9 private IList<OrderLine> Lines;
10
11 public Order()
12 {
13 Lines = new List<OrderLine>();
14 }
15
16 public bool DoesOrderExist(string OrderNumber)
17 {
18 return ((List<OrderLine>)Lines).Exists(
19 delegate(OrderLine line)
20 {
21 if (line.OrderNumber == OrderNumber)
22 return true;
23 return false;
24 }
25 );
26 }
27 }
28
29 class OrderLine
30 {
31 public string OrderNumber;
32 public int Quantity;
33 public string Item;
34 public double Cost;
35 }
This is all fine and dandy but when we reconsistute the object from the back-end data store using NHibernate, it blows its head off with an exception saying it can't cast the collection to a list. Internally NHibernate creates a PersistantBag object (which implements IList) but can't be directly cast to a List, so we can't use our predicate.
There's a quick fix we came up with which is to modify the DoesOrderExist method to look like this instead:
16 public bool DoesOrderExist(string OrderNumber)
17 {
18 List<OrderLine> list = new List<OrderLine>(Lines);
19 return (list.Exists(
20 delegate(OrderLine line)
21 {
22 if (line.OrderNumber == OrderNumber)
23 return true;
24 return false;
25 }
26 );
27 }
This feel dirty and smells like a hack to me. Rebuilding the list from the original one when we want to find something? Sure, we could do this and cache it (so we're not recreating it every time) but that just seems ugly.
Any other ideas about how to keep our predicates intact when reconsituting collections?
-
GoDaddy and their crazy accounting system
I got an email from GoDaddy today, where most of my domains are hosted, about a reduction of ICANN fees. I must say that GoDaddy is absolutely brilliant in crediting me the overpayment I've made as a result of the reduction of the fees:
Dear Bil Simser,
The Internet Corporation for Assigned Names and Numbers (ICANN®) recently agreed to reduce their Registrar Transaction Fee from $.25 to $.22. What does this mean for you?
Good news. You have been credited $.03/yr for each domain name you registered or renewed dating back to July 1, 2006* -- $.15 has been placed into your Go Daddy® account with this customer number: 9999999.
Your in-store credit will be applied to your purchases at GoDaddy.com® until it's gone or for up to 12 months, whichever comes sooner. If you have any questions, please contact a customer service representative at 480-505-8877.
As always, thank you for being a Go Daddy customer.
Sincerely,
Bob Parsons
CEO and Founder
GoDaddy.comWow. 15 cents for all my domains. What should I buy with this winfall first? A new laptop? A 42" LCD TV? I understand that it's the law and without sending this note out, I would probably be complaining about them stealing my $0.15 but it's akin to a bank sending you a cheque for $0.02 interest and is somewhat funny (even if others think its not)