A phrase that often repeats in my mind is Charlie Munger’s “take a simple idea and take it seriously.” Good ideas can be found in abundance. There are thousands of viable ways to improve your life and your work. What’s in short supply is application. We don’t take the ideas we come across seriously enough. We don’t apply them to the degree that would be beneficial.
While reviewing the Designing Embedded Software for Change course, I realized I had done (as best as I could) what Munger suggested – I took the principles that are central to the course – separation of concerns, information hiding, loose coupling, and the open-closed principle – and applied them to the overall course design.
We designed our early courses in a linear fashion. We presented information in a specific order, and we expected you would work through the course, lesson-by-lesson, from start to finish. Examples of this style Introduction to Build Systems using Make and Creating a Cross-Platform Build System for Embedded Projects with CMake.
Designing Embedded Software for Change is not written this way. The application of the core design principles resulted in the course being split into atomic concepts, each with a single purpose or idea. Practically speaking, we have tried to reduce duplication within the course material by giving each distinct idea or theme a dedicated lesson. We think of each concept as having an abstract interface composed of the link to the page along with the title or a summary. When referring to these concepts in other lessons, we present the interface, but we do not expand upon it more than is necessary.
There are, of course, pedagogical tradeoffs made here. Sometimes we intentionally repeat a point in multiple places. Sometimes we group related concepts into a single page to balance the number of lessons and the average lesson length.
Lack of separation of concerns and loose coupling has been a major problem with maintaining and expanding our previous courses. Like in tightly coupled software, making an update to a small course detail often required changes in multiple lessons. Inserting a new idea into the course flow often involved major surgery, such as splitting lessons apart and reorganizing the lesson order. Often, like in tightly coupled software, a change in one lesson would introduce an error or inconsistency in another lesson that was not noticed during the update – resulting in a “bug” that the next student would encounter.
By dividing lessons into distinct concepts (with a single responsibility!), hiding the actual “implementation” within the lesson concepts, and keeping lessons loosely coupled through linking (rather than a dependent order), we can make changes while minimizing the impact on other lessons. This approach has proven its value even before the initial course release. We have moved around entire modules, reordered lessons, inserted lessons, and removed lessons without drama.
Another major change is in the “types” of lessons present in this course. Our previous courses essentially have three types of lessons: pedagogical (focused on specific topics), exercise prompt, and exercise solution. Given this course’s focus on separation of concerns, we developed a refined lesson model based on the lesson’s purpose:
- Explorations of why we think these ideas are important (which do double duty in providing arguments that can help you get buy in from your team)
- Theoretical discussions of design principles
- Strategies that you can adopt to focus your goals on designing for change
- Tactics that apply at the implementation level
- Demonstrations of applying the techniques in the course
- Model Software Analyses, which looks at how a real world software project uses design for change techniques
We grouped each of these content types into distinct course modules. The lessons are highly interlinked across these module boundaries – for example, tactics lessons are mapped onto the strategies and principles they support, related tactics, demonstrations that show how the tactic is applied, and model software that uses the tactic.
The same principles also helped us focus on design for change within the course lessons. Some concepts are much too complex to fully cover within a single course lesson. Given that, we set the responsibility of the lessons as the application of this idea to design for change. This narrowed the focus on the lessons on what we considered most essential to the design focus at hand. But that means some stuff has to be left out. Our solution was to create a related page in the Field Atlas or Glossary that had the responsibility of summarizing the general topic and providing useful references. We can the link to these from within the course, providing easy access to supplemental information. Being separated, too, allows us to evolve the lessons and resources independently of one another.
One unplanned outcome of these simple design decisions is that there are multiple ways to proceed through the course. Designing Embedded Software for Change is not like a traditional technical book (or our earlier courses) that you read from start to finish, or like . Instead, it is a comprehensive exploration of a set of ideas that apply to software development. We present the material in an order that makes the most sense to us from a “linear” perspective, but the presented order is only one way to proceed. The interlinked nature of the material means that you can forge your own path. If a lesson has any conceptual dependencies there will be links that you can follow. Certainly, you can read through the material in a straight shot. You could also pick at random, based on what is currently interesting to you. You can work backwards, starting from a tactics lesson or a demonstration, using the links to address any gaps in your knowledge. You could read one lesson per week for continuing education on general software design principles and decoupling techniques. All of these approaches to the course will work, as long as you’re willing to click links to concepts that are not familiar to you.
David Parnas describes “Design for Change” alternatively as Design for Success. We suggest in the course that it can also be described as Design for Sanity. After all, the goal is to more easily change your software and adapt to changing requirements, leading to fewer fire drills, lost weekends, and late nights. It turns out the same holds true for course design and maintenance as well.
Now I have a new question to ponder: what else can I apply these simple, powerful ideas to?
Designing Embedded Software for Change
Are you tired of every hardware or requirements change turning into a large rewrite? Our course teaches you how to design your software to support change. This course explores design principles, strategies, design patterns, and real-world software projects that use the techniques.
