2010-12-22

The Goal

I have pretty strong feelings about Agile. That is to say, I can't stand it. When someone mentions Agile to me all I think about are overpriced books, puffed up consultants and "coaches" and a whole slew of project management software tools that give Pro[du|je]ct Managers way too much noise vs. signal about how a project is really going. And all of it gets in the way of what I really love to do: sling great code.

But man, oh man, do I dig being agile.

There's already a pretty awesome article about the difference between "Agile" and "agile". It says just about everything I could write on the subject. Rather than rehash ideologies, I'm going to introduce a concept that has helped me towards gaining an agile mindset: the goal.

I've had the goal in my head for a while now. I never bothered writing it down anywhere until a presentation that I threw together in about 30 minutes to help my new team with their agile adoption. That presentation is the first time I've seen the goal presented and worded in that form (I don't take credit for the goal; it is the product of a lot of reading, attending other people's presentations, some experiences good and bad, and a healthy dose of my own biased worldview.) Here is the goal:

Deliver working, usable, high-quality software as quickly as possible.

The goal answers a simple question: why are we adopting agile? This isn't about the project or product. The business has already defined the rationale for that. The goal is about the rationale for wanting to be agile while accomplishing the project.

Nothing in the goal (or the Agile Manifesto, for that matter), speaks to a specific process or method. And that's where the power of the goal comes from. It speaks to what the team is trying to accomplish, while making the how a secondary concern. Focusing on the goal allows a team to easily see where their agility is being compromised:
  • Is our software working? Is it ready to be put in the hands of our users? Are we making continual improvements to it?
  • Is it usable? Does it meet our users' needs and goals? Does it provide value to the stakeholders?
  • Does it have high-quality? Is the code clean, as bug-free as we can make it, and easy to fix when the bugs we missed inevitably appear?
  • Are we delivering fast enough? Are we meeting the current needs of the business? Are we able to act on ideas and opportunities before our competition does?
If the answer to any of those questions becomes "no" at any time, then the process is broken. Fix it. You don't have to follow Scrum or any other Agile methodology to the letter. Process is highly context dependent. Only you and your team know what will get you to the goal.

If everyone can agree on the goal, the rest is downhill. The team will work out it's own way of getting there. I suggest Scrum as a starting point because, as a method, it's easy to understand. But I believe that a team that is really focused on the goal will probably leave the guardrails of Scrum and start building their own process fairly quickly.

There's a concept that I first heard from Alistair Cockburn but originally came from Japanese martial arts: Shuhari 守破離. The basic premise is that there are 3 stages to attaining mastery of a skill:
  1. Shu — You imitate the form exactly. You do not deviate from the specified process, and you follow it to the letter.
  2. Ha — You begin to innovate for yourself. You tweak the process to take advantage of your own special circumstances and strengths.
  3. Ri — You no longer think in terms of forms or processes. There is a constant, smooth and uninterrupted flow of thought into action.
Everyone starts at Shu. Scrum is Shu, as is any other Agile method. Moving towards the goal helps a team move out of Shu and towards Ha. This is where agile beats out Agile. When you stop thinking about Agile or agile, and you simply act in the direction of the goal, you have attained Ri.

2010-12-15

Git, TargetProcess and Hashtags

At $job, we're using TargetProcess for our user story and task management. One of the neat things you can do in TP is tag commits to a code repository in such a way that they will link to the task associated with that commit:
#123 This commit is linked to task number 123
In order to get this to work, the hashtag has to be the first thing on the first line of the commit message. Anyone using `git` as their source control should immediately see the problem with this...

...In git commit messages, any line starting with # is considered a comment and is stripped out of the commit message. Quite annoyingly, there's no way to change git's default comment delimiter. Since $job is using Subversion, this isn't a problem except for myself, the lowly git user hobbling along with git-svn.

The solution I've come up with is a two-pronged approach involving changing a default and adding a git-hook.

Firstly, the default --cleanup option on a `git-commit` command strips trailing and leading whitespace lines and all commentary (lines starting with #). So I aliased `git commit` to only worry about the whitespace lines, by adding this to my .gitconfig:
[alias]
    cmt = "commit --cleanup=whitespace""
So now git will leave lines starting with "#" alone. This means I have strip them out myself. This is accomplished with a git commit-msg hook that looks like this:
# Use TargetProcess hashtags to link commits to tasks
# use this in conjunction with --cleanup=whitespace
sed -e 's/^#.*//' -e 's/^@\(#.*\)/\1/' -i $1
The first sed expression strips out comment lines. The second one translates any line that starts with "@#" into one starting with "#". The trick is that it does it after the comment line stripping. So now I can do commits that look like this:
git cmt

# The editor opens and I can type:

@#123 This commit is linked to task number 123
# This is a comment line that will get stripped out
#  So it this

When the commit goes through, voila! A commit message starting with a hashtag that can be picked up by TargetProcess.

Edit 2010-12-16: After experimentation and verification, it turns out the TP can pick up the task id hashtag anywhere in the commit message. So all the above is not really necessary. It's interesting from an educational perspective, though.

2010-12-05

Private Git repository with Dropbox

I recently began working on a project that needs a remotely-accessible private git repository. The project needs to be done on the cheap, and we don't have the budget to pay for a private github or assembla repository. We're already using Dropbox to handle project documentation and such, so it became a natural fit for sharing code as well.

I already have the Dropbox client installed and set up on my development machine. Here is how to set up the repo:
cd /path/to/Dropbox
mkdir myproject
cd myproject
git --bare init
This initializes a "bare" repo; a repo without a working directory. In other words, you can't edit and commit to it directly. The repo is now your "remote", hosted on Dropbox, and accessible through the local filesystem.

Create a working clone from the remote repo:
cd /path/to/myproject-working
git clone /path/to/Dropbox/myproject .
This will complain about cloning an empty repo, which is fine. Now follow the normal git development cycle:
echo "Read this!" > README
git add README
git commit -m "Initial commit"
When you're done making changes and committing, it's time to push to the remote repo in Dropbox:
git push /path/to/Dropbox/myproject --all
The `--all` flag is necessary on the first commit to the remote. It can be left off of all subsequent commits.

That's it! Now the repo is available on any computer linked to the Dropbox account, and can be checked out using the normal `git clone`, work, commit, `git push` cycle.

If you want other developers to have access, simply share the repo directory with their Dropbox accounts as you would any other directory. They can clone it and push to it just like any other git repository.

Here's another trick if you don't have the Dropbox daemon (dropboxd) running all the time on your development machine. Put the following script in "/path/to/Dropbox/myproject/hooks". Name the script "dropbox-push"
#!/bin/sh

dropbox running
if [ $? -eq 1 ]; then
 echo "Dropbox started by another process."
 exit 0
fi

dropbox start
until [ "`dropbox status`" = "Idle" ]; do
 sleep 1
done
dropbox stop
Now make the post-receive hook runnable:
mv post-receive.sample post-receive
Edit the "post-receive" file, and add the following lines:
cd `dirname $0`
./dropbox-push
Save the file. Now whenever you (or another developer) pushes to the repo, it will check to see if the Dropbox daemon is running, and if not, will start it and let it run until the code is synced, then stop the daemon. Since the hook itself is in under Dropbox, it will be synced and will be run for all other developers pushing to the Dropbox repo as well.

So there it is, a free, private git repository; at least, until the repository gets larger than the Dropbox free 2GB limit.