Enjoyable development
What is the secret to happiness? Surprisingly, this question can be answered more and more definitively. I want my work to be conductive to the happiness of myself and others, and I believe agile methods can help me do that.
Years of research into happiness can be summed up in a simple sentence. You all know what gives you a happy life. It’s not anything strange or unexpected. It’s simply enjoyable progress towards a meaningful goal. This deceptively simple sentence contains two parts: Enjoyable progress and meaningful goal. If I sacrifice the enjoyment for the goal, for example, if I hate to study, but do it anyway because I want to pass the exam, I ultimately feel unhappy even when I reach my goal. And if I indulge in slacking off or eating good food for a long while, I start feeling like my life lacks meaning. Most software projects have a meaningful goal. Usually, it’s about making someone’s life better. Many of our goals are unrealistic, and quite a few of them have questionable meaning, too. This is definitely something to address. But for now, I want to focus on the enjoyment aspect, and how I use my tools to create an environment where I enjoy my work. When I first read Tal Ben-Shahar’s “Happier”, an introduction on the field of positive psychology, I was struck by the similarity to what Ben-Shahar calls “the rat racer mentality” and projects with a long delivery cycle. Rat racers only focus on the goal and forget to enjoy the road there. Like the stereotypical “waterfall” project, they go about their tasks with much pride and no joy and they aim to deliver something in years that will make up for suffering along the way. This doesn’t lead to happiness. As a matter of fact, when the project is finished and our pain is over, do we feel like the goal was worth it? How do we address the rat racers dilemma? How do we make sure that the progress towards our goal is enjoyable? There are two ways I can think of: We can distract ourselves with the pleasures of life and try to ignore the pain of work, or we can try to make the work itself more enjoyable. Which of these methods are most worthwhile to try? I put my money on making work more enjoyable. How can I make sure that I enjoy my work? If I can avoid waiting for my tools; if I can be sure that I haven’t introduced a bug; if I can automate repetitive manual tasks; if I can be sure tha I haven’t forgotten anything; if I know that someone appreciates the output of my work; if I can trust that the tasks I can’t perform myself will be done correctly and timely; if I understand my tools; if I understand why I am working on whatever I am working on. What tools and processes seem to conspire against my happiness? I can think of a few: Application servers that require minutes for a restart; processes that require me to hand over my system to someone else for basic testing; mountains of documents that together, probably, contain most of the requirements. What would a process that takes care of my concerns look like? It would have fast running tests for me to work with all the time. It would automatically run several types of test to verify the correctness of my system. It would enable me to deliver frequently to a realistic environment and get feedback from users. Starting with test: What happens if a test takes more than 10 minutes? Well, I certainly won’t be sitting at the computer when it’s done. If it takes more than just ten seconds, I will have switched to another window. What about a test that takes five seconds? I for one will have lost my train of thought. So I prefer tests that run in a second or so. And I can often get there, even when adding tests to existing code. So that’s the tests running at my computer. What about all the tests that run after I have checked in my code as ok? First, I want three kinds of tests: I want to make sure that my unit tests are still running correctly, I want functional tests that automatically check which requirements are met, and I want integration tests that verify that the system will work under realistic conditions. All of these tests are automated and reasonably accurate in my current system. What about speed and feedback from the real user? In my current system, it takes less than 10 minutes to run all unit test and all functional tests. This happens automatically, so I don’t have to worry about it. Since I can run my relevant tests before checking in my changes, I feel safe in starting on another task. Every hour, if there has been a change, my integration tests run automatically by setting up the system as realistically as possible and subjecting it to production data. Every two weeks, we check all our work and create a formal release. That is, we give the system a name like 2.0.20 (yeah, those version numbers tend to go up fast!). We demonstrate our progress for our customer and deploy it to a stable test environment (called “preproduction” or “staging”). This environment experiences the same conditions as the production environment and is subject to the same stability requirements. If this version of the system runs satisfactory for a week, we deploy it to a pilot production environment. That is: We let it handle a select small subset of the users. The result is a production line that provides fast feedback, gives us a safety net that catches us if we made a mistake or forgot something, and gives us the ability to discuss our progress with our customers. Getting here was not easy, and we had to sacrifice many golden cows along the way. Would you think that enterprise software like that delivered from IBM or BEA would help with this process? Surprisingly enough, you would be wrong. It seems like most expensive enterprise software is designed to make work as unpleasant as possible. Such software (ideally) comes with a lot of power, but also introduces complexity. Only when we got rid of IBM WebSphere, were we able to make meaningful progress. Happiness requires enjoyable progress towards a meaningful goal. For me, making enjoyable progress possible meant to focus on automatic, accurate and fast feedback. I was unable to get this feedback using complex tools, so I quickly found that everything that I can’t get a handle on after playing around with it for a day is not worth it, even if it’s an extremely powerful. Are you currently plagued by boring, manual, and error prone processes? What do you think you can do about it? And if you don’t fix it, then who will?
Comments:
Geir Hedemark - May 14, 2008
I don’t know if you have heard of this already, but it follows up on your thoughts on the time it should take to run tests.
There is something called flow psychology ( http://en.wikipedia.org/wiki/Flow_(psychology) ) which describes the conditions that need to be fulfilled if you are to experience “flow” (Which at least for me is a precondition for not being caught my my mail reader). I learnt a lot from that as a project manager.
On to a question I have:
What would happen if all your tests took less than a second to run? Would you structure your tests differently?
Geir Hedemark - May 15, 2008
I was unclear, once again. Let me clarify.
If all of your tests - system tests, unit tests, integration tests, the works, all completed in less than a second - would you structure your test suite differently? Would you still keep your unit tests around? Would you hang on to your CI server?
Johannes Brodwall - May 15, 2008
Hi, Geir
Thanks for a very interesting question. I think I might want to expand this into a full entry eventually.
I think the risk of my tests running this quickly are fairly slim. But if it did happen, I would still want to separate out the functional tests that we create in cooperation with domain experts and the system level tests that simulate realistic operating conditions. I’m happy with the system level tests we have now, which stress the system. There’s no way these could run in under 1 second.
But neither of these types tests are JUnit tests. Our functional tests are implemented in FitNesse and our system tests are scripts that push data on the system (for a web based system, I would consider JMeter).
For tests implemented with JUnit, I would not see any usefulness in the distinction if things ran sufficiently fast. I might consider deleting tests that were covered sufficiently by the functional tests, but since these are run by different tools, it might be hard to find out exactly what tests could be deleted.
I would keep my CI server, though, so I was sure that changes by every member of the team (myself included!) actually passed the test suite. I might even add a failure condition if the tests ran for too long, to make sure that we didn’t start down the slippery slope of slow tests.
Geir Hedemark - May 15, 2008
I agree when it comes to performance tests. Those are, by design, meant to take longer.
My idea when it comes to functional testing doesn’t really lend itself to fitnesse. I want to also veryify that all interfaces to the system do what they should. I can’t really see that happening with fitnesse the way I want it to.
The good news is that we are almost there. I have created functional test suites which ran a full regression test for a module in less than a minute or so. The drawback was the setup time, which also was on the order of a minute. This minute was caused by spring/hibernate.
Good point about the CI server. What if eclipse (or whatever) continually ran your tests, using the second processor everyone seems to have but not use these days, just as your code gets compiled “continually” behind the scenes?
Johannes Brodwall - May 14, 2008
Flow is definitively an important component of happiness.
“If all my tests took less than a second”? Do you mean more than a second?
Most of the tests I write first are independent of infrastructure, which means that they run really fast. I try to separate out my slow-running tests (e.g. test that a search generates SQL that retrieves the correct result from the database). I haven’t doing any soft of formal categorization here, though.
I find that either I run a single test in the IDE. Then it should run fast. Or I run all my tests for the command line. Then everything should be run. So I don’t need to categorize stuff now.
Johannes Brodwall - May 15, 2008
If everyone (including the questionable professionals who currently don’t really test!) ran continuous testing in their IDE, I wouldn’t feel the need to run these tests in CI. But we use our CI server also to build the software and push it out to test servers for performance testing. So I don’t know what the point of disabling the tests would be. :-)
I think functional tests will tend to vary a lot from project to project. It really depends on what your interface to the outside world is.
A minute to start up Hibernate (Spring is seldom to blame) is unacceptable for a functional test. In my functional tests, I have replaced the whole persistence layer with a stupid in-memory replacement.