Anxiety Driven Software Development

sunnuntaina, tammikuuta 06, 2008

Have you ever spent a few days designing something and then asked yourself "is this really a good idea?" Do you have that moment of self doubt and then change your design? Do you do it because you didn't think you could deliver it on time, that it would be too difficult to implement, that it was fundamentally flawed or you didn't like what you were getting yourself into.
I spend a fair amount of time wondering if one of my designs is actually a good idea. A manager once referred to me as a worrier. Of course, the effect of all this worrying is that my code generally works very well. I haven't found all my bugs, but I have tested the feature dozens of times. I fear complex designs and fall back to tried and true methods or prototype and verify that my complex or novel solution will really work.
    // Example 1: Iterating
    void myFunction(List<String> stringList)
    {
        for ( String stringElement: stringList )
        {
            System.out.println( stringElement );
        }
    }
This example seems like a pretty safe piece of code. I only write code like this for examples now. I would look at this code and right away figure that a caller will eventually pass in a null stringList and crash my component. My iteration operations look more like example 2.
    //  Example 2: Iterating
    void myBetterFunction(List<String> stringList)
    {
        if ( stringList != null )
        {
            for ( String stringElement: stringList )
            {
                System.out.println( stringElement );
            }
        }
    }
Adding the if statement is such a trivial change that ensures this code will not crash my application as often. Some people will argue that this is merely a good coding practice. That the check is one of many that should appear in a developer's code. But what motivates me and other developers to add this code? Is it good training, professionalism, the dislike of fixing a dull bug, the fear of looking like a dolt to the rest of the team or something else?
This code is a far too simple example of how anxiety driven software development can benefit a project: good developers write stronger code to avoid simple problems. Algorithmic errors may still remain, but the algorithm will not fail because of an uninitialized parameter.
How do you choose a third-party library? Let's say you have three days to write a very simple user interface with Tomcat running on the server. Do you write you servlet layer using Struts, Tapestry, JSF or something else? Do you choose something you have been reading about or something you know very well? I go back to the library I know the best. I may want to try something new, but I don't know the tricks and traps so I go back to the familiar and ship on time and with a high level of quality. Again, one could argue that the choice of library was dictated by a logical process of elimination. I would argue that my fear of a late delivery dictated that I pick the library I knew best. Given more time I may have read more about other's opinions and write a prototype to verify that a different library will work well.
Fear of failure can be immobilizing. Software development moves far too quickly to allow a developer to become crippled because he is afraid to fail. You can't become immobile because others will simply pass you by. Using your anxieties to your advantage means that you advance along the path that is simplest and most proven. You don't need to worry that you'll get a dumb bug because you bullet-proofed your code. You don't have to worry that you picked the wrong UI library because you have used Tapestry in three other projects and you are rock solid. Instead, you choose the safe bet and code the project.
The risk is that you always go back to your safe bets rather than trying anything new. Writing great software requires taking risks. Riskier code often teaches far more than tried and true code. The reason is fairly obvious: tried and true code has been documented to death, there is nothing new or interesting to learn. Riskier code, like using a new design pattern or library, is an opportunity to try something different and grow. Knowing when to go safe vs new is a difficult problem.
Balancing new vs safe code is a skill. I usually go with safe code when I have very little time to implement a given thing or when I am doing the design work and the implementation will be turned over to significantly junior developers. The vision and spirit of a design is often difficult to impart in documentation. It requires some hands-on work by its creator to really drive home how it should operate. However, you don't always have the time to impart that vision sufficiently when turning over a design to a different team. Its their job to go off and do the implementation and so without the oversight or lots of communication then it is likely that their implementation and your vision will diverge. The divergence could be good if they figured out a few improvements or detrimental if they missed the point entirely. You just can't tell which way it is going to go, so safer code is better.
Novel code is best done when there is plenty of time to prove the concept out in a prototype. If you can't do a prototype then be sure to add time to the schedule for you to get the implementation right. That maybe one or two days depending on the design, but definitely add some room to the schedule.
On-line research is a very useful tool in the balancing act too. I often google for other people's impressions of using a pattern or a library. I often like following the herd. For example, I would rather use a library that has thousands of user, a forum and been around for a few years. Especially if I am going to be highly dependant on that library for a large amount of functionality. I am more willing to try a really new library for something small and isolated- easy to remove later.
Getting the opinions of friends, colleagues and managers is a good idea too. You will almost always find some strong opinions on nearly every technology. It also brings them into the design process earlier and gives you a feel for the ideas that will resonate with them in the design review. Having a lively discourse at a design review is good, but it isn't helpful if people are fundamentally opposed to certain approaches. Knowing this early in the design process is incredibly useful.
Setting expectations is the last aspect I will mention today. Its a good idea to brace people for why you chose to do something. I would rather tell my manager that I am doing something risky and pitch the benefits than say nothing. If you think that something is difficult, then say it is difficult so it isn't a shock if the schedule slips. If it is easy, then say it is easy. The effect is that the manager can trust your judgments and you can be trusted with more complex and interesting projects.
I worked with a really nice engineer awhile back. Everybody loved the guy, including me. The thing was that every time we had to do anything (write code, do a build, setup a new machine) he would just shake his head and start to moan about how it couldn't work because the machine was too small, there wasn't enough time, the code was too complex, the code didn't cover all the possible problems, it takes too long to build,we're all going to die but it really doesn't matter because eventually the sun will expand and scorch our entire planet right off the universe and no one will know that we ever existed. Ok, the last one I made up, but you get the picture. He made it harder on himself because he believed that everything was going to fail and he said it to management every day. Yet the company continued to succeed and grow even though we were faced with constant doom. His opinions were discounted until they became a kind of constant background noise. The point is that setting expectations must be done in a positive and objective way so that people listen to you when you have found serious issues.
Anxiety driven software development is a conservative decision tree. If there is plenty of time, try something risky after researching carefully other developer's experiences and prototyping if possible. If there is little time, go to the thing you have the most experience with so that the job can get done on time. Go with simpler designs when creating a design that you will not be involved in overseeing or implementing. Listen to your team, they have good ideas. Finally, set expectations objectively describing the risks and benefits to an implementation or design.
Remember that taking risks is necessary. You can't get anywhere or do anything new if you don't take risks. Taking foolish risks though is what kills a development cycle. Balance is the key.
I'll leave you with two quotes:
The pessimist sees difficulty in every opportunity. The optimist sees the opportunity in every difficulty.
- Winston Churchill
Great things are not done by impulse but by a series of small things brought together
- Vincent Van Gogh

You Might Also Like

0 comments