The first time I - virtually - met Klaus was at C++ On Sea, I think in 2020. He held a workshop about modern software design which I managed to partially attend. He spoke in a slow and friendly manner which both helped participants to follow along and it also encouraged us to ask questions.
Then I saw some of his talks, one in live - again at a later C++ On Sea - and I always came away with the same feelings. Klaus is a very good teacher who doesn’t make you feel bad if you don’t know something, even if it’s a basic piece of knowledge.
Given all that, I was very happy to see his post some time ago saying that his first book was going to be published soon. Its title is C++ Software Design and now that I read it, I think it’s a great book.
It won’t teach you the implementation details of how to write modern C++ code, it has no such promise, but it does teach you how to design a modern C++ system. The book is structured into 10+1 chapters and in each chapter, you’ll find a couple of guidelines. The first few chapters are about design patterns in general: what is software design, what are abstractions and what’s the purpose of design patterns?
After having these things covered, a few design patterns are covered in detail. Not all of the Gang of Four Design Patterns are covered, but what is covered, are covered in such a depth that was not possible in the GoF book. But not only GoF patterns are covered in this book. After all, that’s an old book and while it’s still completely relevant, a lot of time passed, and there are other ones identified. In any case, this book focuses on C++ which has some other relevant modern patterns.
Each design pattern is explained first, the author shared what problems each solves and what’s the classical object-oriented implementation. But when we talk about object-oriented implementations, we often talk about inheritance, runtime polymorphism and the usage of reference/pointer semantics. In modern C++, we try to use value semantics whenever possible so that we can understand the flow of our program better, and can reason about it more easily. Often the performance is even better thanks to the removal of virtual dispatching. So the author examines each presented design pattern, and whether it’s possible to implement it in a modern, value-semantic way. If so, what advantages and disadvantages does it have compared to the classical implementation, when you should use one or the other?
The book starts with one of the more complex design patterns: the visitor. It’s the one that you should use to extend the operations on existing types. Besides the old implementation, we can also learn about
std::variant and how to use it with
std::visit. Before closing the chapter there is one guideline dedicated also to the acyclic visitor.
In the coming chapter, two design patterns are covered that are somewhat similar but they serve different purposes. The strategy pattern’s goal is to isolate how things are done, while the command’s intent is to isolate what things are done. They are both covered in detail, both classical inheritance-based approaches are presented just as modern value semantics-based solutions. In this chapter, in guideline 22, Klaus also explains why we should prefer value semantics over reference semantics.
In chapter 6, three design patterns are covered, one of the is a sort of curiosity, though it’s more and more widespread in modern C++. Besides the adapter and observer patterns, the CRTP is explained. Something I also wrote about some time ago. Probably it would have been worth mentioning how deducing this will change the suage of CRTP. Nevertheless, it’s very useful to read about how to use the static inheritance provided by the CRTP pattern in order to create compile-time mixin classes
Chapter 7 introduces the bridge, prototype and external polymorphism patterns. If you know the recent works of Klaus, at this point you can suspect even without looking at the table of contents where this all lead. I mean using the strategy pattern, emphasizing the importance of value semantics and then introducing the prototype and external polymorphism patterns all culminating towards the next chapter, which finally combines many of the presented techniques under the name of type erasure.
So chapter 8 is all about type erasure, which is implemented first as a combination of the strategy, the prototype and the external polymorphism design templates. If you’re looking for a deep introduction and you don’t have the book yet, I recommend this recording of the author’s talk at CppCon 2021. The analysis goes quite deep, it shows many alternatives that are in the standard library, or other design patterns to achieve similar results and it also details the performance issues and benefits you might run into. Speaking about the performance, the readers also learn about some possible performance optimizations of the type erasure design pattern, such as small buffer optimization or manual virtual dispatch. While I think that Klaus is a big fan of this design pattern, he didn’t forget to mention its costs and limits.
Before concluding the book, there are two more patterns explained, the decorator one and the singleton. What? The Singleton? - you might ask. Yes, and it’s worth noting that the author classified singleton not as a design pattern, but as an implementation pattern. Also, he focused on presenting how to design singletons for change and testability. As such, singletons can be useful. I almost wrote useful abstractions, but as Klaus explained, a singleton is not an abstraction and as soon we recognize that and we handle it simply as an implementation pattern, we’ll have fewer bad feelings about this pattern.
C++ Software Design by Klaus Iglberger is a great book that, in my opinion, every non-beginner C++ developer should read. My personal opinion is the chapters coming after the one on type erasure do not perfectly fit into the chain of thoughts, the story he wants to tell, but as he shares essential knowledge there too, I couldn’t say those should be skipped. I’m glad I learned more about those. And I encourage you to do the same and learn deeper about these design patterns and probably it would be a good exercise to think about more patterns and try to implement them in a modern way just as an exercise inspired by this book. A highly recommended read, I hope not the last one by Klaus!