Sunday, 18 November 2007

The Three-Headed Product Owner

Note: Following is the ScrumAlliance version of my September post re-SCRUM Product Owner. The version below has been edited and published by the ScrumAlliance on 13th Nov here.

The Three-Headed Product Owner

My company had a fairly good transition to Scrum. The team adapted well to the change and we all felt very lucky with how well things were going. Even so, when my colleague and I got back from our Certified ScrumMaster course, we were amazed by how easy it was to spot some little problems that had previously gone unnoticed. It was immediately obvious to us that, though we had a product owner, he was “missing” in many fundamental ways.
We weren’t the only ones who noticed this. A week after we returned from training, the team mentioned the same problem at our retrospective meeting. Clearly, our product owner, who was also the product manager, was not doing what the team needed and expected him to do. We decided that we needed a commitment from someone to really take on the product owner role. But who?
The product manager was not very interested in “driving” the team. This was evident from his recent acceptance of a number of features that clearly were not complete because of debug information popping up everywhere on the screen. We had a senior manager who was very supportive about Scrum but he was too busy to commit more than 25 percent of his time. We weren’t in a position to hire someone to do the job either. It soon became obvious that I had to do something myself. I volunteered to be product owner for the team.
I am a technical guy, not a salesman or marketing guru. I could commit to being there for the team, but wasn’t sure I had the point of view the team needed in a product owner. Luckily, we’ve been able to think outside a strict interpretation of Scrum and take three important steps that have helped me be the kind of Product Owner the team needs.
Step 1. Direct Meetings
Thanks to my recent ScrumMaster training and some reading I had done on my own, when I took over as product owner my understanding about Scrum had reached the level where I could look after the already prioritized and estimated product backlog and organize the review and planning meetings.
In the beginning, I felt a bit unprepared, but I dove right in anyway. Right after I took the position, I created a proposed list of product backlog items for the next sprint and presented them to the team the same day. I started calculating the completed story points and told the team that I would sit with them during the sprint and be ready to answer questions and execute acceptance tests when asked to do so.
The team never mentioned it, but I sensed that they might have been a bit worried about my ability to provide user feedback. Yet, at the very next retrospective meeting the team reported that the problem with the missing product owner had been pretty much solved.
Step 2. Form a Customer Team
We’re a product company that has always been driven by the sales team—they historically had specified the features that need to be developed based on the sales they wanted to complete. I come from a technical background. How could I provide feedback for the team that would come from a sales point of view? How could I be sure which features were the most valuable to our business? I couldn’t. Not by myself. Yet I was the product owner.
To give the project the correct perspective, we formed a customer team that includes a product manager who is good at spotting market trends and knows the competition, the senior manager I mentioned previously (who makes most of the decisions regarding features priority), a member of the pre-sales team who receives a lot of customer feedback, and me. We meet together periodically to answer any outstanding questions, to turn feature requests into user stories and add them to the backlog, and to assign and prioritise based on benefit, penalty, risk, and cost. I am the sole point of contact for the development team. When a question arises, I consult with at least some of the other customer team members to arrive at an answer the represents the customer team’s point of view.
Step 3. Create User Proxies
The customer team improved things for the development team. However, other departments began to feel as if they had no mechanism to provide us with their feedback. We were inundated with feature requests from our support and services departments and had quite a few from sales and marketing as well. We needed a way to deal with those and still make sure the team always worked on the highest priority items.
About that time I read about user proxies. They seemed to be the solution to our problem. Now, the other departments maintain prioritised lists of feature requests. Twice a month, they give us an updated list, indicating any changed priorities and added or dropped features. The customer team reviews the lists and balances these needs against the other items in the backlog before setting the final priorities.
Are Three Heads Better than One?
Having one product owner who is supported by a customer team and user proxies works for us. But let’s look at whether it satisfies the key components of an effective product owner.
A basic knowledge of how software is developed and deployedCheck. Coming from technical background and knowing quite well all the technologies involved, I more than met this criterion.
An active stakeholder managementWe think we’re doing the best we can. Organizing the customer team meeting and collecting feedback from other departments might be the best you can do in a product company. Of course we would love to be able to receive feedback directly from the users, but right now it seems like we have some way to go before this could be achieved.
A thorough understanding of customer needs Yes, for the most part. Understanding the needs of over three hundred customers is always going to be a challenge. We get feedback from every single department that communicates with clients. Since each of these departments interacts with many different client levels, from decision makers to end users, we should be getting a good picture of client needs. We also have data available from customer satisfaction surveys and training feedback that we use in customer team discussions. Most, if not all, of the customer team members also sit in the review meeting and take part in deciding if a story is done.
After reading a number of books on Scrum and attending ScrumMaster training, I wanted to do Scrum as close to the books as possible. However, in our real world situation, it wasn’t feasible to find a single product owner who satisfied all of the necessary criteria. After looking at the situation we took a three-pronged approach: 1) A product owner who could take part in the planning and review meetings, update the product backlog, and help the team to get their answers 2) A diverse customer team and 3) User proxies to help the team make informed decisions when prioritising the product backlog. Will it work for other teams? Who knows? Inspect and adapt!

SQL Server Recursion

Have you ever come across a problem where you need to traverse a tree and MS SQL Server does not allow more than 32 level of recursion? I often work with trees and this is a common problem I need to solve. I can actually remember at least four occasions in which I needed to solve it so I thought if I blog the solution at least I will know where to look for it instead of reinventing it again ;)
The idea is not new I guess but probably not the one you would want to implement in SQL. First step is to create a “list” – a table which has a column for status so you can filter out the nodes you have already visited. This table will also need to have any primary keys or significant data you can’t do without depending on your specific task. My pick usually is an in memory table because I almost every time have two integers and a bit field. So with 17 bytes per row even with 100k rows the memory taken is still 1.62MB which should be alright for everyone these days. Of course if you’re dealing with a lot bigger data volumes you may want to go for a temp table.
My example below is based on traversing a tree or a branch starting from certain tree node and visiting all child nodes to construct a list of values which are later one updated with a single update statement in the big data table.
Step 1 – The list
So I start by declaring my “list”:

-- create the in memory table here
DECLARE @list table (nodeId int, metaId int, done bit)
DECLARE @curNID int -- current nodeID
DECLARE @cnt int

Node Id is my key field here and you can add PRIMARY KEY if performance isn’t good enough, meta ID is the filed I want to update back in the big table and the done field is how I filter the nodes I already visited.
As you notice there are a few more declarations here. The curNID (short from current node id for the curious ones) is keeping my key field in the loop, and cnt is just a temporary variable to store the global @@rowcount.
Next step is to insert the initial node details so that’s a simple insert statement:

-- insert the initial values
INSERT INTO @list VALUES(@nodeID, @metaID, 0)
SET @curNID = @nodeID

The @nodeID and @metaID presumably come from the stored proc argument list. And here I also set mu current node id to be the initial value.
And here comes the loop.

SET @cnt=1
WHILE @cnt>0
-- get next unprocessed
SELECT top 1 @curNID = nodeId
FROM @list
WHERE done<>1


IF @cnt>0
-- this inserts the set of child nodes
CASE WHEN metaID = 0 THEN defaultMetaID
FROM bigDataTable
WHERE theParentNodeID = @curNID

-- update in the list that it is done
UPDATE @list
SET done=1
WHERE nodeId=@curNID

Briefly we run the loop until every row in the table gets its done field updated to 1. In the loop we pick top 1 of the not done rows and insert all its children nodes in the list with done set to 0. There is a bit of logic also in the case if you need to do that case gives you a lot of options. Finally before going back to check the while condition we update the row we worked with so it is no longer selected for processing.
Finally we need to update the values in the big table:

UPDATE bigDataTable
SET big.MetaID = list.MetaID
FROM bigDataTable big
INNER JOIN @list list ON big.theNodeID = list.nodeID

As you can see this is also achieved through a simple update statement.

So overall I think this doesn’t look too scary, does it?