Tag Archive for 'Agile'

Recipe for 5 Whys with an Agile Software Team

5 Whys is a great way to get at the root of quality problems. On my last three projects, when I felt like code quality was dropping, I ran a “5 Whys” session. I have found it adds variety, solves a very specific problem, and plugs right in as an alternative to an agile reflection.

It’s not in every agile software team’s bag of tricks. Asking around our fairy savvy office, I discovered it’s far from universal. In the “State of Agile” report from Version One, which includes survey results from 2500 software developers, it wasn’t mentioned. Since I haven’t seen it show up that much in other agile writings, I thought I’d share my experiences here. Continue reading ‘Recipe for 5 Whys with an Agile Software Team’

assert_changes and assert_no_changes in Ruby

Update: This code and documentation is now available on github: http://github.com/ndp/assert_changes/tree/master

The Problem

On our work on gobalto.com, we spend time to have good fixture data for our tests– data that can represent all the important application states that our tests require. As a result, our tests are very dependent on the data. It’s important that someone doesn’t inadvertantly change it in subtle ways. This has led us to write not only asserts at the end of tests, but pre-conditions as well. For example,

    ...
    inotech = companies(:inotech)
    assert inotech.services.public.include?(categories(:a))
    assert inotech.services.public.include?(categories(:b))
    assert inotech.services.public.include?(categories(:c))
 
    post :edit_services_dialog, :id=>inotech.id,
                                          :service_category_id=>categories(:a).id
    inotech.reload
 
    assert inotech.services.public.include?(categories(:a))
    assert !inotech.services.public.include?(categories(:b))
    assert !inotech.services.public.include?(categories(:c))

Although the pre-conditions were introduced to guard against accidentally changing fixture data (or just to figure out what’s going on), we don’t necessarily delete them. They provide stronger tests. And in some ways, leaving in pre-conditions make the code more readable by providing documentation of your assumptions to the readers. The code above would be hard to follow without the clarifying pre-conditions. What do we expect to change and what stays the same?

Unfortunately all these asserts make the tests twice as long. And there’s a subtle readability problem: there’s no relationship between the corresponding pre- and post-conditions. In the example above, you have to scan carefully to see that the three assertions are repeated, but negated (b and c only). The reader must mentally put pieces together. And it’s not DRY. Using local variables doesn’t help much.

The Solution

I was inspired by a nice little test helper called assert_difference. It takes a string to evaluate and a block to execute. It’s useful for checking on state changes– especially database changes– during a test:

assert_difference('Company.count', -1) do
    Company.delete_one
end

(Without this method, we rely on a count of all database records, or merely look for specific ones. The former approach leads to brittle tests, and the latter to incomplete assertions.)

A limitation of assert_difference is that it only deals with integers. What if it were generalized? Here goes:

    i = true
    assert_changes 'i' => false do   # read as: i changes to false
      i = false
    end

Continue reading ‘assert_changes and assert_no_changes in Ruby’

Agile Modeling Techniques for Story Writing

At Carbon Five, all our projects begin with ‘customer facing’ meetings focused around determining scope and expectations. A core component of these early meetings involves one or more story writing sessions. The end goal of story writing sessions is to have most user stories in a project documented (i.e. in Pivotal Tracker) regardless of whether you have a requirements document or not. Story writing sessions are informal and conversational in nature, where information from customers are digested by a Team Lead and converted into stories. Most of the time, I compile user stories as a linear list in Tracker (displayed on the wall using a projector) while discussing functionality with a customer. However, sometimes customers have a difficult time ‘connecting the dots’ because of the linear nature of a list.       

On those occasions, I supplement my list in Tracker with another technique for capturing user stories. It involves modeling using a UML IDE. Primarily, I use Activity Diagrams because they capture behavior using ‘actions’ and allow for flow. Because activity diagrams are essentially flow charts, they provide a simple comprehension mechanism for all customers regardless of their technical background. I usually display my desktop in the conference room using a projector and interactively add elements to the diagram as I receive customer input. For demonstrating modeling techniques, I will use a ‘Music Store’ web application as an example.

Summary of Steps:

  1. Create an Activity Diagram from a High-Level Functional Requirement.
  2. Capture Customer Input for Identified Functional Requirement.
  3. Model Flow for Activity, Link Actions with Diagram Elements.
  4. Aggregate Similar Actions to Separate Activity.
  5. Convert Activity Diagram into User Stories.
  6. Repeat Steps until all Functional Requirements are Exhausted.

Step 1: Create an Activity Diagram from a High-Level Functional Requirement

Start with a known high-level functional requirement and create an Activity diagram. When starting, I will identify a large chunk of functionality that I know to be required for the project and use that as a discussion point with the audience. For my sample Music Store project, I would choose ‘Browsing the Inventory’ as a large piece of functionality. At this point, the audience might begin to shout out other large pieces of functionality (i.e. ‘Customers can create accounts’, ‘Employees can add to inventory’). If this occurs, I like to create empty Activity diagrams named appropriately. These large pieces of functionality will eventually be decomposed into smaller, more manageable, Activities and Actions.

 

High-Level Functional Requirement as an Activity

Step 2: Capture Customer Input for Identified Functional Requirement

Gather input from the audience regarding this Activity / functional requirement and capture pertinent information as Actions. Essentially, what you are trying to do here is decompose the larger ‘Browsing the Inventory’ functional requirement into smaller ones. Make an attempt to name each of the Actions with story-like syntax (i.e. ‘As a <role> I can <result> so that <benefit>’). The goal of this step is to create a catalog of smaller functional requirements so that you can start modeling flow.

Capturing Smaller Functional Requirements as Actions

Step 3: Model Flow for Activity, Link Actions with Diagram Elements

Start modeling flow for this Activity, linking Actions with other diagram elements. All Activities must have a start as well as an end point. I model my Activities so that my flow is complete. This ensures that all known paths have been captured. This step is crucial in capturing all known functionality for the high-level requirement.

Remember that this is an interactive step with the audience. The audience / customer will provide input as to the flow of the Activity from Action to Action.

Adding Flow to Activity

Adding Flow to Activity

Step 4: Aggregate Similar Actions to Separate Activity

If the diagram begins to flow outside of your viewable area, this is an indicator for breaking out one or more actions into a separate Activity. Several actions can be converted into one abstract action that encompasses all the functionality provided by all those actions. In the figure in step 3, the Action ‘Purchase an Item’, was created to represent another Activity diagram. The separate Activity diagram that I created was named ‘Purchasing an Item’ and contains the detailed flow for that functionality.

This step is reliant on the Tech Lead’s skill to identify similar areas of responsibility within the activity. 

Step 5: Convert Activity Diagram into User Stories

After one Activity diagram is fairly complete, begin entering them into Tracker as Stories. Each Action should be converted into a user story using a consistent syntax (i.e. ‘As a <role> I can <result> so that <benefit>’).

 

Convert Action elements into User Stories

Convert Action elements into User Stories

User Story list with Activities as Milestones

User Story list with Activities as Milestones

 

Step 6: Repeat Steps until all Functional Requirements are Exhausted

Steps 1-5 must be repeated until all high-level functional requirements have been modeled as Activities during discussion. In the end, I will have a catalog of Activity diagrams. In the figure below, a Package Diagram displays all the Activity Diagrams that I have modeled. I like to use each of the Activities as a milestone during planning. This may or may not be ideal depending on how granular your functional requirements are.

Inventory of Activities as Milestones

Package Diagram: Inventory of Activities as Milestones

 

Conclusion

There are many arguments against modeling in the agile communities, so it is important to view modeling as being supplemental to the process. In the end, our models are used to aid in the process of conveying and gathering information with the customer. Some other benefits include:

  • The diagrams can serve as a documentation deliverable
  • Interactive modeling along with the diagrams, which serve as a visual aid, improves customer comprehension of our software development process
  • This is a great way to capture requirements when none exist
  • The Activity diagram allows us to write stories in a format that follows an accompanied wireframe (if available)
  • User roles can be added to Activity diagrams as swimlanes (partitions). This aids in separating functionality by use case

Continuous Integration and Build Promotion

We have a build server and we practice continuous integration on all of our projects. In fact, it’s pretty much the first thing we set up after version control. We’re feedback junkies. It became especially apparent while working on a client project last year where we used their development infrastructure. They had a build server running, but the problem was that it took too long to get feedback. I was lost and jonesing. They had a monolithic build that took about 45 minutes to run its course and give me the affirmation I was seeking.

While setting up my current project, I decided to take a different approach when configuring our build server and continuous integration. I had a few goals in mind:

  • Super fast feedback
  • “Promoted” builds get pushed to the acceptance server
  • Minimize issues with the build infrastructure

I split our build into three plans:

Continuous Integration Build Plan

This resets the unit test database (using c5-db-migrations), compiles the project, runs all of the unit tests, and if there are no errors or failures, produces a war. The war is installed locally using Maven so that it’s accessible to other processes in a known location. This build is very fast and is triggered on every subversion commit. The command used for this build plan is:

mvn db-migration:reset clean install

Functional Tests Build Plan

This resets the functional test database, deploys the war built during the continuous integration build to tomcat using Cargo, runs all of the functional tests, and shuts down tomcat. This build is triggered on every successful continuous integration build (i.e. as a dependent build). A very short script performs the work of this build:

mvn -Pdev db-migration:reset
cd functional-tests; mvn -Pdev clean test-compile cargo:start surefire:test cargo:stop

And here’s the cargo-maven-plugin configuration:

<plugins>
...
    <plugin>
        <groupId>org.codehaus.cargo</groupId>
        <artifactId>cargo-maven2-plugin</artifactId>
        <version>1.0-beta-2</version>
        <configuration>
            <wait>false</wait>
            <configuration>
                <deployables>
                    <deployable>
                        <groupId>com.acme</groupId>
                        <artifactId>acme-web</artifactId>
                        <type>war</type>
                        <properties>
                            <context>acme-web</context>
                        </properties>
                    </deployable>
                </deployables>
            </configuration>
            <container>
                <containerId>tomcat6x</containerId>
                <zipUrlInstaller>
                    <url>http://www.apache.org/dist/tomcat/tomcat-6/v6.0.18/bin/apache-tomcat-6.0.18.zip</url>
                </zipUrlInstaller>
            </container>
        </configuration>
    </plugin>
</plugins>

Deploy to Acceptance Build Plan

This step doesn’t build anything or run any tests, but is a little more complicated than the others because it’s interacting with a another machine: our dedicated project acceptance server. We scp the war (built during the continuous integration phase) to our acceptance server. Next, we shutdown tomcat and clean a few things up (logs, old webapp, and work). Then we migrate the database (no reset because we care about the data). Last, we bring tomcat back up with the new war. This build is triggered on every successful functional test build. Here’s the script that’s run by the build server:

ARTIFACT_NAME=./ROOT.war
 
# SCP Application and Scripts
WAR=`find ~/.m2/repository/com/acme/acme-web -name "*-*.war" | sort | tail -1`
echo "Copying $WAR to acceptance server."
scp $WAR acme@acme-acceptance:$ARTIFACT_NAME
scp ./bin/*_as.sh acme@acme-acceptance:.
 
# Shutdown and Clean Tomcat
ssh acme@acme-acceptance sh ./shutdown_as.sh
 
# DB Migration
mvn -Pdev db-migration:migrate -Djdbc.host=acme-acceptance
 
# Install Application
ssh acme@acme-acceptance mv $ARTIFACT_NAME ./apache-tomcat/webapps/
 
# Startup
ssh acme@acme-acceptance sh ./startup_as.sh

Conclusion

This has worked out really well for the project and we get feedback very quickly.

You may wonder why we broke functional tests into their own plan. I find that functional tests can be a little less stable than unit tests (especially if selenium is involved), and they run much more slowly. I’ve seen cases where flaky functional tests caused a team to start ignoring build results because it was usually a problem with the infrastructure, not with the code. So, the decision was somewhat defensive and in retrospect, probably unnecessary.

We’ve spent less time maintaining our build plans than in the past as well. At some point, our build server MySQL instance crapped out and even though all of the databases were deleted, our builds all ran successfully when the build server came back up because they start with a database reset, which creates the target database and migrates it to the latest schema.

A single war is promoted as it passes a greater level of testing, and is eventually deployed to the acceptance server if all of the tests pass. While we’re saving a little time by not rebuilding the archive for each plan, that’s not the only thing I like about it. It just feels a little more right and it completely eliminates the chance that something about the artifact changes as it makes its way through the pipelines. The same war can make its way from the first CI build all the way to production. This is possible because we include default configuration for the application which matches our development environments, and then provide a mechanism for externalizing application configuration for the one-off environments.

I think most modern build server software provides everything you need to do something like this as it’s rather straight forward. However, for those who are curious, we have been using Bamboo for the last year or two and recently installed TeamCity so that we can give it a proper try. Both are great products, and if you’re on a smallish team, TeamCity is completely free (and is superior to the open source alternatives, IMHO).

How are you using your build server?

Agile User Experience (UX) Resources

For the seven years that we have been evolving our Extreme Programming practice, we have repeatedly readdressed the question of how to best integrate user experience design (visual design, information architecture,…) with an agile process. As a consulting company, it has always been a requirement that we flex our process to accommodate our clients and partners. Over the last year or two we have found our clients and partners increasingly interested in flexing their processes to work more agile and collaboratively with us.

The post is the first of a series on user experience (UX) design practices for agile software development teams. In an upcoming project with our partner Hot Studios we will be exploring new ways to integrate their user experience design process with our software development process. We’ll share some learnings from that, experiences from the past and new ideas for the future.

First we have a growing reading list of existing resources on the topic that I am posting here for you. If you have other resources for us, please share.

User Research as a Commodity
Added 2008-02-14
Alex at Pivotal Labs noted this post from a user experience manager at Kaiser Permanente who describes a strategy for including regular user testing in an agile development process. The strategy is attractive because it fits with a key characteristic of agile where simple practices performed regularly produce high level complex results.

Kent Beck v. Alan Cooper
This is a 2002 article with the following abstract “Kent Beck is known as the father of ‘extreme programming,’ a process created to help developers design and build software that effectively meets user expectations. Alan Cooper is the prime proponent of interaction design, a process with similar goals but different methodology. We brought these two visionaries together to compare philosophies, looking for points of consensus—and points of irreconcilable difference.” The difference in perspective between the two is very expressive of the conflicts we have seen between design and agile development processes. Many of the following resources reference this discussion.

Note: the original source for this great interview appears to have been taken over by another entity that is no longer making the article available. I am linking to it in the Internet Archive.

Waterfall Bad, Washing Machine Good
Leisa Reichelt’s IA Summit 07 presentation on the role of IA in the design process identifies the failures of a waterfall design process and argues that an agile, iterative design process is superior. Slide 14 is right on.

User Experience Activities on Agile Development Projects
Recent article by Scott Ambler addresses the gap between Beck and Cooper by identifying a middle ground that requires UX and agile practitioners to learn a bit more about each others’ practices and to adopt some of each.

Holistic Product Design & Development
A series of blog posts by Jeff Patton on agile software development and user centered design. Jeff moderates the agile-usability Yahoo group.

Agile Usability Yahoo! Group
The description for this group provides a good summary of the issues we are tackling here. You are invited to jump into the fray.

Experiences Integrating UED Practices
In this experience report Paul Hodgetts presents his “teams’ struggles to come to grips with the often programming-centric orientation of agile processes, and their ongoing efforts to integrate their UED (user experience design) best practices into the incremental, collaborative world of agile processes.” He provides an overview to the range of UX practices, identifies challenges and discusses practices that he found were particularly useful in integrating UX and and agile development.

Agile User-Centered Design
A post to ID-discuss that presents one designer’s struggle to reconcile agile and user-centered design.

Process Agility and Software Usability: Toward Lightweight Usage-Centered Design
2001 paper by Larry Constantine presents concrete practices for UX that map to agile practices. His approach is simple and pragmatic.

The Challenge of Agile Design
These are slides from a talk given by our friends at Pivotal Labs and Satisfaction.

User Centered Design Round Table
Podcast of a discussion on user-centered design and agile development with Lynn Miller, Jeff Patton and Rebecca Wirfs-Brock.

Originally posted 2007-09-06
Last updated 2008-02-14