Change is the universal constant. Nothing can escape change.
And yet, most projects we have worked on seem to ignore this reality and act if major changes will never happen to us.
…all the things you see around you change immediately and will no longer be; and constantly bear in mind how many of these changes you have already witnessed.
– Marcus Aurelius, Meditations
Perhaps this is due to the increasing pressure on software teams to deliver at a faster and faster pace. Surely you’re familiar with this pressure: you need to get this software working now, in order to meet a critical deadline to get funding, ship a feature required by a Very Important Person, or make an arbitrary launch date. You don’t have the time to slow down and “do things the right way”. Management doesn’t care about any of that. Sure, go back and fix it later, but take whatever shortcuts necessary to get it done now.
But it turns out that there’s never a good time to go back and clean up the system. One “quick hack” after another piles up. Eventually, even management notices that every new feature takes longer and longer to develop. You suddenly realize you’re working in a house of cards, where even the simplest changes seem to touch multiple parts of the system and run the risk of introducing new bugs. Then the Big Change comes knocking on your door, and you’re forced to redesign a significant part of your system as a result, stalling new feature work and causing customers to wonder why they haven’t heard from you.
What’s happened here?
In an effort to move quickly, your team neglected to make the necessary investments to support change. Your software aged with each new change. You sowed the seeds of your own defeat and gave your competition the advantage. And unless you can resolve this problem, there will only be one outcome: your system, and possibly your team, will fail and disappear from the landscape. Of course, it might already be too late.
If you are clear- and far-thinking enough, you will understand that the future is uncertain, and that you must be open to adaptation. Only having a clear objective and a far-reaching plan allows you that freedom.
– Robert Greene, The 48 Laws of Power
Designing Embedded Software for Change
Maybe you think this is an overly dramatic scenario, especially in the age of “Agile” software development. But this same story has played out in most projects we have worked on, and over the years hundreds of software developers from around the world have written to us and shared similar stories.
We got tired of the last minute fire drills, the continual redesigns, the constant tension between “we need to take the time to fix this” and “I don’t care how bad it is right now, we need to make this work as fast as possible”. We wanted to know what it would take to design our embedded systems in such a way that we can easily respond to changes, regardless of whether the changes were:
- Changes in requirements or user needs/goals
- Changes caused by environmental shifts (switching dependencies, using different components)
- Changes needed to maintain the long-term health and viability of the software
We spent years studying the software literature, especially the works of David Parnas, who was interested in designing software (especially embedded software!) to support change as far back as the 1970s. We learned about software architecture and system design, areas where people are already thinking about change. We analyzed the software projects we worked on to identify factors that made change easier or harder. We found high-quality model software from around the web, identifying positive factors that we wanted to incorporate into our own work. We set up an internal “development laboratory” to experiment with changeability strategies in software. We worked with clients to test out these techniques, both implicitly and explicitly.
All systems change during their life cycles. This must be borne in mind when developing systems expected to last longer than the first version.
– Ivar Jacobson
This course is the result of our years of effort. We have collected and condensed the most helpful learnings here, for you. We have identified software worth studying and using as a model for your own development projects. We have even found these ideas so helpful that we applied them to the design of this course, making it easier to change, refactor, and reorder the content as we continue to experiment and evolve our understanding.
It’s time to step out of the embedded software dark ages and enable true agility.
What to Expect
David Parnas describes “Design for Change” as Design for Success. We certainly agree with Dr. Parnas on this, but we propose another alternative description: Design for Sanity. Given the increasing pressure on software teams and the tendency to overwork, sanity is an important goal. Being able to more easily change our software and adapt to changing requirements means few fire drills, lost weekends, and late nights. We can more easily maintain and expand our software. We can focus on delighting our customers.
Of course, this is easier said than done. To help you achieve this outcome, we have designed the course around the following principles:
- You work on a team, and you may also need “buy in” from your manager to use a new approach. To help you make your case, we provide a compelling narrative you can share for why the status quo of embedded software development is harmful to the business.
- We structure the course around a core set of principles that underlie Design for Change: information hiding, separation of concerns, loose coupling, and the open-closed principle. We continually reiterate these principles throughout the course, building a layered understanding of the concepts and how they apply to embedded software.
- The goal of each lesson is to improve your understanding or to provide you with a skill that can be applied to your work. Some complex topics have been condensed to only a summary. Whenever we feel we have significantly condensed the material and cut out useful nuance, we provide options for those who want to (or need to) dive deeper. One such example in this course is the discussion of Abstract Interfaces, which can be explored further in a dedicated course by those who are interested.
- So many software examples are trivial, regardless of whether they are found in articles, books, or courses. We repeatedly found ourselves thinking: “Great, this is a neat idea, but I don’t get how I can take this simple example and use it on my sprawling, complex software project.” To avoid that problem, we provide you with analyses of real-world software projects that model Design for Change principles.
- Many of these techniques and principles are more easily to new software projects. However, most of you will be working with an existing code base and will not have the benefit of starting from scratch. We include demonstrations that show how the same techniques can be applied to existing software.
Time Commitment
Using an average reading speed of 250 wpm, we estimate that the course will require:
- Core Reading: 5 hours
- Optional Reading: 2 hours
Support
We’re here to help you if you get stuck! Our course is designed to be as comprehensive as possible, but also challenging. You can always ask questions or get help in the Course Support section of the forum, through private messages in the course interface, and also through private messages in the forum.
