Frank Thoughts

Is Test-First Development an Impediment to Creative Flow?

by Frank Sommers

January 27, 2005



Summary

Writing tests before writing code is a key tenet of extreme programming: Write your tests before you write your code. I find myself violating this XP rule very often. A bit of psychology suggests that test-first development may actually stifle creative flow.


A key XP tenet is to write unit tests first, and then the simplest code that passes those tests. As the Extreme Rules state,

"When you create your tests first, before the code, you will find it much easier and faster to create your code... Creating a unit test helps a developer to really consider what needs to be done. Requirements are nailed down firmly by tests."

I find myself violating this tenet of XP very often. I do test all my code, but often only after I've already written that code. Why does this one XP rule seem so out of place to me?

I may have come close to the answer in the work of the famed psychologist Mihaly Csikszentmihalyi, professor and former chair of the psychology department at the University of Chicago. Csikszentmihalyi (pronounced ME-high CHICK-sent-me-high-ee) is best known for his decades-long research into the key causes of happiness, and for his seminal book on Creativity. For that work, he interviewed several hundred scientists, engineers, writers, artists, philosophers who shared the distinction of having achieved remarkable feats of originality in their work, advancing their respective fields. Csikszentmihalyi wanted to find out what these people had in common that contributed to their exceptional creativity.

One shared thread: Their experience of "creative flow" during their peak mental work. Being in a state of flow means

"being completely involved in an activity for its own sake. The ego falls away. Time flies. Every action, movement, and thought follows inevitably from the previous one, like playing jazz. Your whole being is involved, and you're using your skills to the utmost."

Csikszentmihalyi identified four ingredients that must be present to experience flow.

The activity must present just the right amount of challenge: If the activity is too hard, we become frustrated; if too easy, boredom ensues.

There must be clear and unambiguous goals in mind.

There needs to be clear-cut and immediate feedback about the activity's success.

Finally, our focus during the activity must center on the present - the activity itself.

Writing code in a certain way can help us get in a state of flow. For flow to occur, we must work on a chunk of problem at the right complexity level - a problem that's neither trivial, nor overly complex. We must have a clear objective for what we're working on -- for instance a specific, well-defined use case. To receive immediate feedback, we must unit test the code as we write it. Finally, it should be possible for these small pieces of functionality to work on their own, without having to go through major integration steps.

Most XP practices facilitate these conditions - with the exception of test-first coding. In my experience, writing tests first often interrupts flow. I can think of a couple of reasons:

The granularities of what's easily testable and what's a sufficiently challenging chunk of problem often mismatch. In general, I find that testing works for small pieces of functionality the best. But working on problems at a higher level, say at the level of 5 of 6 test cases, challenges us more.

The focus shifts to passing the tests from solving the use case. So we may have a situation where all tests pass, but the use case still doesn't work, or is not complete.

For instance, you may be working on a Web app controller. That controller serves a specific use case, say, adding a new user to the system. The controller must perform a set of validation steps first. If all checks out, it must save the new user, and redirect to a confirmation page. If errors occur, it must communicate those errors back to the user. What I often like to do is just write all that logic in one sitting - focusing on the problem as a whole. Only when the code is done do I like to write tests for that code.

In creating the tests, I often find the need to refactor the initial code into smaller methods that are easier to test. But those small methods serve mainly the purpose of easier testing, and perhaps better comprehension of the code by other developers - they are a secondary artifact, created after the initial deed of writing the code to perform that focused, well-defined task. Refactoring and testing are less creative than writing the initial code and, instead, are more "mechanical" activities.

I like to think of refactoring and testing as editing. When writing an article, most writers first create an outline, then write the content, typically in a few sittings, and without regard to mistakes, typos, sentence structure, etc. Only then does an author spend most of his time on editing, fine-tuning, and polishing the article. "Writer's block" often occurs when a writer intermingles editing with the initial "brainstorming" and creation of content. Most writers would agree that editing is a very different kind of activity from coming up with the initial content.

Looking back at some of the more complex systems I worked on, I always developed the trickiest part of the code that way - in one sitting, just getting it to work from beginning to end. I can often get a lot of work done that way, and produce a lot of functionality in a short period of time. In other words, that is a very creative time period. Then I spend some time on testing and refactoring.

I am curious if my experience is shared by others: Do you really write your tests first?

Resources

Extreme Progamming "Rules"

http://www.extremeprogramming.org/rules/testfirst.html

Mihaly Csikszentmihalyi

http://www.edge.org/3rd_culture/bios/csik.html

Mihaly Csikszentmihalyi. Creativity: Flow and the Psychology of Discovery and Invention.. Perennial, 1997.



Mihaly Csikszentmihalyi. Flow: The Psychology of Optimal Experience. Perennial, 1991.

Talk Back!

Have an opinion? Readers have already posted 41 comments about this weblog entry. Why not add yours?

RSS Feed

If you'd like to be notified whenever Frank Sommers adds a new entry to his weblog, subscribe to his RSS feed.

About the Blogger

Frank Sommers is a Senior Editor with Artima Developer. Prior to joining Artima, Frank wrote the Jiniology and Web services columns for JavaWorld. Frank also serves as chief editor of the Web zine ClusterComputing.org, the IEEE Technical Committee on Scalable Computing's newsletter. Prior to that, he edited the Newsletter of the IEEE Task Force on Cluster Computing. Frank is also founder and president of Autospaces, a company dedicated to bringing service-oriented computing to the automotive software market. Prior to Autospaces, Frank was vice president of technology and chief software architect at a Los Angeles system integration firm. In that capacity, he designed and developed that company's two main products: A financial underwriting system, and an insurance claims management expert system. Before assuming that position, he was a research fellow at the Center for Multiethnic and Transnational Studies at the University of Southern California, where he participated in a geographic information systems (GIS) project mapping the ethnic populations of the world and the diverse demography of southern California. Frank's interests include parallel and distributed computing, data management, programming languages, cluster and grid computing, and the theoretic foundations of computation. He is a member of the ACM and IEEE, and the American Musicological Society.

This weblog entry is Copyright © 2005 Frank Sommers. All rights reserved.