Stress Free Programming

The following was cut and pasted from my web site as a starting point for the Wiki change process. The original can still be found at http://www.efsol.com/golden.html. -- FrankCarver
The Golden Rules of Stress-Free Programming

I have been designing and programming computer systems for over a dozen years now. At times I've loved it, and at times I've hated it.

Oh yes, I've done my share of grumbling about poor management, inadequate requirements, indecisive customers, incorrect documentation and so on. But even in the darkest depths, with blame flying thick and fast and the corporate axe laying waste all about, I could always look back to the pure joy I discovered when I first made a dumb machine do what I wanted.

In recent years I have begun to wonder; what made those early years so exhilarating? Why does corporate programming often seem to be a hothouse for frustration and stress? And more importantly, how can I make it more fun for me and my colleagues?

So I examined the projects I've worked on which had a good (or even great) team atmosphere, the ones that worked, the ones that came in on time and under budget, and compared them with the others. Here is the result so far; a few simple rules for stress-free programming!

Build in small pieces

Every one's heard of divide and conquer. Well in programming it's vital. That 200 line function or that 80 method object may seem straight-forward when you write it, but 6 months or a year down the line when several conflicting customer requirements have been patched in by different people it turns into a horrible lump. By then it's too late. Everyone agrees it should be simplified, but nobody really understands it or the way it's tangled into the system - the benefit of improvement is outweighed by the risk.

This conflict of common desire against practicality is the first source of programming stress. It's the one that causes team members to curse management for their stubbornness and dream of pastures new. It's also the one that causes management to distrust programmers. One or two overly-optimistic attempts at improvement can crash and burn an entire team's reputation.

Test early. Test everything. Test often. Test automatically

This may seem like a whole bunch of rules, but it all boils down to one thing: testing is not an after-the-fact process to find faults with whole systems, it's a vital tool for getting them right in the first place. As the second step to removing my programming stress, I make sure that every function, every method, every object, every subroutine has an associated automatic test harness which tests normal, limit and error cases for every parameter, and makes sure it does the right thing. This appears like overkill, and it's one of the hardest of these rules to "sell" to team members. In my experience, though, this technique gives the biggest single reduction in project duration (and therefore in cost) of any tool or process I've ever encountered. Think of it like building a house; Before you build the walls, you want to make pretty sure the foundations are stable. If you find a fault with the footings after the walls are raised it's going to cost a lot to get it fixed. If the roof's gone on and the furniture is in place, that same fault might cost more than the house to put right.

A corollary of this is: Design for test. Provide test hooks, diagnostic switches and so on wherever you can without compromising other constraints (such as performance or program size). In a system designed for test, where a complete set of automatic test harnesses have been built at the same time as the system, it's much easier to consider rewriting even large sections. Just rerun the automatic test pack after each of a series of small changes and you can be sure that the final system is as robust and complete as the original.

This technique helps to remove the second source of programming stress, which comes from not trusting the rest of the system. Locating a fault is easy if the whole preceding system has already been completely tested. The problem must be in the new bit. If you stick to my first rule, the new bit will be small too - which makes it doubly easy. If you haven't tested all the bits as you built them, it's like trying to find a rotten apple in a sack - by poking the sack with a stick!

Do the simple bits first, you may never need the complex bits

I've seen many projects snowball into chaos, and drive everyone working on them to distraction, just from losing sight of the priorities. Some people seem to live for "requirements capture" and "customer relations", but its a fact of life that no project is ever fully specified before design and coding starts. If you demand this you really will get stressed out! So go with it, accept that things are going to change and make the best of it. My survival technique for this is to always code the simple cases first. Not only is it more likely that the requirements and specification process has got the simple cases right (more people at more meetings can understand them), but it's less hassle if you have to throw them and start again.

This also applies to adding complexity in the name of "future-proofing" or "performance". Only do it once you know it's really needed. Many systems I've encountered have actually become less flexible and even slower because of ill conceived initial complexity. If you don't need it, don't code it.

The stress you can get if you don't use this sort of approach is the sort which leads to despair at indecisive customers and a feeling of loss of control of the project. As well as frustration and arguments as you have to change, again, the code you've laboured over. This can never fully be eliminated, but by doing the simple cases first you can at least feel you're making progress.

Communicate and share the workload

In the real world, the vast majority of programming is done in teams, but all too often the teams are divided in the wrong way. Each team member becomes an "expert" on some area of the system, and all changes, faults or support requests for that area naturally go to them. If you have any influence on team structure, it's almost always better to divide the team another way. The ideal end result is that everyone in the team knows enough about the system to code reasonable changes, find basic faults and handle normal support requests for any part of the system. They should also know who to ask or where to look for more detailed answers, but consider it an exercise in "learning from the master" rather than "delegation" or "division of labour".

This approach naturally implies good communication between team members. Working close together, frequent social and business meetings, a common "house style" for code, comments and documentation all help. My top recommendation, though, is to develop a "review culture". If everyone in the team helps to review everyone else's work (and takes it seriously...) it not only helps to catch potential problems and deviations from the house style, but also helps everyone get up to speed on all parts of the project.

The type of stress this helps to prevent is well known, I'm sure. If you're the only "expert" on one part of the system, then the pressure is on you to solve all the problems. If a particular change or fault is mainly in your component then you are the critical path for the work while others seem to sit about doing nothing. On the other hand, if a problem or question arises concerning someone else's area of expertise when they are not available, you are put under pressure again.

Work to human timescales, and seek "closure"

This is a tip which doesn't just apply to programming stress, but it's just as useful here as it is in any other field. It could also be phrased as "don't bite off more than you can chew". If you work regular office hours, try to divide your work into chunks you can complete in a day. Try to build and test some sort of subsystem by the end of a week, and so on. It seems obvious, but it's amazing how many people don't even try to do this.

This has double benefits in reducing stress. First it lets you free your mind from clutching onto part-finished work. I've never been able to fully relax if I have remember where I've got up to for tomorrow; well, not and do any useful work the next day, anyway. The second benefit is the happy "kick" we all get from "closure". I get a physical sense of release when I've finished and tidied a piece of work; a feeling of "now I could do anything!".

So there are my rules. They are not a complete recipe, you must still allow sensible timescales; ensure you have the appropriate skills, tools and resources; and develop an good and clear relationship with your customer(s). I'm not saying that any project which implements these rules is guaranteed to succeed, but they can certainly help. And they can make doing it a lot more fun.

A footnote to this. While cruising the web recently, I came across the concept of ExtremeProgramming. While coming from a different direction to the above, it has an amazing amount of overlap. For more information about ExtremeProgramming see RonJeffries, KentBeck or the WikiWikiWeb.


See also ProgrammingStress, GoldenRule

There is a surprising amount of alignment between what you've put forward here and what the XP guys have been evangelizing. One thing that jumps out at me:

Your rule above about the simple bits lines up very well with JustSufficientImplementation and YouArentGonnaNeedIt. But it seems to run against the grain of WorstThingsFirst. While WTF doesn't seem to make it into the top five list of XP practices, it probably makes it into the top twenty, and has been a recurring part of our success applying XP. How can we distinguish between complex things that we should put off (hopefully) forever, and complex things that we should tackle right now to remove project risk?

Often when I am talking to people about why XP is so important, we focus on the need for sustainable success. In other words, I'm not so interested in the superhuman heroic efforts to bring a single troubled project in. I am interested in how we make success repeatable, over and over, and a regular part of how we do business. Managing stress levels is a key part of this, and these ideas bring this topic into focus. -- BillBarnett

... How can we distinguish between complex things ...

I think what's missing from the above description of StressFreeProgramming is (stealing from the AgileManifesto) customer collaboration, and working on the things that the customer (or ProductOwner in ScrumProcess) deems most important. That is how you distinguish between which complex things to avoid and which to tackle right now.
See also PragmaticProgrammer, OptimisticProgramming

EditText of this page (last edited March 10, 2006) or FindPage with title or text search