white nautilus icon

Agile Development Outside-In

Incremental-development

Paging

Next:
Plan incremental software releases in system spans
Previous:
Developing iteratively to release incrementally

Referenced Concepts

Referenced Techniques

Page Information

Manage feature scale

Software releases, and agile releases in particular, are generally planned with little or no specific detail on the features in that release. Characteristics of a particular feature can make it time consuming and expensive to design and develop, or relatively simple. Managing these characteristics throughout the design and development process is what I'll call managing scale.

The ideal feature may not be

I hope you're reading this book because you ultimately want to see great software built and in use by your customers. So in spite of all the words in this book dedicated to deciding what to build and evaluating if it was the right thing to build, really the important thing is actually building something.

When we do the work necessary to understand our business goals, our users and their goals, and the work we need to support in the system we're building, we can often clearly see an ideal solution.

That ideal solution is compelling. It becomes a bit of a holy grail to quest for. We often set out in out on our quest to build this ideal product by dividing it up into the ideal features that make up this ideal product. We then estimate the cost to design and develop each feature. However, the ideal solution may not be within our budget to construct. It may take more time than we have to meet our release and return on investment goals. It may take more development hours than is economical to spend for a particular feature. Or simply placing so much focus on designing and building one particular ideal feature may distract us from looking at the other features we need. This concentration on a single feature pulls our focus from evaluating the product as a whole and all the features the product will need to be successful. This can be risky.

Designing and building each feature in its ideal form may be unacceptably time consuming, expensive, or risky.

Let's dig a little deeper into this problem.

Of course we want the best product possible. When using incremental development a common approach is to start with a list of features for a product and estimate the time to build each feature based on high level design and assumptions about how that feature might look and behave. Given those development estimates, plus some suitable time for contingency to account for unknown risks, we as a team can then come up with how many of these features we can place in a release of our software. That sounds reasonable, right?

This is where things go bad.

Prioritizing features doesn't always work well

The business paying for the software might like to see the release in a certain amount of time. Let's say 6 months. When we add up the development times plus the contingency for the features it might add up to 12 months. Ouch.

One obvious solution might be to prioritize features and simply not build some of them. Then we'd still get an ideal product with the most important ideal features, right? But, prioritization can be surprisingly difficult. Considering the detail that we have, all the features look necessary. Prioritizing one over the other might be easy in some cases, but hopelessly problematic in others.

Let take an example far away from software. Let's say we're building a car. Now I know cars aren't designed and built like software, but suppose for a minute they were. Suppose in front of you was an empty parking space, and a few months from now you'd like to see car there. Let's start by building a backlog of the features you'd include in your car:

I'll stop there, since there are lots of basic features that describe a car, I think you can imagine enough for us to continue. A feature list like this lacks detail. Now if I were to ask you to prioritize a list like this, could you? Is the engine more important than the transmission? Is the steering wheel more important than the breaks? Aren't questions like this just silly?

Often questions about the priority of features in scope seem just as silly, especially for a new product that needs a large set of features constructed to be viable. Yet, it's common to ask business stakeholders to perform this sort of prioritization.

De-scoping features isn't always possible

Assume we were able to prioritize features sufficiently to come up with a release we could live with. The interesting thing about prioritizing features for a product release is that the attention isn't on the top of the list - because these those are the features we know will make it in the release. The emphasis is on the bottom of the list; the cutoff area between features that make it and features that won't. To get an acceptable set of features for a release, lots of heated discussion generally happens around these features. It's common for people making those decisions to push hard on the development estimates for those features.

Assuming software development goes as it often does, toward the end of development time we find that we're a little behind schedule. To meet our schedule we'll need to de-scope a few of these features. Conversations at this time usually don't go well. The features left in scope are all necessary. Decision makers are often left with the problem described when prioritizing car features. They may be asked to de-scope either the steering wheel or the brakes… or more likely if it's near the end of the list, the headlights or the brake lights. These aren't just hard choices to make, those making them know that the resulting product may likely be unacceptable.

This is when business stakeholders usually call for more overtime, offer bonuses, and silently make a vow to consider off-shoring next time - or bringing it back on-shore if this was already the next time.

Features have a hidden dial

Let's go back to our car example. We all know that there's a huge variance in the cost of cars. Yet they usually have the same general features: engines, transmissions, tires, etc. So what makes one car more expensive than another?

To understand that we need to look closely at the specifications of those features - the features of the features. Bigger engines cost more money than smaller engines. Automatic transmissions cost more than standard transmissions. Large, hard, low-profile, rated tires cost more than skinny, soft ones that slide in the rain. So, while a car always needs an engine, transmission, and tires, the choices the manufacturer makes about those things, as well as all the other features of the car, drastically affect the cost of that car.

I'll call that hidden dial in a feature the scale of that feature. For any feature in a car, or in software, we can scale it up, or scale it back. For the features in our car or in our software we can control cost by scaling the feature back.

To control the cost of building all the necessary features in a software release, scale the features back to economical levels.

It's not all about money

While scaling back a feature may allow us to buy it for less, it's not just about the cost of the feature. Let's revisit our story above where we were nearing the end of our release, but unfortunately we're running behind schedule. Let's assume we knew about feature scale, so we scaled the features appropriately before estimated the time and money to build them. We've built most of the features already, except for the last few. Knowing now about the hidden scale dial we now have two choices: de-scoping some of the remaining features, or further reducing the scale of the remaining features.

Since it's the near the end of the release, there's only a few features left. If we reduce the scale of those features to a level that will allow us to deliver on time, we may be back in the same situation we were before - delivering a product that may be unacceptable. Using our car example again, we may be forced to duct tape flashlights to the hood to use as head lights, and cover the windows clear plastic sheeting instead of glass. This looks bad on a car - especially an otherwise high quality car like a Mercedes Benz. Sadly, software often ends up in this position with many well designed and built features and few that look like a clumsy afterthought.

Happily we're designing and building software, not cars. One of the options we have to manage this risk is to scale the features to a very low level early in the development cycle then gradually add scale back to the features. As the design and development of the software release proceeds, the software scale continuously improves. When we near the end of the release development cycle, and development is a little behind we now have most features up to full scale. We need not substantially reduce the scale of some features, but only slightly reduce the scale of a few features. We'd hope that slight scale reduction was not easily perceived by users, or the business paying for the software.

Let's look back at our car and pretend its metal was as malleable as software. If I knew at the end of the release I needed a pretty good car, and I took on this strategy, I might choose to scale the features down and get the car built as quickly as possible. My first car might have a tiny engine, usable brakes, and a steering wheel, but the driver seat was a lawn chair bolted to the floor. I could drive it down the street without a roof or doors, so left those off. I was able to build this sort of car with all the basic features I needed rather quickly, and now I have a lot of time left.

One at a time I begin pulling and replacing some features, and adding in some I could initially do without. The engine gets bigger, the car gets doors and a roof, the lawn-chair initially gets replaced with a simple fabric seat, then towards the end of the release replaced again with a leather seat. At release time I have a pretty good car. There's still more I wished I could have added, but all the features I needed are present, and I haven't really skimped on any of them. This strategy of scaling features up over time seemed to work.

Reduce scale of features aggressively early in a software release development cycle, then build up scale as the release design and development continues.

Given that there's some good reasons to reduce the scale of a feature both when planning a software release, and while designing and constructing the release, let's look closer at how we might thin the scale a of a particular software feature. feature thinning guidelines describe four basic areas to look at when making choices to thin the scale of a feature.

Feature thinning guidelines

Feature thinning guidelines help identify characteristics of a feature that may deferred or removed making the feature lighter, simpler, and faster to develop. Use feature thinning guidelines to thin proposed features during release planning, and choosing and designing specific work to iteratively develop during iterative release development.

These feature thinning guidelines are based on Gerard Meszaros Storyotype approach for splitting bloated XP stories.

Whether you’re using eXtreme Programming and user stories or not, the four categories identified by Gerard offer a simple way to thin features or stories. Looking at a proposed product feature, these guidelines offer a simple way to divide up characteristics of the feature. These characteristics identify perforations in the feature that make it easy to divide up. I’ve taken liberty with the names of the characteristics so that I could more easily remember and apply them. Hopefully you can to.

Imagine you’re making choices about scale on each particular feature of a car. The characteristics of the feature we’ll look at are:

  • Necessity: what minimal characteristics are necessary for this feature? For our car a minimal engine and transmission are necessary – along with a number of other features.
  • Flexibility: what would make this feature more useful in more situations? For our car, optional all wheel drive would make it more useful for me to take on camping trips. A hatchback might make it easier for me to load bigger stuff into the back.
  • Safety: what would make this feature safer for me to use? For our car making the brakes anti-locking would make the car safer.
  • Comfort, Luxury, and Performance: what would make this feature more desirable to use? I’d really like automatic climate control, the seats to be leather, and a bigger V6 engine.

If we were buying and using a car, we all need the necessities. However, we all may have different opinions on what’s more important between flexibility, safety, and comfort, luxury, or performance. We want varying degrees of all those things up to what we can afford. We expect each feature of the car to have at least the necessities and some of all the other categories.

Some characteristics don’t easily fit into one category. Is all-wheel drive a safety characteristic or a flexibility characteristic? I guess it depends if it’s raining hard outside, or if I choose to drive the car off road to go camping.

Now let’s look at a high level software feature and apply some thinning guidelines. Let’s choose a feature in software we likely all use. We’ll express the need for this feature as a user task – since the feature we build needs to support that user task.

Send an email message

We’ll look at how these four guidelines might apply to the feature or features that support this task, and how these guidelines might apply while planning and estimating a release, and while iteratively designing and building the software.

Necessity

To identify what’s necessary look at the user of the software and the simplest possible use. Start by looking at the task the user intends to perform. Write a simple user scenario or task case to understand the steps of usage. Identify only the absolutely necessary steps that allow the task to be considered successful. A feature that supports necessity supports only those necessary steps.

Using our "send an email message" task, success for me is to get a message sent.

The steps I as a user might likely follow would be to:

  1. Indicate I’d like to send a message
  2. Indicate who I’d like to send the message to
  3. Write the message
  4. Indicate I’d like the message sent now.

I’ve really cut back here. Notice I didn’t enter a subject line, send it to multiple people, carbon copy anyone, or add any attachments. It’s likely I wouldn’t choose to buy a product that did only those things. But, if the product couldn’t do those basic things, well, that would just be silly.

If we described a "send an email message" feature as having just those things, it would have only the necessities.

For any given software feature, we can thin it to include only its necessities.

When planning and estimating a release: make sure each feature has support for at least the necessities.

When designing and incrementally building your software: initially introduce a new feature into the system using a necessity-only feature or user story.

Flexibility

To identify specific options that make the feature more flexible look back at the user and possible use of the feature. For the task the user is performing, write a simple user scenario or task case. For each step in that task, ask what your user might alternatively do, or do in addition to the actions performed in that step. In use case writing these might be considered our alternative steps. A feature that supports some degree of flexibility supports some or all of these alternative uses.

Using our "send an email message" task, I might optionally type a subject line – actually I usually do that, but I guess if you press me, it’s not really a necessity. I might optionally send the message to many people. I might optionally carbon copy or blind copy others. I might send an attachment, save it to my sent folder, or forward someone else’s message.

Adding support for some or all these "might dos" adds flexibility to the feature.

When planning and estimating a release: consider how much flexibility the feature might likely need and estimate development time to include that assumption about flexibility.

When designing and incrementally building: split away flexibility from features to add later as individual flexibility features or user stories.

Safety

To identify specific options that make the feature more safe look again to the user and use. For the task the user is performing write a simple user scenario or task case. For each step consider things that could go wrong. How might our user enter data incorrectly and cause trouble downstream? What does the business paying for the software want to make sure the user doesn’t do? Characteristics that help the user by validating or correcting input, or by applying business rules that restrict or block some actions are considered safety features. A feature that contains this sort of input validation, correction, or business rule applications has some amount of safety built in.

Using our "send an email message" task, if I typed in an improperly formatted email address, sending the message would fail. I might appreciate it if the email address were validated. In some corporations large attachments are considered unacceptable because they bloat email storage, and consume lots of bandwidth. If the system were to stop me from attaching a large file, the business paying for this software might appreciate that. Adding these sorts of characteristics to the "send an email message" feature adds safety. Features in our software often have some number of safety characteristics.

When planning and estimating a release: consider how much safety the feature might likely need and estimate development time to include that assumption about safety.

When designing and incrementally building: split away safety from features to add later as individual safety features or user stories.

Comfort, Performance, and Luxury

To identify specific options that make the feature more pleasant to use look again to the user and use. For the task the user is performing write a simple user scenario or task case. For each step consider things that make the step easier to accomplish, faster to accomplish, or more fun to accomplish. You may have to base your decisions on what’s easier, faster, or more fun based on what the feature already looks like, or what’s considered the bare necessity feature. It helps to look at similar or competitive products to identify these areas for improvement.

Using our "send an email message" task, I really hate typing the same email addresses over and over. It would be nice if the system auto-completed addresses I’d used before. I’m a rotten speller, and my grammar aint so good. Could the system check my spelling and grammar in the email message and subject line? Can I insert amusing smiley icons into the message? Adding these sorts of characteristics to the "send an email message" feature adds comfort, performance, and luxury. I’ll like this product much better if it has some of these things.

When planning and estimating a release: consider how much comfort, performance, and luxury a feature might need. Estimate development time to include that assumption about comfort, performance, and luxury.

When designing and incrementally building: split away comfort, performance, and luxury from features to add later as individual features or user stories.

Estimates at the release level become budgets

The estimates given against prospective features to support tasks will serve as development time budgets during iterative design and development. For now, use these estimates to size and plan releases that will be successful in the eyes of their target users and the business paying for the development. As you begin to make specific design decisions for the features to support users’ tasks, let the budget set limits for the amount of flexibility, safety, and comfort, performance, or luxury you add.

Thinning and Building Up Features During Iterative Design and Development

When we set out to build a software release, we make decisions to try and come up with a set of features which will be both feasible to build in the time available, and make the product as valuable as possible both economically to the business paying for the software and functionally to the user constituencies who will use the software.

When we choose those features and make our plans, we do so without detailed knowledge of exactly how each feature may ultimately look and behave in the software and exactly how much time each feature may take to develop.

As we design and build more features we may discover better ways to build features, opportunities for other high value features, or omissions of features we subsequently understand may be critical.

While we're busy designing and building a software release, the world around us isn't standing still. Competitors may release new software or features we must react to. We may come to understand more about our users or our business that causes us to question our feature choices. Other demands on our available design and development time may reduce the time budget we have to complete a release.

Uncertainty about specific feature design and development time along with high likelihood of change requires active management and adaptation in the decisions we make about specific feature characteristics.

If we try to battle uncertainty by resolving more details about feature design before planning the release, we risk delaying the beginning of that release. While we may be more confident in our development estimates, we're certainly not ensured of their accuracy. In fact they're still likely wrong. We may be tempted to reduce risk by padding development times to a more comfortable level, which increases the time to delivery, the cost of the product, and may substantially reduce the return on investment for the product.

If we proceed with feature design and development naively, we're likely to find ourselves with a subset of our features built as we'd anticipated, or some other fraction of features as we're faced to make the choice to de-scope or scale down. The result is often an incoherent product where necessary features are either missing or designed and implemented poorly relative to other features in the product.

An effective strategy for designing and developing during release is implement all intended features scaled down to bare necessities, then gradually adding flexibility, safety, comfort, performance, and luxury.

This design and development strategy has the effect of gradually bringing the software into focus.

Software design and development is an art

When I was very younger I expected I'd be a graphic artist. I spent a lot of time drawing. One of the mistakes I often made was to picture in my head what I wanted to draw and then begin to draw it. I'd render my subject in fairly precise detail. If I were drawing a dinosaur - which I often did when I was a kid, I might start with the head. A T-Rex head is big and mouth full of sharp teeth which I'd take quite a bit of time drawing. As I moved on, I'd eventually get to the neck, body, arms, legs, and tail. This is when I'd figured out I'd got the proportions all wrong. The head was generally way too big for the body. The shape of the whole dinosaur looked as though I was looking at it through a funhouse mirror. Then my mom would call me to dinner and I didn't have time to fix or finish it. So in addition to the odd shape, there were parts, like the head, in extreme detail, and other parts un-drawn or with nearly no detail. This wasn't the scary dinosaur I was looking for.

When developing software iteratively, this is often one of the outcomes. Slightly misshaped software with high quality of detail in some places, and lots of rough spots elsewhere.

Let's go back to our budding artist. As I continued to draw, and got a little help, I learned that artists often sketched out the basic shape of the thing they were drawing. They resolved the positioning and proportions of elements on the page first. Painters often created an under-painting or a preliminary painting that let them see the basic form, colors, and contrast in the painting. Then the artist might proceed to work on different parts of the painting, moving from one part to another, spending time where it seemed sensible, but gradually working on the whole drawing as a single unit. A graphic artist with a deadline might look to the important, or focal, parts of the work and put more time there. She knows this was where the viewer's eyes would spend more time. She could pace herself to create the best work possible given the allotted time.

Software design and development works well when it follows the same strategy.

emerging mona

A painting emerges from original composition work then is refined over time.

Mapping uncertainty to the software release

There's a fairly obvious law that we often forget to accommodate. It's difficult to predict outcomes and events in the distant future and easier to predict them in the near future.

Barry Boehm first described the Cone of Uncertainty to illustrate how uncertainty about development estimates decreases over time. Steve McConnell later elaborated on this to say that the same applies for requirements.

uncertainty decreases over time

Uncertainty about what to build and, consequently, development estimates decreases over time.

The iterative development style of Agile development adapts to this uncertainty by not focusing early on accurate estimates, since they likely won't be, and not focusing too hard on accurate requirements, since they likely won't be.

If we acknowledge and accommodate what looks like an obvious truth and map our feature thinning guidelines to this we're able to come up with a useful strategy for thinning and building back-up features during the time span of a single incremental release.

three trimester release development

Scale up functionality over time within a release timebox. Divide the timebox into three parts, and focus on different elements of scale during those three parts.

The shape of iterative release design and development

To effectively manage the design and development of features throughout a typical release cycle we'll need to aggressively manage the scale of each feature. In the Agile development approach of eXtreme Programming, we might consider the feature or features that support each user task a user story. Built in an ideal form, or in a scaled down form we'd intended for our release, they might be very big stories. We'll use our thinning guidelines to split these big features or big stories into lots of smaller stories. These are the stories we'll focus on during the each iteration of development.

This ideal release design and development strategy breaks the release period in thirds - a three trimester gestation period. Please excuse the bad metaphor.

Laying foundation with necessities

Focus first on carving away all the necessities in each feature of the software. Use the first part of the release cycle to complete the design and development of all these necessities. If this is a new product and you've used a span plan to help plan this release, you'll have implemented the first system span. If this is a subsequent release, you'll have implemented some range of features that span the entire release's functionality.

Alistair Cockburn describes this as a walking skeleton; although this term is often used to indicate the design and implementation of basic architectural necessities. This walking skeleton could be considered a functional walking skeleton in addition to an architectural one.

There's no need to split the features further at this point. When managing a feature backlog, I may place a necessity feature into the first iteration, and then leave one remaining feature for "all the rest" of the intended feature characteristics. You'll split these later. There's no need to predict how they need to split now.

Filling in with flexibility and safety

By a third of the way in to your release cycle, the end of the first trimester, you now have the necessities completed for your release. You can see the general shape of your software. You've implemented most of your basic domain objects. You've implemented most of the screens of your software and can now see the navigation structure clearly. With luck the basic architecture of your software is complete. This is a good time to begin validating basic interaction design using usability testing, and system performance and scalability using functional testing and load testing. You've mitigated a lot of risk by doing this. Pat yourself on the back.

Now go back through your features and carve out flexibility and safety additions to the features you've implemented. Keep the pieces you carve out reasonably small. Don't do your carving all at once. You might carve an iteration or two ahead, but don't plan the entire rest of your release.

Refining with comfort, performance, and luxury

By two-thirds of the way through, the second trimester, you're seeing a pretty solid product. It may not be quite as sexy as you'd like, but it works well. You've been able to validate the scalability and performance, and adapted to some unforeseen problems there. You've been performing simple end-to-end usability testing and stumbled across some features you'd overlooked. You also identified some changes to navigation that will make things easier to use. Along the way you've identified areas in the software where you can significantly improve the users' experience. If the software really had to release now, it could, but it wouldn't be your best work.

If you have new features to implement, immediately carve off, design, and build necessities. Then move through to flexibility and safety additions for those features.

Go back through all other features and carve off additions that will add comfort, performance, and luxury. Now more than ever your business goals and user models will give you guidance on where best to spend the remainder of your time. Look for additions that benefit focal users performing focal tasks that directly support business goals.

As the release date nears, shift designers and developers into validation roles testing and retesting the software for functional and usability errors.

Always releasable?

There's a goal in eXtreme Programming that the software we're designing and building be always releasable. This goal is adopted by many projects working in an Agile manner. You'll notice that the "trimester" strategy may not leave the software always releasable. During the release's first and second trimester the software wouldn't normally be considered viable. Unlike childbirth, these three cycles don't need to take 9 months. I've typically practiced this pattern using a 45 to 90 day cycle. You can scale your cycle depending on the complexity of your product. Let your release planning help guide the decisions about what a viable product might be.

Thinning is a risk management strategy

No matter how you look at it, it often takes longer to split up a feature into little parts and develop it a piece at a time. It often takes major rearranging or rewriting of existing features to accommodate new flexibility and safety characteristics. Sometimes a comfort, luxury, or performance feature may result in complete redesign of both user interface and underlying code.

Thinning and building up allows deferring of design decisions when uncertainty is at its lowest till later in the release cycle. It affords the earliest possible validation of the functional scope of the release. It affords the earliest possible validation of underlying architecture and domain objects. It affords early testing of usability, performance, and scalability. It preserves time near the end of the release cycle to react and adapt to what you learned from building the software, and what might have changed in the world around you while you were building.

To better manage risk, use a thinning and building up strategy to coordinate the ongoing design and development of features during a release development cycle.

comment on this page via email comment

Next Topic: Plan incremental software releases in system spans >>

<< Previous Topic: Developing iteratively to release incrementally