I can’t begin to describe how excited I am to announce the release of my first book!
Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software, published by Pragmatic Bookshelf, is based on my decades’ worth of hands-on experience as a software developer, consultant, and educator. I have seen all nine practices described in the book work, and work for some of the biggest players in the software industry.
Here’s an inside look at some of what you’ll find in Beyond Legacy Code, starting with why we need “practices” in the first place:
Building software is complex—perhaps the most complex activity that humans can engage in. Writing software is a discipline that requires a range of skills and practices to accomplish successfully.
It’s easy to get it wrong because the virtual world is so different from the physical world. In the physical world, we can easily understand what it takes to build something, but in the virtual world this can be much more difficult to see and understand. The software development profession is just starting to figure things out, much like where the medical profession was a few hundred years ago.
It was less than two hundred years ago that the medical community laughed at Ignaz Semmelweis for proposing that microscopic creatures could cause disease. How could something as trivial as washing your hands before surgery make the difference between life and death to your patient?
The medical community held this view in part because germ theory did not exist yet and partly because they were at that time actively trying to dispel the myth that invisible spirits caused disease (often truth and myth share a lot in common). Therefore, the practice of washing your hands before performing surgery wasn’t considered essential.
Battlefield surgeons in the Civil War knew about germ theory, but they argued they had no time to sterilize their instruments. If a soldier needed an amputation they didn’t have time to wash the saw. But when the medical community looked at the success rates of battlefield surgery they discovered that in many cases more men died of infection and disease in the Civil War than died on the battlefield, so medicine had to rethink its position.
When we understand germ theory, we understand why we have to wash all the instruments. This is the difference between following a practice (the act of sterilizing a specific instrument) and following a principle (the reason for sterilizing all instruments).
And the thing about the following software development practices, just like sterilization, is that we have to get it all right for any of it to work. If we happen to miss one of those things… one germ can kill your patient, and one bug can kill your application. And in this we require discipline.
I don’t believe there is one right way to develop software just as there’s no one right way to heal a patient, create art, or build a bridge. I don’t believe in the “one true way” of anything, but especially not for programming.
Still, having worked with thousands of developers, I’ve seen firsthand how we constantly reinvent the wheel. Software development has attracted a range of people from all backgrounds, and that has brought many fresh perspectives to creating software. At the same time, the huge diversity among developers can be a real problem. Enterprise software development involves enormous attention to detail and a lot of coordination among those involved. We must have some shared understanding, a common set of practices, along with a shared vocabulary. We must arrive at a common set of goals and be clear that we value quality and maintainability.
Some developers are more effective than others, and I’ve spent most of my life trying to discover what makes these extraordinary developers so good. If we understand what they understand, learn some principles and practices, then we can achieve similar extraordinary results.
But where to begin?
Software design is a deep and complex subject and to do it justice requires a great deal of background theory that would need several books to explain. Furthermore, some key concepts are not yet well understood among all developers and many of us are still struggling to understand the context for software development.
In many ways, legacy code has come about because we’ve carried the notion that the quality of our code doesn’t matter—all that matters is that software does what it’s supposed to do.
But this is a false notion. If software is to be used it will need to be changed, so it must be written to be changeable. This is not how most software has been written. Most code is intertwined with itself so it’s not independently deployable or extendable, and that makes it expensive to maintain. It works for the purpose it was intended for, but because of the way it was written it’s hard to change, so people hack away at it, making it even harder and more costly to work with in the future.
We want to drop the cost of ownership of software. According to Barry Boehm of the University of Southern California, it often costs 100 times more to find and fix a bug after delivery than it would cost during requirements and design. We have to find ways to drop the cost of supportability by making code easier to work with. If we want to drop the cost of ownership for software, then we must pay attention to how we build it.
Want more? Download the full excerpt here.
In the first of the nine practices we look at some of the problems facing far too many software development teams as they struggle just to get started:
Up to 50% of development time in a traditional software project is taken up by gathering requirements. It’s a losing battle from the start. When teams are focused on gathering requirements, they’re taking their least seasoned people—business analysts who don’t have a technical orientation in terms of coding—and sending them in to talk to customers. Invariably they end up parroting what the customer says.
We all have a tendency to tell people what we think they want to hear, and some customer-facing professionals still fall into this trap. It’s uncomfortable to try to find a way to tell your customer, “No, you don’t want that, you want this,” or “Let’s not worry about how it works and instead trust our developers to get us there.”
It’s easier to list the features requested by the customer and tell them exactly what we think they want to hear: “Got it. We can do that.” But can we?
More importantly, should we?
It’s natural in spoken language to talk in terms of implementation. That’s how people tend to speak, and it’s hard to identify when we’re doing that. I go from my specific understanding to a generalization. You hear that generalization and go back to your specific understanding. And in the end we have two different experiential understandings of what we think is common ground, but they’re probably completely different.
Requirements have no form of validation and that’s translated from the customer telling the analyst, the analyst writing it down, the developer reading it and translating it into code… It’s the telephone game. There are all these different ways of reinterpreting stuff so when you finally give the released version to the customer they’re apt to say, “That’s not what I said. That’s not what I wanted.”
Want more? Download the full excerpt here.
And the last of the nine practices addresses the legacy code crisis head on with advice for working with legacy code, but most of all, how and why the practice of refactoring code before it’s released can stop legacy code from propagating in the first place:
Refactoring is restructuring or repackaging the internal structure of code without changing its external behavior.
Imagine you’re where I was a few years ago, saying to your manager that you want the whole team to spend two weeks, a full iteration, refactoring code. My manager said to me, “Good. What new features are you going to give me?”
And I had to say, “Wait a minute. I’m talking about refactoring. Refactoring is changing the internal structure but not changing the behavior. I’m giving you no new features.”
He looked at me and asked, “Why do you want to do this?”
What should I say?
Software developers are faced with this situation too often. Sometimes we don’t quite know what to say, because we don’t speak management’s language. We speak developers’ language.
I shouldn’t tell my manager I want to refactor code because it’s cool, because it feels good, because I want to learn Clojure or some other piece of technology… Those are all unacceptable answers to management. I have to specify the reasons for refactoring in a way that makes sense to the business—and it does.
Developers know this, but need to use the right vocabulary to express it—the vocabulary of business, which comes down to value and risk.
How can we create more value while at the same time reduce risk?
Software by its very nature is high risk and likely to change. Refactoring drops the cost of four things:
Clearly, you want to refactor code when you need to work with it some more to add features or fix bugs—and it makes sense in that case. If you never need to touch code again, maybe you don’t need to refactor.
Refactoring can be a very good way to learn a new system. Embed learning into code by wrapping or renaming a method that isn’t intention revealing with a more intention-revealing name. You can call out missing entities when you refactor and basically atone for any poor code written in the past.
We all want to see progress and meet deadlines, and as a result we sometimes make compromises. Refactoring code cleans up some of the mess we may have made in an effort to get something out the door.
Want more? Download the full excerpt here.
Come back for new posts every week, where I’ll be backing up some of the assertions made in Beyond Legacy Code: Nine Practices to Extend the Life (and Value) of Your Software with additional information, tips, and strategies to help us all come together and once and for all move Beyond Legacy Code.
—David Scott Bernstein
Previous Post: « Seven Strategies for Continuous Delivery
Next Post: Playing All or Nothing »