Tuesday, 15 May 2012

Uncertainty and Risk in Software Development (1 of 3)

To develop high quality software consistently and reliably is to learn how to master complexity.  You master complexity when you understand the different sources of uncertainty and the different risk characteristics of each uncertainty.  Uncertainties introduce delays in development as you attempt to resolve them.  Resolving uncertainties always involves alternative designs and generally affects your base architecture.  Poor architecture choices will increase code complexity and create uncertainty as future issues become harder to resolve in a consistent manner.

Confused?  Let's untangle this mess one issue at a time.

The key principle here is that uncertainty will introduce delays in development.  Let's look at the average speed of development.  The Mythical Man Month conjectures that an average developer can produce 10 lines of production code per day regardless of programming language.  Let's assume for the sake of argument that todays developers can code 100 lines of code per day.  Development speed is limited because of meetings, changed and confused requirements, and bug fixing.  

Suppose we take a working 200,000 line program and print all the source code.  If we ask a programmer to type this code in again, they are likely to be typing at least 2,000 lines of code per day.  So to develop the program from scratch would have taken 2,000 man days, but to type it in again would only take 100 man days.

The time difference has to do with uncertainty.  The developer that develops the application from scratch faces uncertainty whereas the developer that types in the application faces no uncertainty. 

If you have ever done mazes you discover that to do the maze from the entry to the exit point involves making decisions, and this introduces delays while you are thinking.  However, try doing a maze from the exit back to the entry, you will find there are few decisions to make and it is much faster.  Fewer decisions from resolving uncertainty faster leads to fewer delays.

It is always faster to do something when you know the solution.

Sources of Uncertainty
The major sources of uncertainty are:
  • Untrained developers
  • Incomplete and inconsistent requirements
  • Technical challenges

We use the term "learning curve" to indicate that we will be slower when working with new technologies.  The slope of the learning curve indicates how much time it will take to learn a new technology.  If you don't know the programming language, libraries/APIs, or IDE that you need to work with this will introduce uncertainty.  You will be constantly making syntax and semantic errors as you learn new languages, but this should pass rather quickly.  What will take longer is learning about the base functionality provided by the libraries/APIs. In particular, you will probably end up creating routines only to discover that they are already in the API.  Learning a new IDE can take a very long time and create serious frustration along the way!

Incomplete and inconsistent requirements are a big source of uncertainty.  Incomplete requirements occur when you discover new use cases as you create a system.  They also occur when the details required to code are unavailable, i.e. valid input fields, GUI design, report structure, etc.  In particular, you can end up iterating endlessly over GUI and report elements – things that should be resolved before development starts.  Inconsistent requirements occur because of multiple sources of requirements as well as poor team communication.

Technical challenges come in many forms and levels of difficulties.  A partial list of technical challenges includes:
  • Vendor APIs that are poorly documented
  • Vendor APIs that are buggy
  • Interfacing incompatible technologies
  • Insufficient architecture
  • Performance problems 
In all cases technical challenge is resolved either by searching for a documented solution in publications, on the Internet, or by trial an error.  Trial and error can be done formally or informally but involves investigating multiple avenues of development, possibly building prototypes, and then choosing a solution.  While you are resolving a technical challenge your software project will not advance.
A common source of uncertainty is insufficient architecture.  Insufficient architecture occurs when the development team is not aware of the end requirements of the final software system.  This happens when only partial requirements are available and/or understood by the developers.  The development team lays down the initial architecture for the software based on their understanding of the requirements of the final software system.

Subsequently, clarified requirements or new requirements make developers realize that there was a better way to implement the architecture.  The developer and manager will have a conversation that is similar to:

Manager: We need to have feature X changed to allow behavior Y, how soon can we do this?

(pause from the developer)

Developer:  We had asked if feature X would ever need behavior Y and we were told that it would never happen.  We designed the architecture based on that.  If we have to have behavior Y it will take 4 months to fix the architecture and we would have to rewrite 10% of the application.

Manager:  That would take too long.  Look I don't want you to over engineer this, we need to get behavior Y without taking too much of a hit on the schedule.  What if we only need to have this for this screen?

(pause from the developer)

Developer:  If we ONLY had to do it for this one screen then we can code a work around that will only take 2 weeks.  But it would be 2 weeks for every screen where you need this.  It would be much simpler in the long run to fix the architecture.

Manager:  Let's just code the work around for this screen.  We don't have time to fix the architecture.

The net effect of insufficient requirements is that you end up with poor architecture.  Poor architecture will cause a technical challenge every time you need to implement a feature that the architecture won't support.  You will end up wasting time every time you need to work around your own architecture.

Management will not endorse the proper solution, i.e. fixing the architecture, because they have a very poor understanding that every work around that is made is pushing the project closer and closer to failure.  Eventually the software will have so many work arounds that development will slow to a crawl.

It is interesting that the project will probably fail, yet, soon enough the organization will attempt to build the same software using the same philosophy.

There is never enough time to get the project done properly, but there will always be enough time to do it again when the project fails.

  • Uncertainty comes from several sources
    • Untrained personnel (language, API, IDE)
    • Inconsistent and incomplete requirements
    • Technical challenges
Next part (2 of 3)
  • Defining and understanding risk
  • Matching uncertainties and risks