Saturday, August 09, 2008

No Personal Backlog!




Naturally, we will assign tasks to team member and mark as owner. We will give a good naming of this action: Resource management. Within traditional project management, one of the things we most focus on is the resource management and tracing. Yes, I agree. The resource is really important, and we definitely should concern the ROI. But we need to consider the granularity of resource. Otherwise, we will be lost. Although you know every resource usage, that doesn't mean you ship your feature in time. And if you focus on resource management too much, believe me, it's easy to be failed in software development. Because you would be easily ignore "Technical Debt", "Team Building", "Delivery", although you still have good reasons to business and management team in that time. So what? Reasons and reports do not mean working software.

Scrum, is the agile methodology I experienced most. It defines three roles, PO, Scrum Master, Scrum Team. And actually the three roles are one, because if one fails, then all 3 roles fail. The self-managing Scrum team is always the goal we fight for.

That's why we always emphasis team rather than individual team member in Scrum. So "No Personal Backlog"! Personal backlog is good for management team to know every resource's status. But it's too bad for the team! Member will say, "At least I finished my items." Yes, you had a bad member, and you lost a potential good team.

And that's why I do not like some commercial/free Scrum project management software. Because it does do the personal backlog.

From Henrik Kniberg's slides on Agile Conf 2008, you also can consider following list as bad practices to team:
• Fixed roles
• Personal backlogs
• Not helping each other
• Personal incentive models
• Implementing all stories in parallell
• Management interference

Anyway, I believe good management team will focus on "Delivery", "Quality", "Team/Assets" rather than focusing on resource management too much. ROI always the first rule to business, but it is not short term!

Labels: , ,

Friday, March 21, 2008

Scrum with XP (eXtreme Programming) Style


From my perspective, Scrum is a methodology of management and it’s quite loose, but the XP is a methodology of development and it’s quite specific. So Scrum is like a framework, you could develop your concrete process. In Scrum, the approach you apply in the development is quite free. It depends on your team’s ability and tradition. So naturally, we will consider bringing some stuffs from XP into Scrum.

1. Split Sprint into small iteration
Normally, 1 sprint is 1 month within same length. But sometime, it’s still too long to control and commit. So we could split it into small iterations, like 1 week per iteration. But we still will have the Sprint planning meeting to pick up and definite the scopes of next sprint, then separate the sprint backlog items into iterations according to the priority. Meanwhile the iteration planning meeting will happen in every beginning of iteration. With small iteration, it’s easy to get the velocity more accurately.

2. User story and Spike in planning
Since the product/sprint backlog could be very simple, no information very detailed and deep, it’s difficult to estimate them sometime, especially when you are not sitting together with customers/users. So a good user story would be really helpful to understand the requirement and to estimate it. The communication is still needed, certainly.

The commitment is the target of the team, so it’s tough to estimate features when we get uncertain things within it. The spike supplies the practice guidance of this situation. We could do a spike before estimate the real work and to produce the possible solutions to PO. Then we could give the correct estimation when PO confirms the solution.

3. TDD and Refactory
No methodology guideline for how to code and test in Scrum. So normally we will apply TDD and Refactory into the development. Modern IDEs (Visual Studio for .Net, Eclipse for Java, Zend for PHP …) all provide these two functions.

4. Pair Programming
It’s difficult to involve Pair Working into scrum (I will detail this in following entry). But Pair programming is the best way to share knowledge and assure the quality.

5. Continuous Integration & BVT
CI could help us to find questions at the very beginning. BVT could ensure the major functionalities of the product won’t be broken. (Cruise Control is a good tool.)

6. Acceptance Tests
Acceptance is the guideline of the test cases. We also could create automation tests base on acceptance criteria.

7. Combined style of daily scrum and daily stand-up
In daily Scrum, team members will focus on 3 questions:
a. What I’ve done from last daily Scrum
b. What I will do in next
c. Any obstacles

Via these 3 questions, we could easily know the status. But it’s hard to know other team members’ ideas or comments. So we could plus another question:
d. Any feedbacks?

Although we plus this, we still need to focus and control the meeting time. If the feedback would be long, it should be discussed after the daily scrum.

Labels: , ,

Thursday, November 08, 2007

Does Developer in Scrum Have Any Specific Thing?



NO! I can say dev is same as Testers.

Today I just read an interesting thread. Some guy is looking for documents which mainly help to introduce the Scrum to developer.

Actually besides the Product Owner and Scrum Master, there is only one another role in Scrum. It is the “Team”! Within Scrum the team should be self-managed. In another words, there are three managers in Scrum — Product Owner, Scrum Master and the Team. And their one and only goal is achieving their commitments. The three roles do have different responsibilities, but act as a team role, the teammates in the team should share responsibilities of the same commitments. So no excuse to be blocked by specific as Dev or Tester, your goal is delivering your commitments. Dev and Tester should help each other to complete their tasks via focusing on different aspects which they are good at. Remember, your team should always act as one team, not individual team members. So never be blocked internally. Even when you think you are really blocked by your teammate, adjust youself or the team! If it’s kind of external blocking issue, ask Scrum Master for help.

But I still found one documentation which is pretty nice in that thread. “Scrum in five minutes”, http://www.softhouse.se/Uploades/Scrum_eng_webb.pdf.

Labels:

Tuesday, October 30, 2007

A Simple Comparison of Scrum and XP


Scrum


XP

Sprint(1 month)


Iteration(1-2 week(s))

Scrums


Stand up

PO


On-site customer

Product backlog

Story card

Release plan



Continuous integration



TDD (unit testing)



Test first (functional testing)


Retrospective



Demo



Both not have



Requirements analyze



Deployments



Bug process


Labels: , ,

Saturday, April 29, 2006

Router in Zend Framework

Core job of Router is very simple. Generate Zend_Controller_Dispatcher_Token instance for Zend_Controller_Front from request parameters. Default Router of Zend Framework parses request URI with url_rewriter. For example, http://your.com/test/add will be translated to a controller named TestController and an action method named addAction. These information and parameters are all encapsulated into a Zend_Controller_Dispatcher_Token instance.
After we know this, it is very easy to write our routers we expected. Such as, we need a NoRewriterRouter, if our web servers do not support url_rewriter. And we need a SubDirectoryRouter for virtual host subdirectory.
I've written a SubDirectoryRouter for Diggmore.



/**
*
* Sub Directory Router for diggmore
*
*/
class SubDirectoryRouter implements Zend_Controller_Router_Interface
{
//

private $sub_directory;

public function setSubDirectory($sub_directory)
{
$this->sub_directory = $sub_directory;
return $this;
}

public function route(Zend_Controller_Dispatcher_Interface $dispatcher)
{
//
$path = $_SERVER['REQUEST_URI'];
if (strstr($path, '?')) {
$path = substr($path, 0, strpos($path, '?'));
}
$path = explode('/', trim($path, '/'));

$start = 2;

if ($this->sub_directory != '')
{
//
$tmp = explode('/', trim($this->sub_directory, '/'));
$start = sizeof($tmp) + 2;
}
$controller = $path[$start-2];
$action = isset($path[$start-1]) ? $path[$start-1] : null;

$params = array();
for ($i=$start; $iisDispatchable($token)) {
throw new Zend_Controller_Router_Exception('Request could not be mapped to a route.');
} else {
return $token;
}

}

}


If your web server doesn't support url_rewrite, you may use codes below.


class NoRewriterRouter implements Zend_Controller_Router_Interface
{
//

public function route(Zend_Controller_Dispatcher_Interface $dispatcher)
{
//

$params = array_merge($_GET, $_POST);

$controller = $params['controller'];
$action = $params['action'];

unset($params['controller']);
unset($params['action']);

$token = new Zend_Controller_Dispatcher_Token($controller, $action, $params);

if (!$dispatcher->isDispatchable($token)) {
throw new Zend_Controller_Router_Exception('Request could not be mapped to a route.');
} else {
return $token;
}

}

}


You may think add some access control codes in router. But I think it is really not a good idea. Later I will write why.

Wednesday, April 26, 2006

Get InnerXML from XPathNavigator

First thanks a lot to my colleague, Eunge. He helped me to solve this problem. And it's really a long time I haven't written .Net codes.

Sometimes we need to get InnerXML from the XPathNodeIterator, especially when you are writing codes in XSLT.

If you are using .Net Framework 2.0, it's very easy. There is a property, InnerXML, in XPathNavigator, and from disassembled code we could find new functionalities of XMLWriter. But if you are using .Net 1.1, it's really not quite convenient to do it. There are two concrete classes which inherit abstract class XPathNavigator. One is XPathDocumentNavigator, the other is DocumentXPathNavigator. Two classes have an important difference. DocumentXPathNavigator implements the interface IHasXmlNode, but XPathDocumentNavigator not. That means if your XPathNavigator is DocumentXPathNavigator, it's easy to get InnerXML.


XPathNavigator nav = dom.CreateNavigator();
// do some select
String innerXml = ((IHasXmlNode)nav).GetNode().InnerXML;



Unfortunately, if your XPathNavigator is XPathDocumentNavigator, you have to write many codes. Codes below are sample.


public string GetInnerXML(System.Xml.XPath.XPathNodeIterator nodeIterator)
{
System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
System.Xml.XPath.XPathNavigator navigator = nodeIterator.Current;
System.Xml.XmlNode rootNode =doc.CreateNode(this.ConvertXmlNodeType(navigator.NodeType), nodeIterator.Current.Name, nodeIterator.Current.NamespaceURI);
doc.AppendChild(rootNode);
this.SetChildNode(rootNode, nodeIterator);
return doc.InnerXml;
}

private void SetChildNode(System.Xml.XmlNode parentNode, System.Xml.XPath.XPathNodeIterator parentIterator)
{
System.Xml.XPath.XPathNodeIterator childIterator = parentIterator.Current.SelectChildren(System.Xml.XPath.XPathNodeType.All);
while(childIterator.MoveNext())
{
System.Xml.XPath.XPathNavigator navigator = childIterator.Current;
System.Xml.XmlNode childNode = parentNode.OwnerDocument.CreateNode(this.ConvertXmlNodeType(navigator.NodeType), navigator.Name, navigator.NamespaceURI);
parentNode.AppendChild(childNode);
if(childNode.NodeType == System.Xml.XmlNodeType.Element)
{
this.SetChildNode(childNode, childIterator);
System.Xml.XPath.XPathNodeIterator attrIterator = navigator.Select("@*");
while(attrIterator.MoveNext())
{
System.Xml.XPath.XPathNavigator attrNavigator = attrIterator.Current;
System.Xml.XmlAttribute attribute = childNode.OwnerDocument.CreateAttribute(attrNavigator.Prefix, attrNavigator.LocalName, attrNavigator.NamespaceURI);
attribute.Value = attrNavigator.Value;
childNode.Attributes.Append(attribute);
}
}
else if(childNode.NodeType == System.Xml.XmlNodeType.Text)
{
childNode.Value = navigator.Value;
}
else if (childNode.NodeType == System.Xml.XmlNodeType.Attribute)
{
childNode.Value = navigator.Value;
}

}
}

private System.Xml.XmlNodeType ConvertXmlNodeType(System.Xml.XPath.XPathNodeType nodeType)
{
switch(nodeType)
{
case System.Xml.XPath.XPathNodeType.Element:
return System.Xml.XmlNodeType.Element;
case System.Xml.XPath.XPathNodeType.Root:
return System.Xml.XmlNodeType.Element;
case System.Xml.XPath.XPathNodeType.Attribute:
return System.Xml.XmlNodeType.Attribute;
case System.Xml.XPath.XPathNodeType.Text:
return System.Xml.XmlNodeType.Text;
default:
return System.Xml.XmlNodeType.Element;
}
}


Hope it is useful.

Thursday, April 20, 2006

My new English blog

I wanted to create a new blog for my English blog writing. After comparison of some solutions, I chose the service supplied by Blogger.com. So thanks a lot to google. I will post my English blog entries both in my Chinese blog (http://binzywu.com/blog) and the English one (http://blog.binzywu.com). But I think there will be more technical blogs in the English one.

Ok, Let me say Hello to World. And I hope I can be a excellent Programmer.