Wednesday, February 4, 2009

Testing your way to becoming a master craftsman

Jay Fields writes some good stuff, and his latest post is is no exception. You should read it. Really. Yup, it's a bit long, but I like where he ends up:
When asking how and what you should test, start by thinking about what the goal of your project is. Once you understand your goal, select the tests that will help you achieve your goal. Different goals will definitely warrant using different testing patterns. If you start using a specific testing pattern and it hurts, you're probably using a pattern you don't need, or you've implemented the pattern incorrectly. Remember, we're all still figuring this out, so there's not really patterns that are right; just patterns that are right in a given context.
In other words, we should write tests if it helps write better code. That's it. Yeah, writing tests will probably help you write code that you know works, but there sure are a lot of ways to test. So use whatever tools you can to produce something better, but always think and always be ready to learn and adapt.

I've always liked how the trades have the notion of taking decades to really learn your craft. First, you start by being an apprentice, where you learn on the job from someone who's right beside you working on the same job, but who's already been there many times before. After you've proven your mettle, you become a journeyman where you practice on your own, but you continue to learn because you're still under the watchful eye and guidance of a master craftsman. In order to become a master, though, you have to produce a masterpiece and only if that's good enough might you be recognized and elected to the guild by the other masters.

No, building software isn't that different, rather, shouldn't be that different from this. More often than not, known when and why is just as important as knowing what and how. Building good products really does involves more art than most of us would like to admit.

One thing is for sure: we'll spend the rest of our careers learning to do things better, to write better code, and to craft a better product.

Wednesday, January 21, 2009

Inauguration pictures

No, I didn't get to go. But The Boston Globe has an excellent collection of photographs from January 20.

Also check out CNN's pictures that use Microsoft's PhotoSynth technology that collects and "stitches together" lots of individual photographs, allowing you to pan and zoom and click to see different photos.

Tuesday, January 20, 2009

Whitehouse.gov uses Creative Commons by default

Very interesting copyright page on the new Whitehouse.gov site:
Pursuant to federal law, government-produced materials appearing on this site are not copyright protected. The United States Government may receive and hold copyrights transferred to it by assignment, bequest, or otherwise.

Except where otherwise noted, third-party content on this site is licensed under a Creative Commons Attribution 3.0 License. Visitors to this website agree to grant a non-exclusive, irrevocable, royalty-free license to the rest of the world for their submissions to Whitehouse.gov under the Creative Commons Attribution 3.0 License.
Change indeed!

Monday, January 19, 2009

Git it together with Subversion

I've recently been exploring Git, and I'm really impressed. In fact, I'm having a lot of fun. Yes, tooling is not quite there, but it is coming along. Among other tools, there's an Eclipse plugin (still pre-1.0), a Hudson plugin, a JIRA plugin, and plans for a Fisheye plugin. I've tried the Eclipse plugin, and was moderately impressed. Some things just don't work yet, but then there still are lots of problems with the Subversive SVN plugin for Eclipse. I routinely use the SVN command line interface to do (almost) everything, so using Git from the command line isn't a stretch at all.

What really convinced me to try Git, though, was how well it does branching. Actually, branching and merging. Quite a few source control management systems can branch, but the problem is they don't merge - or if they do, they don't do it well. Git, on the other hand, makes merging easy. In fact, it's really easy to create branches, switch between branches, and merge branches.

So why am I so hung up on branches? Well, being able to branch and merge means that I can use branches for everything - bug fixes, new feature work, prototypes, or maintenance. I can create a branch where I do all my work, and I can commit as many times as I want. I can even use tags to help me remember important commits (e.g., "all tests pass"). And when my work is complete, I can merge my changes onto as many branches as I need to. All of this is done locally, without polluting the main repository's trunk or branches. Of course, if I'm working with other people on a feature or bug (e.g., "please review these changes and provide feedback"), I could expose my own repository or we can leverage a shared repository. And when the work is all complete, merging onto the official branch(es) is cake, too.

I don't want this post to be another tutorial about Git. There are already quite a few resources out there, and Google is your friend. If you're new to Git, I'd recommend starting with the videos and documentation at git-scm.com, which is the new home for Git. If you're wondering "Why would I use Git?", then I'd suggest Linus Torvald's talk at Google. If you're asking "How would I use Git?" or "How does Git work?", then a great starting point is Bart Trojanowski's excellent tutorial. The Viget folks also have a number of good blog posts.

What I do want to cover in this post, however, is how to get started with Git and Subversion. See, Git comes with a bridge to Subversion so that we can use Git locally but can routinely do the equivalent of "svn update" and "svn commit" - on any and all branches. In fact, using Git locally means that we can probably work with SVN branches just as easily as SVN users, but we can merge branches. And since branching and merging are so much easier for us, we can create our own branches locally without having to expose them all to the central SVN repository.

So, here's my simple introduction to using Git with Subversion.

1. Install Git
You can install it several different ways, depending on your platform and your preference. I have a Mac, so I could download and compile it using MacPorts, or I could grab the latest installer. I like simple, so since I don't yet have MacPorts I went for the installer. Piece of cake. I also chose to manually set up my path, so in my .bashrc file I added these statements:
export MANPATH=${MANPATH}:/usr/local/git/man
export PATH=${PATH}:/usr/local/git/bin:/usr/local/git/libexec/git-core/
(Okay, I actually used some variables to keep things DRY. I thought the above might cut through all that noise.) Note that we added "git/libexex/git-core/" to the PATH. This directory contains all the commands that start with "git-" (e.g., "git-svn ..." is really the same as running "git svn ...").

2. Clone a remote SVN repository
The next step for me was creating a local git repository that mirrored the remote SVN repository.
$ git svn clone -s http://example.com/my_subversion_repo local_dir
The "-s" option tells git that the Subversion repository use the "standard" naming convention of using "trunk", "branches", and "tags" directories. When this command runs, it creates a subdirectory called "local_dir", initializes the git repository in that "local_dir", connects to the SVN repository at the URL (which does not include "trunk" or any other branch/tag information), proceeds to download all of the history (including branches and tags) in the SVN repository, does some cleanup, and checks out the equivalent of the SVN "trunk" to our working area. And, because of Git's bridge with SVN, we'll be able to regularly pull changes from SVN into our git repository, and we can even upload changes we make locally back into SVN.

We now have our new Git repository, so cd into it:
$ cd local_dir
If you look closely, you'll see a couple of things. First, Git doesn't proliferate your working area with ".svn" folders. Instead, there's just one ".git" directory at the top. Git also uses a different technique than SVN for remembering which files and directories should be ignored. But we can bootstrap Git's ignore information automatically from SVN's. We'll use the ".gitignore" file in our working area, since we want this information to be versioned and we want everyone using the repository to be able to use it. If your SVN repository already has a ".gitignore" file, then someone's done the work for you. Otherwise, you'll have to run the command to generate the file:
$ git svn show-ignore > .gitignore
This will take a minute or two, depending upon the size of your working area. I would then commit this new file, placing it in the master branch.

3. Committing (locally)
To commit our new file, we first have to tell Git that we want to start tracking this file. Or, in Git parlance, we want to stage the file by adding it to the index:
$ git add .gitignore
We can use the status command to see a summary of what's already staged, what's being tracked but hasn't been staged, and what's not being tracked at all:
$ git status .
We can also get a more detail report showing all the individual changes that have been staged:
$ git diff
We can then commit our staged changes:
$ git commit -m "Description of commit" .
or, if we want to automatically stage any modified or deleted files, we can add use the "--all" (or "-a") option:
$ git commit -a -m "Description of commit" .
With the "commit command, Git records the entire set of staged changes as a single commit to our current branch, and it moves the branch's HEAD pointer to this last commit.

4. Branching and Merging
Since your Git repository is local, the process for branching and merging is the same, regardless of whether your Git repository is brand new or whether its based off of a Subversion repository or a Git repository. Steps for creating a branch, making changes, committing those changes, switching branches, and merging branches is all covered well in other places, so I won't cover it here.

But if your repository is based off of a SVN repository, you'll still want to pull changes made to Subversion into your repository. And you'll probably want to be able to push your changes (e.g., commits) back into SVN.

5. Updating from Subversion
If you're familiar with Subversion, you're hopefully used to doing "svn update" before committing your changes. This pulls any revisions that others have made since you last updated, and its good form to do this and to make sure everything compiles and runs locally before committing.

In Git, you do this with the "git svn rebase" command. This command fetches revisions from the SVN used by the current HEAD (of the current branch), and "rebases" any current commits on the branch to apply to these latest SVN changes. This is analogous to creating a patch file for each local commit (relative to that commit's parent) since the last rebase, updating the branch with the new SVN revisions, then sequentially applying the patches. In other words, it takes all your local changes (in the form of commits) and reapplies them to the latest SVN revisions.

Here's the actually command to rebase the current branch:
$ git svn rebase
If you want to fetch all of the revisions on all branches in the SVN repository and rebase any local commits on those branches, you can add the "--fetch-all" option.

6. Committing back to Subversion
Once you have rebased your local commits on a branch, you will still have changes to that branch that aren't yet in Subversion. We want to do the equivalent of an SVN commit, which in Git is to commit each diff on the branch back to SVN:
$ git svn dcommit
This creates a new revision in SVN for each local commit on the branch. Of course, if you want them to look like a single revision, you'd need to squash the commits before running the dcommit command.

Conclusion
This post focused mostly on how to get started with Git using a remote Subversion repository, so I didn't talk much about how to go about branching and merging. I think you'll agree, though, that Git's Subversion bridge seems very intuitive, and in fact many of the same concepts used by the Subversion bridge are the same concepts used by the rest of Git.

But if you're new to Git, no doubt you're feeling unsure about what Git is and how you'd use it. Again I'd have to point you to the recording of Bart Trojanowski's presentation. It is 2 hours long, but it really is a fabulous tutorial if you're interested in learning the fundamentals how Git works and how to use Git.

Thursday, December 11, 2008

JBoss AS 5.0.0 is JEE 5 certified (officially)

JBoss AS 5.0.0 was released late last week, and now it's officially certified as Java EE 5 compatible. Congratulations to the JBoss AS team!

Get your copy today.

iPhone shortcuts

This list of shortcuts for the iPhone keyboard were too good to pass up. I already knew about several of them, but others were new. Love the comma shortcut.

Friday, December 5, 2008

Map those addresses in Address Book

This really cool plugin for Apple's Address Book allows you to right-click on an address and find it in Google Map (among a few other things). Simple, and granted it's not something you need to do frequently. But I have wanted to do this before.