Archive for the ‘Uncategorized’ Category

Learning together: Kanban and the Twelve Principles of Agile Software

Monday, June 21st, 2010

This post is a spin off from the recent Scrum/Kanban debate.  Not wanting to let a situation go to waste, it seems a good time to affirm shared values, which I do here via the Twelve Principles behind the Agile manifesto.  I’m grateful to Joshua Bloom for his excellent input.

Commentary on the twelve principles of agile software

Our highest priority is to satisfy the customer through early and continuous delivery
of valuable software.

Kanban: Check. We pull business value through the system, creating flow.  It should be recognized however that sometimes we create value by means other than delivering software (sometimes even by not delivering software!).  Furthermore, the act of improving the system generates value as it increases the capability of the wider organisation to generate value.

Welcome changing requirements, even late in development. Agile processes harness change for the customer’s competitive advantage.

Kanban: Check. We actively limit work-in-progress (WIP), facilitating late prioritisation and minimising the impact of change on lead times.  We actively work to clarify the customer’s priorities so that the team can manage risk by properly sequencing work.

Deliver working software frequently, from a couple of weeks to a couple of months, with a preference to the shorter timescale.

Kanban: Check. We make deliveries at intervals consistent with customer need and transaction cost.  We seek to minimise transactions costs attributable to the software development process, thereby making shorter delivery intervals economically optimal.  Highly advanced teams look towards continual deployment concepts to limit the inventory of complete yet not deployed software. We believe the best requirements come from software already depoyed being exercised by the customers/users. Achieving flow to the end-user generates higher value faster.

Business people and developers must work together daily throughout the project.

Kanban: Check. The development team and customer must learn together, in relation to both the problem domain and the delivery process.  The visual element of Kanban promotes transparency and creates triggers for customer interaction.

Build projects around motivated individuals. Give them the environment and support they need, and trust them to get the job done.

Kanban: Check. Build processes that respect individuals; empower them to learn and to improve the system.

The most efficient and effective method of conveying information to and within a development team is face-to-face conversation.

Kanban: Check. Visualization and models allow face-to-face conversations to scale effectively. Limiting WIP prompts teams to have conversations DURING difficulties.

Working software is the primary measure of progress.

Kanban: Delivered business value is the primary measure of progress.

Agile processes promote sustainable development. The sponsors, developers, and users should be able to maintain a constant pace indefinitely.

Kanban:  We work within and share responsibility for the capability of our system; sustained long-run capability cannot be built at the short-term expense of the individual.

Continuous attention to technical excellence and good design enhances agility.

Kanban: Check.  And we look to increase capacity by identifying and reducing the failure demand that results from inattention to quality.

Simplicity - the art of maximizing the amount of work not done - is essential.

Kanban: Check.  Furthermore we actively manage work-in-progress, minimizing work not finished.

The best architectures, requirements, and designs emerge from self-organizing teams.

Kanban: Check, and process too. Leaders (inside and outside the team) must foster emergence, not squash it.

At regular intervals, the team reflects on how to become more effective, then tunes and adjusts its behavior accordingly.

Kanban: Check. Continually even.

Conclusions

So there you have it, no fundamental conflict but a couple of clarifications and some changes of emphasis too.  It has to be said that these small differences do add up to a shift of mindset, but it is one that much of the Agile community has taken on board as a result of the increasing influence of Lean.

If I were to pick out a key thought it would be this:

The development team and customer must learn together, in relation to both the problem domain and the delivery process.

This lesson would be recognised by much of the Agile community I’m sure.

Prettyprinter for Pylons routes

Tuesday, December 15th, 2009

No, not described_routes, just something basic to plug a gap. For those suffering Rails-envy there’s no “paster routes” command, but it’s easy enough to use in the Paster shell:

bash-3.2$ paster shell test.ini
Pylons Interactive Shell
Python 2.6.2 (r262:71605, Apr 14 2009, 22:40:02) [MSC v.1500 32 bit (Intel)]

  All objects from encore.lib.base are available
  Additional Objects:
  mapper     -  Routes mapper object
  wsgiapp    -  This project's WSGI App instance
  app        -  paste.fixture wrapped around wsgiapp

>>> print mapper
Route name   Methods Path
                     /error/{action}
                     /error/{action}/{id}
home         GET     /
things       GET     /things
create_thing POST    /things
new_thing    GET     /things/new
thing        GET     /thing/{id}
...

It works by subclassing routes.Mapper (I have other reasons to do this which I’ll explain soon) and you’ll need to use this new Mapper in your config/routing.py.

That should be all you need to know. The code for the new Mapper class is below. Note: That second from last join() isn’t coming out very well - it has a backslash and an ‘n’ in it - honest!

Enjoy!

import routes.mapper

class Mapper(routes.Mapper):
    #
    # Pretty string representation - returns a string formatted like this:
    #
    #    Route name   Methods Path
    #                         /error/{action}
    #                         /error/{action}/{id}
    #    home         GET     /
    #    things       GET     /things
    #    create_thing POST    /things
    #    new_thing    GET     /things/new
    #    thing                  GET     /thing/{id}
    #
    #    etc
    #
    # Enter 'print mapper' in the paster shell to use it, or (TBD) run it via a
    # configured paster command.
    #
    def __str__(self):
        def format_methods(r):
            if r.conditions:
                method = r.conditions.get('method', '')
                return method if type(method) is str else ', '.join(method)
            else:
                return ''

        table = [('Route name', 'Methods', 'Path')] + [
            (
                r.name or '',
                format_methods(r),
                r.routepath or''
            )
            for r in self.matchlist]

        widths = [
            max(len(row[col]) for row in table)
            for col in range(len(table[0]))]

        return '
'.join(
            ' '.join(
                    row[col].ljust(widths[col])
                    for col in range(len(widths))
                ).rstrip()
            for row in table)

One link to rule them all

Monday, August 3rd, 2009

A quick demonstration of the described_routes discovery protocol is in order. It’s all done with link headers, one per resource.

Starting with some arbitrary resource in the application:

$ curl --silent --head http://localhost:3000/users/dojo | grep Link
Link: ; rel="describedby"; meta="ResourceTemplate"
$ curl --silent --head http://localhost:3000/described_routes/user?user_id=dojo | grep Link
Link: ; rel="index"; meta="ResourceTemplates"

So after the first HEAD request we have the location of the resource’s ResourceTemplate metadata; after the second we have the location of the site ResourceTemplates (plural) metadata.

A HEAD request to the site metadata location merely confirms (via the meta tag) what we already knew:

$ curl --silent --head http://localhost:3000/described_routes | grep Link
Link: ; rel="self"; meta="ResourceTemplates"

On the root resource, a single HEAD request links us to the site metadata location directly:

$ curl --silent --head http://localhost:3000 | grep Link
Link: ; rel="describedby"; meta="ResourceTemplates"

After that, it’s up to the client.

When you create a path-to client thus:

app = PathTo::DescribedRoutes::Application.discover("http://localhost:3000/users/dojo")

path-to discovers the site metadata and GETs it, specifying JSON as the acceptable format. The JSON response is converted to basic Ruby objects and used to initialize the Application object app. The client now knows the application’s resource structure:

app.users['dojo'].uri
=> "http://localhost:3000/users/dojo"

and we’re back where we started!

First post!

Friday, April 10th, 2009

That wasn’t so hard!