Category: Uncategorized

  • Walking Skeletons in Software Lead to Amazing Results

    Four weeks into a project, we had automated 70% of our order approvals. Sounds great. Except we could have automated 35% of them in five days, and we didn’t.

    That gap haunts me. Not because of the engineering. The engineering was fine.

    It haunts me because of the five people on the order processing team who spent three extra weeks doing work that a computer could have done for them. And the sellers who waited days for their products to reach buyers, products they had poured weeks of effort into creating.

    This is what happens when you build software from the inside out. You assemble each of the parts, then put them all together at the end.

    It works. It’s logical. And it delays value for everyone.

    There is a better way. Slice your features thin, end to end through every layer, and deliver them one at a time. You will ship value in days instead of weeks. You will reduce risk. And you will be amazed by what happens then.

    Cockburn calls this a walking skeleton. The Pragmatic Programmers call this style tracer bullets

    How do you just start thinking in this daily habit?

    One of the first things you can do is to armchair your features after you are done. When you have completed a feature, especially one that took longer than you expected, think about how else you could have rearranged the work, so that you could confidently share your work every day.

    It may seem like you are playing armchair quarterback when you go back after you are done. The work is already complete, and now you have hindsight as your companion and colleague. Nonetheless, doing this exercise will help you start to think in smaller slices. It will start to change the way you think.

    Learning this way is one of the fastest ways to master something new. Often called trial and error, we should think of it as trial and feedback.


    Order Approvals: Four Weeks or Five Days

    I was working with a marketplace for digital products. Once a purchase is approved, these products are available for immediate delivery. Sellers put sweat and tears into building these products. Weeks of effort distilled into something a buyer could access in seconds.

    That instant delivery created a fraud problem. Someone buys a product with a stolen credit card, downloads it immediately, and the seller loses the product and the revenue. Their sweat equity just evaporated.

    To fight this, the company put together a team to review every order before it was fulfilled.

    As the business grew, so did the team, the workload, and the bottleneck. Buyers were waiting a day or two for products they were expecting instantly.

    Buyers called the support line. Support escalated to the approval team. The approval team fell further behind. And sellers watched their hard work sit in limbo, waiting on a process they couldn’t see or control.

    We put together a project to automate the review. We identified three rules:

    1. Rule 1 handled 15% of orders. It was complicated.
    2. Rule 2 handled 35% of orders. It was straightforward.
    3. Rule 3 handled 20% of orders. The complexity was somewhere in between.

    Orders that didn’t match any rule would still go to human review. Together, the three rules would automate about 70%.

    The team estimated three weeks. It took four. And during those four weeks, nothing changed for the humans doing the reviews. They were working harder, the orders were climbing, and there was no relief in sight.

    After the project shipped, Phil and I sat down to dissect how it went. Here’s what the team actually built, in order:

    Rule 1 first, the most complicated and risky. Then Rule 2 and Rule 3. Then the workflow change to split the order list into “needs review” and “already approved.”

    This is bottom-up development. Build the parts, then assemble them. It’s logical. Developers think this way naturally. How can I build a system if I don’t have the parts?

    Phil and I, who worked together on the project, asked a different question. How could we have delivered value sooner?

    We came up with this approach:

    1. Split the order list into multiple views by status. Small work.
    2. Add the workflow hook, a no-op that sends every order to manual review, same as before. Nothing changes yet.
    3. Implement Rule 2. The simple one. 35% of orders now auto-approve.
    4. Implement Rule 3. Another 20%.
    5. Implement Rule 1. The hard one. The final 15%.

    Steps 1 and 2 would have taken about three days. Step 3, another two. Within five days, 35% of orders would have been automated.

    Five days to get 35% of sellers’ products into buyers’ hands without delay. Five days to lighten the load on customer support. Five days to give the order processing team some breathing room.

    Instead, they waited four weeks for our original approach to build all of it at once.

    The total effort is roughly the same either way. The difference is when value arrives.


    Image Upload: Ten Days of Silence vs. Two Days of Progress

    This example comes from a 3D space-planning application. Users designed and visualized physical spaces: floor layouts, furniture placement, signage, the works.

    One feature let users place custom images into their 3D scenes. Grabbing an image from the asset library was easy. Getting a new image into the library was not. The original workflow required uploading through a separate web app, processing it through another application to create a 3D asset, then reloading the entire scene. Fine for one or two images. Unworkable when a layout redesign involved hundreds of new assets each month.

    The team was asked to build a streamlined upload: trigger it from within the app, select an image, and have it appear in both the library and the scene immediately.

    They estimated 10 to 15 days. I asked when we could see parts of it working. The answer: in 10 to 15 days.

    Another all-or-nothing feature.

    I started asking questions. How are you approaching the work? What’s the architecture? What comes first? What comes second?

    The plan was for two developers to work “together”, with heavy air quotes. One would start at the database layer and build upward. The other would start at the UI and build downward. In about 7 to 8 days each, they’d meet in the middle and connect the pieces. That connection could take a day, or it could take a week.

    I pulled Brandon aside. We talked through an alternative approach using thin slices through all the layers.

    We found something we could demonstrate in about two days:

    1. Trigger the upload action from the UI.
    2. Hard-code a known image path from the user’s machine.
    3. Send the image to the server with no additional attributes.
    4. The server applies default processing, creates the 3D asset, and responds.
    5. On response, the app reloads the entire asset library, the same reload that happens at startup.

    Ugly? Yes. Hard-coded? Absolutely.

    But in two days, the entire pipeline was working end to end. Every slice after that replaced a hard-coded piece with a real one.


    Scene Loading: Three Months in the Dark

    Building a 3D application is like building any other software in some ways, and completely different in others. There’s a render loop that constantly redraws the scene. Separation of concerns and clean architecture still apply. But the visual nature of the work changes what “progress” looks like.

    When we rebuilt this application, one of the first features was scene loading. A space in 3D is made up of layers: the shell (walls, floor, ceiling), fixtures (counters, tables, built-ins), sections with detailed layouts, display areas, and signage.

    Loading and composing all of that took about three months to build.

    And when it was done, loading a large scene took several minutes, slower than the application it was replacing. The new system was worse.

    The team had worked incrementally, but their increments followed architectural layers. First, load all the data. Then convert it to domain models. Then download the 3D assets. Then render. Seeing anything on screen took over two months.

    Along the way, features were added to keep the user informed while they waited: gray-boxing, then color-boxing, then white-boxing. Scene loading was rewritten, not refactored, twice.

    After the project, I sat down with Marcus, the lead developer, to talk about what we learned and what we could have done differently. I had a hunch that “differently” might also mean “better.”

    A single thin slice could have been: get the data for the shell, convert it to the domain model, download the one asset, and render it on screen.

    Just the walls and floor and ceiling. Incomplete. Useless. Or is it?

    That slice touches every layer:

    • Data access
    • Domain model
    • 3D asset
    • Rendering

    Just enough of each layer for one thing. And once that one thing works, new possibilities open up.

    A feature called screenshot, which generates an image of the 3D scene, could have been developed independently once the shell was rendering. That work could have started weeks earlier.

    Performance would have been visible from slice one. Instead of building everything and then discovering it was slow, telemetry from the first slice would have shown where time was being spent. Was it data loading for fixtures? Asset loading for sections? We would have known early and adjusted early. We might have avoided a rewrite or two.

    Think about what performance means for a developer’s daily life. If loading a scene takes four minutes, and you restart the app every fifteen minutes to test your work, that’s two hours a day spent watching a loading screen. Two hours. Every day. For months.

    If performance had been addressed from the first slice, imagine that loading time was one minute instead of four. That’s ninety minutes back every day. Happier developers. Faster features. Less context switching.

    A better application for the end user.


    Store Locator: A Story Decomposed

    I was on a team building a retail e-commerce site. The product owner described a Store Locator feature:

    Users search by zip code or city and state. The five closest stores appear with address, phone number, and hours. A map shows the stores with zoom and pan. The regional manager’s name, phone, email, and photo are displayed. And if the user is logged in, pre-fill their address.

    That’s not one feature. That’s seven.

    My first instinct was to split it by layer: build the models and services in week one, then the UI in week two. This felt productive. Yet something felt off. I kept thinking.

    Will the models I build in week one survive contact with the UI? What do I tell my product owner when he asks for a demo? That I’m 40% done? What does 40% done look like? And if a teammate offered to help, can I hand off any work?

    The answers were “no” and “I don’t know.”

    Instead, I figured out how to slice it into thin features, each one end to end:

    1. Search by zip code. Display stores with address and hours.
    2. Add search by city and state.
    3. Add a static map to results.
    4. Add zoom, pan, and navigation to the map.
    5. Display the regional manager’s name, phone, and email.
    6. Display the regional manager’s photo.
    7. Pre-fill search when the user is logged in.

    After feature 1 shipped, I could have built features 2 through 7 in almost any order. Some could have been built in parallel. The product owner saw real progress after each one. At one point, he changed the order of the remaining work and dropped the idea of the regional manager’s photo. This was exactly the kind of feedback I wanted early, not late.

    Thin slices were lighter to carry. I could think about search without worrying about maps or managers. The mental stack stayed small. The wins came fast. The feedback was real.

    It’s not always easy to find the right slices. The key: what can you demonstrate to the user? If you can’t show it, it’s too thin. If it doesn’t go end to end through your system, it’s not a slice. It’s a layer.


    The Pattern

    Every one of these examples follows the same arc. My team built from the inside out, assembled the pieces at the end, and delivered value all at once, weeks or months after starting.

    Each alternative approach slices thin, delivers end to end from the first few days, and creates options that the original approach never had.

    The pattern is simple:

    1. Tell the story from the user’s perspective. What problem are you solving?
    2. For each part of the story, identify the simplest possible version.
    3. Map the parts to your software architecture.
    4. Implement a single thin strand through all the layers.
    5. Demonstrate your work. Ask for feedback. Adjust the plan.
    6. Implement the next strand.

    Three loops drive this forward:

    • A tight loop of developing and delivering a strand.
    • A medium loop of getting feedback and adjusting course.
    • An outer loop of deciding whether to keep going or stop.

    You don’t need to define “done” on day one. You set a direction. You implement the simplest version. You get feedback. Seeing the solution, you decide the next step. Seeing all the steps together, you decide whether to continue or stop.

    Think about a suspension bridge. The strength to support lanes of traffic over a mile of open water does not come from a single thick cable. It comes from many long, thin strands, all working together.

    Working in long, thin slices gives you the strength to keep your project above water.


    “But Wouldn’t It Be More Efficient To Just Build It All At Once?”

    I hear this one the most. And on the surface, it makes sense. If you already know what you’re building, why not just build it?

    Three reasons.

    First, you don’t know what you’re building. You think you do. But the moment users see working software, priorities shift. Features get reordered. Some get cut entirely.

    Every story in this article includes a moment where the team could have changed direction, if we had delivered something sooner. When you build it all at once, you’re betting that your understanding on day one is still correct on day twenty. It rarely is.

    Second, the “efficiency” of building everything at once is an illusion created by ignoring what happens to everyone else while you build.

    The order processing team worked overtime for three extra weeks. Developers stared at four-minute loading screens for months. Efficiency measured only in developer keystrokes misses the cost carried by everyone waiting for value that could have arrived sooner.

    Third, small batches surface bugs faster. When you deliver one slice and something breaks, you know exactly what changed. When you deliver four weeks of work and something breaks, debugging becomes archaeology.

    The DORA research is clear on this: teams that work in small batches have lower change failure rates and faster recovery times. The time you think you’re saving by batching gets eaten by the debugging you create.

    “I’ll Build The Full API While I’m Already Here”

    This is YAGNI dressed in work clothes. You Aren’t Gonna Need It.

    Building the full API feels efficient because you’re already in the code. You already have context. Why not build the other three endpoints while you’re at it?

    Because every endpoint you build before it’s needed is a bet. You’re betting that the shape of the API won’t change when real users arrive. You’re betting that the time spent building, testing, and maintaining those endpoints won’t be wasted. And you’re betting that nothing more valuable could have been built with that same time.

    Martin Fowler breaks the cost into three parts: the cost of building it, the cost of delaying other work, and the cost of carrying the extra complexity. All three work against you.

    Build the one endpoint the current slice requires. Make it clean. Make it tested. Ship it. When the next slice needs another endpoint, build that one. Your API will end up shaped by real demand instead of speculation. And every endpoint in it will be there because someone actually needed it.

    “It’s Useless If I Hardcode That Value”

    In the image upload example, we hard-coded a known file path. It felt wrong. It felt like a shortcut that wouldn’t count.

    It counted.

    That hard-coded slice proved the entire pipeline worked end to end in two days. Server processing, asset creation, library reload, all connected and running. Every slice after that replaced one hard-coded piece with a real one. The file picker replaced the hard-coded path. Attribute editing replaced the defaults. Each replacement was small, tested, and shippable.

    The hard-coded version isn’t the product. It’s the skeleton that proves the product can stand up. Once the skeleton is standing, you add muscle one layer at a time.

    Without that skeleton, you’re two developers building from opposite ends for eight days, hoping everything connects at the end. With the skeleton in place, you have a working system on day two and a clear list of what to improve next.

    That useless hard-coded slice is the most useful thing you can build. It eliminates integration risk on day one instead of deferring it.

    “Who Would Even Want Such A Small Slice?”

    Your product owner. Your teammates. Your users.

    Every one of your stakeholders benefits from working in small slices. You validate assumptions. You will accelerate learning. You will unblock other work. And you’ll deliver real business outcomes sooner.

    The Amazing Part

    It’s not in any single example. It’s in the pattern that every example reveals, especially when you sit down afterward and rethink how the work could have gone.

    The amazing part happens after the walking skeleton ships. It’s all the options that open up. It’s who benefits.

    That first thin slice, the tracer bullet, puts every layer of the architecture into place. Once it’s standing, the work changes.

    A product owner who saw zip code search working on day three could decide that the map wasn’t worth building at all, saving her team a week of work on something nobody needed.

    Developers who rendered the shell of a 3D scene in week two could have started building screenshot, or tackled performance, instead of waiting three months to see anything on screen. Ninety minutes a day back in their lives. Fewer rewrites. Better software.

    Brandon, who was about to spend eight days building from the database up, had a working pipeline in two. Every slice after that was a clear, small improvement instead of a leap of faith.

    And that order processing team. Five people doing manual reviews while the system that would replace their work sat unfinished for three extra weeks. They could have had relief on day five. The sellers who poured weeks of effort into their products could have had buyers receiving them instantly, not sitting in a queue.

    That gap still haunts me. Not the engineering. The engineering was fine.

    What haunts me is the people. The time they spent waiting for value that could have arrived sooner. That’s the lesson that stuck: the cost of building from the inside out isn’t measured in code. It’s measured in the days that real people spend waiting for something better.

    Slice thin. Ship early. Watch who benefits.

    Deliver daily. One thin slice at a time.

  • Composing a Cup of Coffee from Components

    Composing a Cup of Coffee from Components

    You can learn a lot about software design by thinking about your first drink of the day.

    Anyone heading in to work isn’t themselves without that first infusion of caffeine. Whether it’s at the drive-thru or the counter, you make your order, then grip, sip, and go.

    What does that have to do software design?

    Follow me down this line of questions, I will show you how composable design can improve your software.

    First, how do you use a cup of coffee? Typically, you grip the cup, then take a sip.

    Hand-drawn image of a cup labeled “Drink”.

    What if it’s a really hot cup of coffee? You’re server may give you a cup with a sleeve. And how do you take a drip of hot coffee? Grip, then sip.

    Hand-drawn image of a cup with a sleev labeled “HOT Drink”.

    What about when you’re on the move? In that case, your server can give you a cup with a lid. And how do you drink your coffee when you’re late and moving fast to the office? Grip, then sip.

    Hand-drawn image of a cup with a lid labeled “MOVING Drink”.

    What if I’m not drinking coffee? Juice, water, soft-drinks, the rules are still the same. Grip, then sip.

    So the rules around using a cup — for coffee, juice, or anything else you drink in the morning — involve two steps: grip and sip.

    In software terms, we would say that the interface for a drink has two methods: grip and sip.

    public interface Drink {
    public void grip();
    public void sip();
    }

    But I need to drink my half-caff, no-foam, one-pump, extra-hot machi-latte while I’m running late!

    Hand-drawn image of a cup with a sleeve and lid labeled “HOT MOVING Drink”.

    Grip, then sip.

    It doesn’t matter whether your language supports interfaces, protocols, or duck-types. What matters is that when someone asks for a drink, they expect to grip and sip.

    That’s easy enough for you. But what about your barista? How can they keep up with all of these different requests.

    How would that look in software?

    Well, a regular cup is simple enough. We could use some popular OO language to implement the coffee this way.

    public class Cup implements Drink {

    private String liquid;

    public Cup(String liquid) {
    System.out.println("Pouring your new " + liquid);
    this.liquid = liquid;
    }

    public void grip() {
    System.out.println("Gripping " + this.liquid);
    }

    public void sip() {
    System.out.println("Sipping " + this.liquid);
    }

    }

    You could buy a bunch of different cups: regular cups, lidded cups , sleeved cups, and sleeved-and-lidded cups. This solves the problem, but now you’ve got so many combinations to think about.

    The manufacturer has to decide if your sleeved, lidded cups is more similar to the sleeved cups, or to the lidded cups.

    public class Cup implements Drink {} // just like before

    public class HotCup extends Cup {

    public HotCup(String liquid) {
    super(liquid);
    }

    public void grip() {
    System.out.println("Protecting your hands.");
    super.grip();
    }
    }

    public class LiddedCup extends Cup {

    public LiddedCup(String liquid) {
    super(liquid);
    }

    public void sip() {
    System.out.println("Protecting your shirt.");
    super.sip();
    }
    }

    // TODO -- which way should it be?
    public class HotLiddedCup extends LiddedCup {}
    public class LiddedHotCup extends HotCup {}

    The barista also has to get it right the first time.

    public enum OrderType {
    HOT,
    FAST;
    }

    public Drink processOrder(String liquid, OrderType... types) {
    List<OrderType> ots = Arrays.asList(types);
    Drink d;
    if (ots.contains(OrderType.HOT) && ots.contains(OrderType.FAST)) {
    d = new HotLiddedCup(liquid);
    } else if (ots.contains(OrderType.HOT)) {
    d = new HotCup(liquid);
    } else if (ots.contains(OrderType.FAST)) {
    d = new LiddedCup(liquid);
    } else {
    d = new Cup(liquid);
    }
    return d;
    }

    If you change your mind, you have to go back to the counter and ask for a different type of cup. Are you sure you want to upset your barista that way? Besides, you’re running late.

    A Different Approach

    Luckily, the coffee store found a company that makes cups, sleeves and lids that all work together.

    Hand-drawn image of a cup, sleeve, and lid.

    The barista reads your mind, puts together the right parts, and hands you your drink. That always work well.

    Again, the manager comes to the rescue by putting out some extra lids and sleeves near the cream and sugar. So you’re set.

    This is the gist of composing your solution from small parts that work together.

    What could that look like in code?

    public class Cup implements Drink {} //same as before

    public class SleevedDrink implements Drink {
    private Drink drink;

    public SleevedDrink(Drink d) {
    this.drink = d;
    }

    public void grip() {
    System.out.println("Protecting your hands.");
    this.drink.grip();
    }

    public void sip() {
    this.drink.sip();
    }
    }

    public class LiddedDrink implements Drink {
    private Drink drink;

    public LiddedDrink(Drink d) {
    this.drink = d;
    }

    public void grip() {
    this.drink.grip();
    }

    public void sip() {
    System.out.println("Protecting your shirt.");
    this.drink.sip();
    }
    }

    // Making a drink becomes much simpler....
    public Drink processOrder(String liquid, OrderType... types) {
    List<OrderType> ots = Arrays.asList(types);
    Drink d = new Cup(liquid);
    if (ots.contains(OrderType.HOT)) {
    d = new SleevedDrink(d);
    }
    if (ots.contains(OrderType.FAST)) {
    d = new LiddedDrink(d);
    }
    return d;
    }

    What if I’m experience frost-bite, and even the simple hot coffee is too much? Composition has got you covered here, too. Add a second sleeve to your drink.

    Hand-drawn image of a cup with a lid and two sleeves labeled “EXTRA HOT MOVING Drink”.
    Drink hotLiddedDrink = b.processOrder("extra-hot coffee", OrderType.HOT, OrderType.FAST);
    c.enjoy(hotLiddedDrink);
    System.out.println("...and if it's still too hot...");
    hotLiddedDrink = new SleevedDrink(hotLiddedDrink);
    hotLiddedDrink.grip()
    hotLiddedDrink.sip();

    What do all of these lids and sleeves mean for my software design?

    First lets make sure we understand what we are comparing. The first design showed a hierarchy of many types of cups. The second design showed components that could be assembled into different types of cups.

    The design based on a hierarchy has some disadvantages:

    • its impossible to change your mind about the type of cup later.
    • the logic the barista followed in processOrder is more complex.
    • the logic for handling a hot drink is implemented in multiple places, both HotCup and HotLidded cup. Or was it LiddedHotCup?

    The design based on composition had several advantages:

    • The design is flexible. both the customer and the barista could build out the perfect drink.
    • The barista’s steps in processOrder were, therefore, much simpler.
    • You could even add two sleeves, which was not possible with the hierarchical design.
    • The manager could just count cups, rather than guessing which customers need which kind of customization.
    • The logic for sleeves is in one place, the SleevedDrink.

    Both designs solved the problem, providing protection for your hands and your shirt, while letting you grip and sip.

    This example is a metaphor, and somebody could say completely contrived. Yet it shows the trade-offs involved when you think about how to break up your code.

    There are trade-offs for sure, and you can tell which side I lean towards.

    Composable design makes your software simpler and more adaptable. Your code becomes simpler. You avoid duplication. Your software can adapt to situations you may not have imagined up front.

    Consider using a composable design, and see how simple and adaptable your software can be.

    You can find the simulation source code on GitHub.

  • How to Solve the Double Standard of Software Estimates

    The double standard exists. There is an antidote.

    Photo by Pixabay

    Recently, I had some repairs done to my car.

    “There’s a noise coming from the rear wheels. The faster I go, the higher frequency of the sound. I think it’s on the left side.”

    Ok, that sounds like a rotational noise. We can take a look — our diagnostic fee is $259. We will apply that to any repairs based on what we find. We will call you with what we find and confirm how to proceed.

    My family had some home remodeling done last year to update the roof and siding on our house.

    Here is our estimate for material and labor, based on what we can see from the outside. As we get into the work, we may find other work you need. We will call you each time with the details and let you know how much more it will be.

    In both cases, I was the stakeholder. The artisans were my engineers. Both experiences left me thinking about what I can learn from these disciplines to apply to software engineering.

    I would receive a call when they found something new. As a stakeholder, I would be informed of the details as they emerged. The artisans kept the time to surprise to a minimum.

    Each experience was matter-of-fact about the work. New tasks were identified, which needed to be completed and paid. I knew the original estimate of time and money. Yet, I still had to wait and pay for the extra result.

    The workers could not predict the new work from the outside. It wasn’t until taking things apart and digging into the details that they could identify all the work. Along the way, I would get frequent calls to update me on the current status.

    When new work did emerge, the artisans adjusted timelines. Working late was not an option for safety reasons. The workers treated weekends the same way. Working faster did not mean anything. Cutting scope meant accepting an unacceptable level of quality.

    My experience with stakeholders of software teams has been a complete contrast to what I saw with the trades:

    • immediate negotiations to bring the time and cost down
    • a strong desire to control everything upfront, before taking things apart
    • an emotional reaction when the team does notify stakeholders of any changes.

    Stakeholders can learn from their interactions with the trades. Apply that thinking to your Engineering teams. This results in trust, better relationships, more creativity and a high-quality product.

    Use Meaningful Words

    Engineers have to control the narrative when it comes to estimates. The first step involves actively setting expectations. Along with that, explaining the words you are using becomes crucial.

    deadline is a point in time that, if missed, will result in dire consequences.

    Deadlines are standard when there is an expensive next step. For example, newspapers (when they were printed) needed to be set and run on the presses. Likewise, physical items need to be manufactured after they are designed.

    A deadline without consequences is meaningless. Using artificial deadlines adds tension and erodes trust. Both the date and the consequences have to make sense.

    Deadlines do make sense when you need to coordinate with somebody else’s schedule.

    commitment is a promise that something will happen.

    Commitments can only come from those involved in doing the work. Commitments are binding. Commitments are obligations that you take on wholeheartedly.

    An estimate is an informed guess.

    Based on some prior experience, an estimate is a guess about how long a piece of work will take.

    When you want to get some work done on your house, you’ll get an estimate. The workers will tell you how much it will cost and how long the job will take. They come to this based on the size and shape of your roof and their experience working on similar roofs.

    schedule is a list of intended events that will happen.

    Estimates will contribute to a schedule. Other events outside of this work will also contribute to the plan. Plan is a synonym for schedule. A good plan assumes that you’ve listed out everything that will take up your time.

    Finally, a forecast is the rate of executing against an estimate. A forecast uses the trends from recent history to predict how things will go. A forecast is an informed estimate, backed by data about completed work.

    Given what I know now, this is my estimate. This is a guess. It’s not a forecast based on a trend, and it’s not a commitment or a promise that we will hit a certain date. As we learn more, I will adjust the estimate and keep you updated.

    The biggest confusion in software development happens when estimates turn into deadlines without everyone involved. Use the specific term to explain what you are talking about. Contrast that to that other terms that you are not using.

    Set and Manage Expectations

    Engineering teams can apply these critical lessons:

    • explain what
    • set the expectation that we will learn more after we get started
    • come to terms — explain the difference between an estimate, a forecast and a commitment
    • immediately share what changes along the way
    • hold yourself to safety and quality standards.

    Use analogies your Stakeholders understand.

    When you are talking to someone in Finance, or the CEO for that matter, compare software estimates to a financial forecast. Explain that, like the companies annual plan, an estimate cannot double as a prediction. As you encounter more information, you will update the plan and inform your stakeholders.

    When you are talking to some in Sales, compare it to the sales targets. These are goals, informed by the market, that will direct the behavior of the sales team. And the sales team will work as hard as they can to reach this goal. When it is set, however, a sales target does not represent the final sales number you will get at the end of the period.

    When you’re talking to Marketing or Operations, contrast the custom innovative work you are doing with the repetitive task-based work of the agencies that they work with.

    Cut through the double standard. Explain the terms you use, what each word means. Contrast your terms with what it does not mean. Use analogies to other departments, and to common trades, to drive your point home.

    Your actions are the antidote to the double standard.