This week’s post is a bit late because we’ve just come off the “May 24” weekend in Canada and I was working on some house projects that took a little longer than I hoped. These projects were not at all technical - mostly yard work and fence repair, but as I was planning it out and executing it, I realized I was planning it just like I plan projects at work.
Software and other IT engineering stuff are usually built using the Software Development Life Cycle (SDLC). The SLDC instructs developers and managers to follow a process in order to create good software. They analyze the requirements, design something to meet them, deploy it, and then look after it for the rest of its life. If the product needs to be modified at some point in its maintenance cycle, then the process starts all over again with analysis.
By Dzonatas - Own work, CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=4376189
The broad strokes have not changed and likely never will. It’s rather impossible to design something before knowing what its intended purpose is, and you can’t deploy something that has not been designed. Modern software development still follows these broad strokes, but in a much more flexible and granular way.
The original implementations of the SDLC were successful enough, but have changed drastically in recent years; mostly to address a lack of flexibility in earlier iterations. These days we know that any single vision of a product is not going to survive the development process. We know that we’re going to start out building X but wind up building Z by the time the product is ready for the market. The monolithic SDLC doesn’t support this reality very well because it doesn’t have a cycle built into it for modifications prior to deployment (called implementation in the diagram above).
The development industry is filled with stories of spectacular budget or schedule overruns due primarily to this one problem. In mid-stream, a stakeholder will decide that a few features should be added to the project. Because there is no codified way to analyze and design ad-hoc modifications, they usually end up being discarded or bolted onto the project in an inelegant way, typically breaking other parts of the initially well-designed system.
It is the SDLC that we can largely credit with giving us the concept of software “versions”. When a modification comes up, because the monolithic SDLC isn’t great at handling that, it gets marked for “the next version” and forgotten about. Perhaps that next version is years away, or perhaps it never gets released at all. In either case, we needed a better way to incorporate modifications to a product.
These days, most software is developed using an ongoing iteration of the SDLC process which is collectively and generically referred to as “agile technologies”. There are a number of development variations that fall under the agile umbrella. There’s no right way to be agile, although certainly some best practices have been ironed out. In general, agile teams work in a much less formal environment than is proscribed by the SDLC. While all of the steps still occur (analysis, design, etc.) they are done in much smaller iterations, much quicker, and therefore are much more robust to change. New features and previously unknown modifications can be worked into the application much earlier than “next version” and it can be done properly so the product doesn’t have rough edges.
Build smaller, working things
Using agile methods, smaller and less functional versions of the application can be released and built upon. With the initial SDLC, the product doesn’t leave the bullpen until it is a fully complete product that meets all the requirements laid out way back in step one weeks, sometimes months, before.
If software were a car, we’d say that the first thing to be delivered is a fully functional car. That’s great because we set out to build a car and now people can buy it and go grocery shopping and drive to work. What's not great is that those people had no way at all to go shopping or commute while waiting for this car. And, now that they have a car for the first time, they’re asking for all sorts of stuff that was never part of the design.
In agile, we eventually deliver a car, but we also deliver usable bits of the project as we go along. For example, if this car was developed using agile methodologies then we’d deliver a skateboard in the first week. Then a scooter a few weeks later. We’d deliver a bicycle, then a motorcycle and finally, a car. It still takes a long time to get a car, but in the meantime, people can still get to work on the skateboard or scooter. You can’t go grocery shopping yet, but you can do some of the things you need a car for.
Another advantage of continuous development is that it is much easier to incorporate modifications. This is partially because there are multiple and ongoing ‘analysis/design’ phases to accommodate requests for features, but the big win comes from getting the product in front of the end-users quickly. Perhaps the original design did not call for any mirrors on the car but users really want mirrors. Because that was not picked up in the analysis stage, the first time developers are hearing about mirrors is after the launch of Car 1.0 with much fanfare and press. Mirrors will have to wait until version 2.0.
But, consider when the need for mirrors would be discovered using agile. Perhaps the skateboard riders would not come back with an idea for mirrors, but probably by the time users are riding the scooter in traffic they’d start clamoring for mirrors. The agile team can take this feedback, run through the analysis/design phase, and possibly get mirrors on the next step, the motorcycle. By the time the car comes out, we’ve had mirrors for a long time. This well-known image from Henrik Kniberg illustrates the difference between the two methodologies well.
Agile utilizes the concept of continuous delivery of a “Minimum Viable Project (MPV)” instead of focussing on the car. From Kinberg’s post:
Here we take a very different approach. We start with the same context – the customer ordered a car. But this time we don’t just build a car. Instead we focus on the underlying need the customer wants fulfilled. Turns out that his underlying need is “I need to get from A to B faster”, and Car is just one possible solution to that. Remember, car is just a metaphor, think any kind of customized product development situation.
So the team delivers the smallest thing they can think of that will get the customer testing things and giving us feedback. Some might call it an MVP (Minimum Viable Product)…
Notice the subtlety in the image. The end product, the car, looks different. If you read Kniberg’s blog post you will find out that is because, during the bicycle phase, one of the pieces of feedback the users gave was that they like the wind on their faces. So, while the lack of a removable roof may not have been a deal-breaker for the initial model of car, the engineers were able to make a better car because of that early feedback.
Don’t draw the f*ing owl
There’s another saying that I really like and it can be applied to poor software development. I am not saying that any particular development methodology is inherently bad, but there are certainly a lot of examples of software development gone wrong. The main area where software falls down is in the requirements and design phases. If those phrases are not done properly, then there’s a lot of confusion between step one and the finished product. When a roadmap is unclear like that, you’re “drawing the owl.”
To be more clear, the phrase is usually “draw the f*ing owl” because it’s never used in a good way. It’s kind of like the phrase “dumpster fire”. Nobody has ever been happy with a dumpster fire.
The phrase refers to a (hopefully) hypothetical situation where you’re being taught how to draw an owl. But with a ton of missing information, yet you’re still expected to draw the owl. There’s a lot of variations on it, but this is my favorite.
Easy, right? Just lay down some framework code and then just shut up and figure out how to draw the rest of the owl.
Using this method, we won’t find out that we have no clue how to draw an owl until our customer is expecting delivery of the owl drawing. Using a more agile development methodology, we’d find out as soon as we tried to stick the ears on the circles that we are lacking expertise in owl drawing. We could then readjust our course to either revisit the design to see if we really need an owl at all or hire a primo owl drawer to help us out.
What does this have to do with fences?
Maybe not a lot. But all multi-step complex tasks can benefit from simplicity. And a very reliable way to create simplicity is to be agile and develop small bits of deliverable functionality at each step.
Removing the old fence is a good start. It’s a single step with an identifiable and usable delivery: cleared land for the new fence.
Hammering in some small 2x2 stakes along a plumb line is a good second step. It shows us that the new fenceline will be straight, and it also tells us things about the new fence, such as how many fence posts we’ll need, and how high they need to be to accommodate the slope of the ground.
Digging the holes and putting in the fence posts gets us to the point where we can confirm what we learned in step 2. We can also string a rope between the fence posts now to give us a partial fence. We have our bicycle.
Putting the cross beams and fence boards up is a major delivery because we have a working fence. There’s no gate yet, but we have most of what we need, we have our motorcycle.
Finally, the gate seals the deal and the fence is complete. Voila - the car.
While not every step in fence building has a “skateboard” deliverable attached to it, it provides ample opportunities to review frequently and adjust for the next steps if needed. At the end of each step, I learned something - I have too many fence boards and not the right type of hinges are examples of two things I learned during some of these phases. But I learned them early so by the time I needed the correct hinges, I had them so the gate went on flawlessly on time and on budget.