Rob Moffat
Rob Moffat Author of Risk-First Software Development and full-stack developer currently working in the UK.

Development Process

In the previous section we introduced some terms for talking about risk (such as Attendant Risk, Hidden Risk and Internal Model) via a simple scenario.

Now, let’s look at the everyday process of developing a new feature on a software project, and see how our risk model informs it.

A Toy Process

Let’s ignore for now the specifics of what methodology is being used - we’ll come to that later. Let’s say your team have settled for a process something like the following:

  1. Specification: a new feature is requested somehow, and a business analyst works to specify it.
  2. Code And Unit Test: a developer writes some code, and some unit tests.
  3. Integration: they integrate their code into the code base.
  4. UAT: they put the code into a User Acceptance Test (UAT) environment, and user(s) test it.
  5. … All being well, the code is Released to Production.

A Simple Development Process

Can’t We Improve This?

Is this a good process? Probably, it’s not that great: you could add code review, a pilot phase, integration testing, whatever.

Also, the methodology being used might be Waterfall, it might be Agile. We’re not going to commit to specifics at this stage.

For now though, let’s just assume that it works for this project and everyone is reasonably happy with it.

We’re just doing some analysis of what process gives us.

Minimising Risks - Overview

I am going to argue that this entire process is informed by software risk:

  1. We have a business analyst who talks to users and fleshes out the details of the feature properly. This is to minimize the risk of building the wrong thing.
  2. We write unit tests to minimize the risk that our code isn’t doing what we expected, and that it matches the specifications.
  3. We integrate our code to minimize the risk that it’s inconsistent with the other, existing code on the project.
  4. We have acceptance testing and quality gates generally to minimize the risk of breaking production, somehow.

A Much Simpler Process

We could skip all those steps above and just do this:

  1. Developer gets wind of new idea from user, logs onto production and changes some code directly.

A Dangerous Development Process

We can all see this might end in disaster, but why?

Two reasons:

  1. You’re Meeting Reality all-in-one-go: all of these risks materialize at the same time, and you have to deal with them all at once.
  2. Because of this, at the point you put code into the hands of your users, your Internal Model is at its least-developed. All the Hidden Risks now need to be dealt with at the same time, in production.

Applying the Process

Let’s look at how our process should act to prevent these risks materializing by considering an unhappy path, one where at the outset, we have lots of Hidden Risks. Let’s say a particularly vocal user rings up someone in the office and asks for new Feature X to be added to the software. It’s logged as a new feature request, but:

  • Unfortunately, this feature once programmed will break an existing Feature Y.
  • Implementing the feature will use some api in a library, which contains bugs and have to be coded around.
  • It’s going to get misunderstood by the developer too, who is new on the project and doesn’t understand how the software is used.
  • Actually, this functionality is mainly served by Feature Z
  • which is already there but hard to find.

Development Process - Exposing Hidden Risks

The diagram above shows how this plays out.

This is a slightly contrived example, as you’ll see. But let’s follow our feature through the process and see how it meets reality slowly, and the Hidden Risks are discovered:

Specification

The first stage of the journey for the feature is that it meets the Business Analyst (BA). The purpose of the BA is to examine new goals for the project and try to integrate them with reality as they understand it. A good BA might take a feature request and vet it against his Internal Model, saying something like:

  • “This feature doesn’t belong on the User screen, it belongs on the New Account screen”
  • “90% of this functionality is already present in the Document Merge Process”
  • “We need a control on the form that allows the user to select between Internal and External projects”

In the process of doing this, the BA is turning the simple feature request idea into a more consistent, well-explained specification or requirement which the developer can pick up. But why is this a useful step in our simple methodology? From the perspective of our Internal Model, we can say that the BA is responsible for:

BA Specification: exposing Hidden Risks as soon as possible

In surfacing these risks, there is another outcome: while Feature X might be flawed as originally presented, the BA can “evolve” it into a specification, and tie it down sufficiently to reduce the risks. The BA does all this by simply thinking about it, talking to people and writing stuff down.

This process of evolving the feature request into a requirement is the BA’s job. From our Risk-First perspective, it is taking an idea and making it Meet Reality. Not the full reality of production (yet), but something more limited.

Code And Unit Test

The next stage for our feature, Feature X is that it gets coded and some tests get written. Let’s look at how our Goal In Mind meets a new reality: this time it’s the reality of a pre-existing codebase, which has it’s own internal logic.

As the developer begins coding the feature in the software, they will start with an Internal Model of the software, and how the code fits into it. But, in the process of implementing it, they are likely to learn about the codebase, and their Internal Model will develop.

Coding Process:  exposing more hidden risks as you code

At this point, let’s stop and discuss the visual grammar of the Risk-First Diagrams we’ve been looking at. A Risk-First diagram shows what you expect to happen when you Take Action. The action itself is represented by the shaded, sign-post-shaped box in the middle. On the left, we have the current state of the world, on the right is the anticipated state after taking the action.

The round-cornered rectangles represent our Internal Model, and these contain our view of Risk, whether the risks we face right now, or the Attendant Risks expected after taking the action. In the diagram above, taking the action of “coding and unit testing” is expected to mitigate the risk of “Duplicating Functionality”.

Beneath the internal models, we are also showing real-world tangible artifacts. That is, the physical change we would expect to see as a result of taking action. In the diagram above, the action will result in “New Code” being added to the project, needed for the next steps of the development process.

Integration

Integration is where we run all the tests on the project, and compile all the code in a clean environment, collecting together the work from the whole development team.

So, this stage is about meeting a new reality: the clean build.

At this stage, we might discover the Hidden Risk that we’d break Feature Y

Integration testing exposes Hidden Risks before you get to production

User Acceptance Test

Next, User Acceptance Testing (UAT) is where our new feature meets another reality: actual users. I think you can see how the process works by now. We’re just flushing out yet more Hidden Risks.

UAT - putting tame users in front of your software is better than real ones, where the risk is higher

  • Taking Action is the only way to create change in the world.
  • It’s also the only way we can learn about the world, adding to our Internal Model.
  • In this case, we discover a Hidden Risk: the user’s difficulty in finding the feature. (The cloud obscuring the risk shows that it is hidden).
  • In return, we can expect the process of performing the UAT to delay our release (this is an attendant schedule risk).

Observations

First, the people setting up the development process didn’t know about these exact risks, but they knew the shape that the risks take. The process builds “nets” for the different kinds of Hidden Risks without knowing exactly what they are.

Second, are these really risks, or are they problems we just didn’t know about? I am using the terms interchangeably, to a certain extent. Even when you know you have a problem, it’s still a risk to your deadline until it’s solved. So, when does a risk become a problem? Is a problem still just a schedule-risk, or cost-risk? We’ll come back to this question presently.

Third, the real take-away from this is that all these risks exist because we don’t know 100% how reality is. We don’t (and can’t) have a perfect view of the universe and how it’ll develop. Reality is reality, the risks just exist in our head.

Fourth, hopefully you can see from the above that really all this work is risk management, and all work is testing ideas against reality.

In the next section, we’re going to look at the concept of Meeting Reality in a bit more depth.