Blog Archive for / reviews /
Review of Embracing Modern C++ Safely by John Lakos, Vittorio Romeo, Rostislav Khlebnikov and Alisdair Meredith
Wednesday, 01 March 2023
Verdict: Conditionally Recommended (3/5)
This is a huge book, over 1300 pages, and contains a wealth of information about all the language (not library) facilities added in C++11 and C++14. It has one "section" per language feature, and the sections are largely independent of each other, so they can be read in almost any order, and used as a reference. This is mostly a useful structuring, except for the few cases where there are closely related changes in both C++11 and C++14, and these are split into separate sections, that aren't even necessarily consecutive. Though there are already extensive cross-references between the chapters, the book would benefit from more cross references in such cases.
The word "section" is quoted above because they are what might be called "chapters" in other books. As it stands, the book has 4 "chapters", with "chapter 0" being the introduction, and the remaining 3 being what might be called "parts" in other books, and covering "Safe Features", "Conditionally Safe Features" and "Unsafe Features" respectively.
This use of the term "safe" is my biggest gripe with this book; much like a book on chainsaws might be titled "how to use chainsaws safely", the title makes the book seem as if it is going to be a tutorial on how to use modern C++ features without cutting your leg off. However, that is NOT the way that the authors use the word. They are using it with regard to "business risk" of adopting a specific language feature into a codebase that is mostly C++03 without providing explicit training to all the developers. Consequently the list of "safe features" is relatively small, and most features end up in the "conditionally safe" chapter, meaning that developers might need some training to use those features, rather than them being clear to developers only experienced with C++03. The authors explicitly call out that this "safety" axis is the one area where they intentionally deviate from their "Facts, Not Opinions" intent, and is the worst aspect of the book. As a general rule, developers should not be using language constructs they don't understand, so if a company wants to upgade to C++11/C++14 from C++03 then that company should provide appropriate training.
Consequently, I recommend that readers disregard the author's "safety" classification of the language features, and instead read the "Use Cases", "Potential Pitfalls" and "Annoyances" sections for each language feature and make up their own mind. It is particularly frustrating, since features that by and large make code clearer and less error-prone (such as lambdas, enum classes and range-for) end up being marked "conditionally safe" because they require training.
In the section on "Generalized PODs", the book covers what it means for objects to be "trivial", and be "trivially destructible", which are language constructs with specific meanings and consequences. They then go on to define their own term "notionally trivially destructible" to mean "those objects where the destructor has no code that affects program logic" (e.g. a destructor that only logs), and thus is safe to omit if you are directly controlling object lifetime (which should be a rare scenario anyway). This is not a language construct, and has no meaning to the compiler, but the similarity to the standard terms is too close and could easily lead to confusion. The inclusion of this in the book actually has the potential to decrease safety of a codebase, by encouraging developers to do things that might accidentally introduce undefined behaviour.
This book only covers the language features, not the library
features. Since a big part of the improvements from using C++11 and
C++14 comes from using the new library features (
std::auto_ptr, for example), this is a real let down, but given that
the book is already over 1300 pages, I can see why the authors decided
to leave it for another time.
Finally, this is a large, heavy book which makes it uncomfortable to hold it for any length of time, leading to contorted positions when reading. It is also a paper back book with very thin paper, so you can see print on the reverse side of the paper showing through, and a pale-grey font for comments in the example listings which is almost unreadable in many lighting conditions. This is particularly problematic, since many of the information in the examples comes from the descriptions of what each line means in the comment on that line. The e-book editions might thus be an improvement, though I haven't checked myself.
These gripes aside, there is a lot of useful information in this book. Each section covers a single language feature, how it differs from closely-related features in C++03, the precise details of syntax and use, intended use cases and potential pitfalls. If you want to know "how does this language feature work and what might go wrong", then reading the relevant section will give you a really useful set of information. You might still want to get training for the more complex features, but the sections actually contain enough information to get started, with copious examples.
In conclusion: this book is conditionally recommended. There is plenty of useful information there, but the presentation (both physically, and organizationally) is problematic.
Buy this book
Tuesday, 15 July 2008
A couple of weeks ago, one of the products I maintain for a client needed a new installer. This application is the server part of a client-server suite, and runs as a Service on Microsoft Windows. The old installer was built using the simple installer-builder that is part of Microsoft Visual Studio, and could not easily be extended to handle the desired functionality. Enter the WiX toolset.
As its name suggests, the Windows Installer XML Toolset is a set of tools for building Windows Installer (MSI) packages, using XML to describe the installer. At first glance, this doesn't look much easier than populating the MSI tables directly using Microsoft's Orca tool, but it's actually really straightforward, especially with the help of the WiX tutorial.
It's all about the <XML>
The perceived complexity comes from several factors. First up,
every individual file, directory and registry entry that is to be
installed must be specified as a
given a GUID which can be used to uniquely identify that item. The
details of what to install where, combined with the inherent verbosity
of XML makes the installer build file quite large. Thankfully, being
XML, whitespace such as indenting and blank lines can be used to
separate things into logical groups, and XML comments can be used if
necessary. The installer GUI is also built using XML, which can make
things very complicated. Thankfully WiX comes with a set of
pre-designed GUIs which can be referenced from your installer build
file — you can even provide your own images in order to brand
the installer with your company logo, for example.
Once you've got over the initial shock of the XML syntax, the
toolkit is actually really easy to use. The file and directory
structure to be used by the installed application is described using
nested XML elements to mimic the directory structure, with special
predefined directory identifiers for things like the Windows
directory, the Program Files directory or the user's My Documents
folder. You can also use nested
<Feature> tags to
create a tree of features which the user can choose to install (or
not) if they opt for a custom install. Each "feature" is a group of
one or more components which are identified with nested tags in the
What if you're not just installing a simple desktop application?
Windows Installer provides support for custom actions which can be run
as part of the installation, and WiX allows you to specify
these. The old installer for the server application used custom
actions to install the service, but these weren't actually necessary
— the Windows Installer can automatically configure services, it
was just that the Visual Studio Installer builder didn't support
that. With WiX it's just a matter of adding a
<ServiceInstall> tag to one of your components.
The custom actions we did require were easy to add with the
<CustomAction> tags — you can write custom
actions as DLLs or EXEs, or even as simple VBScript included directly
in the installer build file. These can then be added to the
<InstallExecuteSequence> at the appropriate point,
taking care to specify the right conditions (such as whether to run on
install or uninstall, and whether or not to run depending on which
features are being installed).
The WiX toolset is very powerful, and gives you full control over everything the Windows Installer can do. Though the XML syntax is a little cumbersome, it is actually quite simple to use. Once you get used to the syntax, it is easy to see what the installer is doing, and what you need to do to get the desired effect. Though designing installer GUIs is quite hard, the supplied options will be sufficient in many cases and it is easy to customize them to your needs.
It's a free tool, so you can't beat it on price, and the tutorial really reduces the learning curve. Next time you need to build an installer, I recommend you give WiX a try.
Tuesday, 27 May 2008
My wife picked up this book last week, and it's an absolutely fabulous book. It's a jolly, nostalgic trip down memory lane for those of us (like myself and my wife) who grew up with the first batch of home computers in the 1980s. If you can look back fondly on the touch sssssssssseeeeeeenstiiive keyboard of the ZX81, the nine (count them!) colours of the Dragon-32, the 64K (wow!) and hardware sprites of the Commodore 64, and the delights of games like Manic Miner, Frogger and Hungry Horace, then this book is for you.
This book covers more than just the games, though: there are
sections on the home computers themselves, the social environment
surrounding home computer usage, and the various paraphernalia and
random bits of gadgetry people used to have. Over time, the nature
of computer games has changed quite considerably: no longer can you
look at the source code for a game just by pressing Escape
or Break and typing
LIST at the ensuing BASIC
prompt; no longer do we have to fiddle with the volume and tone
controls on our tape decks in order to get the latest game to load;
and no longer are we limited to 16 colours (or less).
If you've got a bit of time to spare, and fancy a trip down memory
lane to a youth spent destroying joysticks by playing Daley
Thompson's Decathlon too vigorously or typing in listings from
magazines only to get
SYNTAX ERROR in line 4360 when
you try and run them, buy this book.
Buy this bookAt Amazon.co.uk
Review of Patterns for Parallel Programming by Timothy G. Mattson, Beverly A. Sanders and Berna L. Massingill
Thursday, 01 November 2007
This book gives a broad overview of techniques for writing parallel programs. It is not an API reference, though it does have examples that use OpenMP, MPI and Java, and contains a brief overview of each in appendices. Instead, it covers the issues you have to think about whilst writing parallel programs, starting with identifying the exploitable concurrency in the application, and moving through techniques for structuring algorithms and data, and various synchronization techniques.
The authors do a thorough job of explaining the jargon surrounding parallel programming, such as what a NUMA machine is, what SPMD means, and what makes a program embarrassingly parallel. They also go into some of the more quantitative aspects, like calculating the efficiency of the parallel design, and the serial overhead.
Most of the content is structured in the form of Patterns (hence the title), which I found to be an unusual way of presenting the information. However, the writing is clear, and easily understood. The examples are well though out, and clearly demonstrate the points being made.
The three APIs used for the examples cover the major types of parallel programming environments — explicit threading (Java), message passing (MPI), and implicit threading from high-level constructs (OpenMP). Other threading environments generally fall into one of these categories, so it is usually straightforward to see how descriptions can be extended to other environments for parallel programming.
The authors are clearly coming from a high-performance computing background, with massively parallel computers, but HyperThreading and dual-core CPUs are becoming common on desktops, and many of the same issues apply when writing code to exploit the capabilities of these machines.
Highly Recommended. Everyone writing parallel or multi-threaded programs should read this book.
Buy this book
Patterns for Parallel Programming
Timothy G. Mattson, Beverly A. Sanders and Berna L. Massingill
Published by Addison-Wesley
Monday, 29 October 2007
David Butenhof's Programming with POSIX Threads was published 10 years ago, in 1997. At the time, it was the definitive work on the POSIX thread API, and multi-threaded programming in general. Ten years is a long time in computing so how does it fare today?
New POSIX Standard
When the book was written, the latest version of the POSIX Standard was the 1996 edition (ISO/IEC 9945-1:1996). Since then, the standard has evolved. It is now maintained by a joint working group from The Open Group, the IEEE and ISO called The Austin Group. The new Standard is called the Single Unix Specification, Version 3 and the 2004 edition is available online.
The new standard has brought a few changes with it — many things that were part of extensions such as POSIX 1003.1j are now part of the main ISO Standard. This includes barriers and read-write locks, though barriers are still optional and the read-write locks have a slightly different interface. Programming with POSIX threads is therefore lacking a good description of the now-standard APIs — although Butenhof devotes a section in Chapter 7 to implementing read-write locks, this is now only of historical interest, as the semantics are different from those in the new standard.
Most things stay the same
Though there are inevitably some changes with the new standard, most of the APIs remain the same. Not only that, the fundamental concepts described in the book haven't changed — threads still work the same way, mutexes and condition variables still work the same way, and so forth. Not only that, but the rising numbers of multicore CPU desktop computers means that correct thread synchronization is more important than ever. Faulty assumptions about memory visibility that happened to be true for single core machines are often demonstrably false for multicore and multiprocessor machines, so the dangers of deadlock, livelock and race conditions are ever more present.
Still the definitive reference
Though it's probably worth downloading the new POSIX standard, or checking the
man pages for the new functions,
Programming with POSIX Threads is still a good reference to the POSIX thread APIs, and multi-threaded programming in
general. It sits well alongside Patterns for Parallel
Programming — whereas Patterns for Parallel Programming is mainly about designing programs for concurrency,
Programming with POSIX Threads is very much focused on getting the implementation details right.
Buy this book
Programming with POSIX Threads
Published by Addison-Wesley
Monday, 22 October 2007
As the subtitle of this book says, Fit is the Framework for Integrated Tests, which was originally written by Ward. This is a testing framework that allows tests to be written in the form of Excel spreadsheets or HTML tables, which makes it easy for non-programmers to write tests. This book is divided into several parts. Parts 1 and 2 give an in-depth overview of how to use Fit effectively, and how it enables non-programmers to specify the tests, whereas parts 3-5 provide details that programmers will need for how to set up their code to be run from Fit.
Though I have been aware of Fit for a long time, I have never entirely grasped how to use it; reading this book gave me a strong urge to give it a go. It is very clear, with plenty of examples. I thought the sections on good/bad test structure, and how to restructure your tests to be clearer and easy to maintain were especially valuable — though they are obviously focused on Fit, many of the suggestions are applicable to testing through any framework.
Fit was developed as a Java framework, and so all the programming examples are in Java. However, as stated in the appendix, there are ports for many languages including C#, Python and C++. The way of structuring the fixtures that link the Fit tests to the code under test varies with each language, but the overall principles still apply.
The book didn't quite succeed in convincing me to spend time working with Fit or Fitnesse to try and integrate it with any of my existing projects, but I still think it's worth a look, and will try and use it on my next greenfield project.
Buy this bookAt Amazon.co.uk
Wednesday, 12 April 2006
The opening chapters cover the background, introducing both refactoring and design patterns, and the context in which the book was written. This gives the reader a clear overview of what is involved in Refactoring to Patterns, and paves the way for the refactoring catalogue which makes up the bulk of the book.
The catalogue is divided into chapters based on the type of change required — is this a refactoring to simplify code, generalize code, or increase encapsulation and protection? Each chapter has an introduction which gives an overview of the refactorings contained within that chapter, followed by the refactorings themselves. These introductions clearly illustrate the principles and choices which would lead one to follow the refactorings that follow.
Each refactoring starts with a brief one sentence summary, and before and after structure diagrams with reference to the structure diagrams for the relevant pattern in the Design Patterns book. The sections that follow then cover the Motivation for using this refactoring, step-by-step Mechanics, and a worked Example, relating back to the steps given for the Mechanics. Finally, some of the refactorings finish with Variations on the same theme. The examples are all pulled from a small sample of projects, which are introduced at the beginning of the catalogue section, and help illuminate the instructions given in the Mechanics section. The mechanics themselves are generally clear, and broken down into small steps — sometimes smaller steps than I might take in practice, but I think this is probably wise, as large steps can easily confuse. Finally, the Motivation sections do a good job of explaining why one would choose to do a particular refactoring, and any pitfalls to doing so — the "Benefits and Liabilities" tables provide a useful summary.
This book is well written, easy to read, and genuinely useful. It has helped me put some of the refactorings I do into a larger context, and given me insight into how I can integrate patterns with existing code, rather than designing them in up front. As John Brant and Don Roberts highlight in their Afterword, this is a book to study, the real benefit comes not from knowing the mechanics, but by understanding the motivation, and the process, so that one may apply the same thinking to other scenarios not covered by this book. If you are serious about software development, buy this book, inwardly digest it, and keep it by your side.
Buy this book
Refactoring to Patterns
Published by Addison-Wesley
Wednesday, 12 April 2006
A lot of the book is spent covering different techniques for getting nasty convoluted code under test. These techniques often focus on breaking dependencies, so you can instantiate an object in a test harness, or call a function without it sending an email or talking to the database. In many cases, these are sensible recommendations for improvements to the codebase, but in some cases, Michael recommends techniques you wouldn't expect to see in production code, such as defining preprocessor macros with the same name as functions to avoid calling them, or writing dummy implementations of API functions. This is not to say that the book recommends such techniques wholesale — Michael is keen to point out that these techniques should only be used to get the code under test, so that it can be refactored safely.
Chapters are helpfully named, with titles like "This class is too big, and I don't want it to get any bigger", and the book gives good advice on how to deal with the nastiest codebases. The key recommendation underlying it all is "get the code under test, so you can refactor safely", and this is borne in mind with those techniques that require changing the production code in order to get it under test — these techniques provide step by step instructions to help you make the required changes without breaking anything.
The content of this book is excellent, and the writing clear, so it is unfortunate that it is marred by numerous minor errors, such as spelling mistakes, or using the wrong identifier when referring to a code example. However, this minor niggle is not enough to stop me recommending it — every software developer should have a copy.
Highly Recommended. This book is a must-have for anyone who has to maintain code — which is pretty much every software developer on the planet.
Buy this book
Working Effectively With Legacy Code
Michael C. Feathers
Published by Prentice Hall PTR
Tuesday, 14 February 2006
The project is not just one big success story; Ron shares his mistakes with us so that we may learn from them. The book is interspersed with "lessons", where Ron reflects on the preceding section and tries to identify important points, either things that he felt worked well, or things the mistakes he made, and what he thinks could be done to try and avoid similar mistakes . Also throughout the book are sentences marked "sb", for "sound bite". These are short phrases which summarise a point, like "It's Chet's fault" (don't focus on finding who's at fault when things go wrong, rather focus on fixing the problem), or "You Aren't Gonna Need It" (focus on what needs doing now, rather than what you think you'll need for later). It is these lessons and sound bites which provide the "message" of the book — Ron's belief that incremental development, done test-first, with simple design, continuous refactoring and a focus on producing value for the customer is an effective method of producing high quality software.
If you like Ron's other writing you'll love this book. If you've never read Ron's stuff before and are interested in learning a bit about how he applies the principles of XP (and maybe a little C#), it's worth reading; you might even enjoy it.
Buy this bookAt Amazon.co.uk
Tuesday, 14 February 2006
The book is laid out into a series of chapters describing related techniques, such as "working with test data" and "testing web components", with each chapter split into a series of "recipes", each describing a particular technique. The layout of each recipe is good, with a problem statement, additional background, the details of the recipe itself, and further discussion. There are also references to other related recipes, that provide alternatives to, build on, or are relied on by this recipe.
The level of coverage is very comprehensive. Having read the book it feels like there is a recipe for testing just about everything you could write in Java, from simple classes, to XML generation code, database access code, EJBs, singletons, and JSPs. There are even recipes on managing your test suites, adding tests to hard-to-test classes, and the use of test implementations of other objects to allow testing objects in isolation.
Just because it focuses on Java and JUnit does not mean that this book is useless to anyone programming in another language. On the contrary, many of the techniques described can be applied in any Object Oriented language, though there are certainly some that are specific to Java. For this reason, I would highly recommend this book not just to Java programmers, but to anyone interested in improving the testing of their code.
Buy this bookAt Amazon.co.uk