An Interview with Andy Hunt and Dave Thomas, authors of The Pragmatic Programmer

by Julia Reynolds

The following interview was originally published in the Middle Tennessee Java User's Group (MTJUG) June 2001 newsletter. (Included here with permission.)

In 1999 Andy Hunt and Dave Thomas published their common-sense guide to software development, The Pragmatic Programmer.

MTJUG: What led you to write The Pragmatic Programmer?

DAVE: When Andy and I first started programming together, it was obvious that we had a very compatible way of working. We'd both come up with many of the ideas that later made it into Pragmatic Programmer. During the next couple of years, we refined these into a pretty consistent set of practices. However, they were implicit: we hadn't written anything down--these were just things that we did every day. At the same time, we realized that much of this was new to others, and we were spending a lot of time explaining what we were doing every time we met a new project team. All this lead to the idea that maybe we should write down what we were doing. We thought it would be a pretty quick process, but in the end it took the two of us over a year.

MTJUG: In your book you talk about the need for Pragmatic Programmers to invest regularly in their knowledge portfolios. You suggest a goal of learning a new language every year. What new languages are you interested in and would suggest others learn more about?

ANDY: Ruby is the latest language that has piqued our interest (see www.ruby-lang.org). It combines the grace and elegance of Smalltalk with the sheer usefulness of Perl. I recommend it highly.

DAVE: I'm planning to spend more time playing with Smalltalk this year. In particular, I want to get familiar with Squeak and the morphic interface.

MTJUG: Which languages would be best to complement the knowledge portfolios of those of us specializing in Java development?

ANDY: That's a tough question. For sheer mind expansion, you might want to look at a dynamically typed language. Ruby comes to mind, of course. Dylan and/or Self might be interesting just to see some other approaches inheritance and such.

DAVE: I'd also suggest Java developers have a look at AspectJ, which is not so much a new language as an add-on to Java, allowing functionality to be spliced in to existing code. Again, it's a different way of looking at things.

In general, look for languages with different philosophies to the ones you're using. Have a look at Haskell, or Self, or Smalltalk, and see what good ideas you can bring back to your existing environments.

MTJUG: In Chapter 3, The Basic Tools, you suggest some very specific steps developers should take to master the tools of their trade. Of course, readers can't help but wonder which specific tools you favor in each of the toolsets you discuss. Specifically: What is your favorite text editor? (Obviously, readers of your book will know it's NOT Notepad!)

ANDY: My favorite editor is vi, hands down. I like some of the features that Emacs has to offer, but I cannot stand the "emacs-pinky" syndrome. I actually use XEmacs in Viper mode, which gives me the best of both worlds -- vi key mappings in a XEmacs environment.

DAVE: Andy of course has a quaint affection for vi, but there is clearly only one true editor, Emacs. I'm personally using XEmacs 21.4 for just about everything (e-mail, development, html and xml writing). Before that, I really liked the simplicity of Brief and Crisp. (Truth be told, I'm also pretty fluent in vi, but don't tell Andy :) Being able to create and manipulate text is key to our job: get good enough with whatever editor you use so that it becomes subconscious. You'll find that this makes things such as refactoring far, far easier.

MTJUG: You emphatically advocate the use of Source Control for everything. What's your favorite Source Control System?

DAVE: We've been using CVS for a while now: it's open source, distributed, multi-platform, and it doesn't enforce locks. It has its warts, but it really works very well in a multi-site, multi-checkin-a-day environment.

MTJUG: What is your opinion of visual IDEs like JBuilder or NetBeans?

ANDY: I don't do a lot with them, personally. For drag-and-drop to create a user interface, they're great, but for integrating into a sophisticated build environment, you may have some troubles. It also seems to be more difficult to integrate code generators and such into that kind of environment.

DAVE: I have mixed opinions about them. On the one hand, I think they are great tools, vastly simplifying the development of complex applications. I know that half of the software we all use every day wouldn't exist if developers couldn't rely on the power of IDEs.

At the same time, I find they have troubling aspects. One is that they dumb-down programming somewhat. If an IDE has a "create table" wizard, developers are fooled into thinking they are designing a database. If an IDE provides code to link fields to bean attributes, developers feel they're doing transactional programming. But behind the scenes, complex things are going on to support this simplicity. Sometimes you just _have_ to understand this complexity to make things work reliably. But the IDEs kind of give you the feeling that they're taking care of it all. We've seen this on recent projects, where developers used IDEs to write database access software that lacked any kind of transactional integrity. When we asked them about it, some of the developers didn't know what a transaction was. IDEs make things simple, but sometimes you need complexity. I'd rather see developers start off their careers by coding things themselves, and then cut over to using the wizards in an IDE once they understand what's really going on.

MTJUG: You address unit testing in detail. Do you subscribe to the XP principle of coding the unit test first, before creating the module code?

ANDY: I think it's a great idea, I've even done it on occasion :-). The nice part about this approach is that it forces you to consider the interface right off the bat – and I mean *really* consider the interface, because you have to actually use the code you are about to write. Being forced to "eat your own dog food" this way suddenly makes you aware of "oh, it would be much handier for users of this code if I did it *this* way instead..."

DAVE: I personally use a hybrid scheme. When I'm first writing a new class, I don't bother to do the XP 'write a test that fails' business, I just write the empty class definition. However, at that point I typically do drop into something approaching test first. I'll write the test framework for that class, and check that it all links together. Typically the first test will be simply constructing an object.

Then I'll start writing tests and supporting code. I don't write strictly test first, because often in Java that's not possible. In particular, exception handling can really mess up testing: one line of code can potentially create three or four different exceptions, and I typically like to write test cases that check the handling of each. I find this isn't too dangerous: I can keep the need to write the four tests in my head while I'm coding. For more complex stuff I'll write placeholder tests:

    public void testMyNewFeature() {
        fail("test missing");
    }

If I forget to go back and fill them in I'm told the first time they run.

I definitely feel that good unit testing is a skill that should be promoted more. Without a complete set of meaningful unit tests, altering code can become a crap shoot. And designing code to be tested really does load to a better structure.

MTJUG: You mention eXtremeProgramming at several points in your book. Can you describe the development process you follow when working on project teams?

ANDY: Well, it's different every time: sometimes subtly different, sometimes wildly. Alistair Cockburn's notion of "a methodology per project" is apt; to be truly pragmatic we must adapt as necessary to the people, culture and politics of each client individually. In fact, that's a big reason why we don't talk too much about any specific methodology in the book; the practices we advocate are appropriate (or not) independent of the methodology in use. If your team can embrace things like Pair Programming and it works for you, great! If you can't and it won't, then there are other approaches to take to ensure a common mental-map and community knowledge of the code. In general, though, we follow an agile approach (see www.agilealliance.org) to ensure that we deliver software of value that is fit for the business purpose, that can built and tested repeatably and reliably, and that honors basic architectural and design principles such as DRY and orthogonality (which gives you things like low coupling and high cohesion for free).

DAVE: As Andy says, it varies, as we try to work with our clients, rather than dictate to them. Many teams (or their organizations) are not ready for revolutions, so we help introduce practices gradually, and in a way that addresses their more pressing problems first. Often this means getting the basics (such as source code control and a build system) in place first. We then try to introduce unit testing, incremental development, and other practices. XP has been wonderful at raising the general awareness for the need for process in software development, and for telling people that methodologies need not be Draconian.