Data on defect analysis is a little sketchier. I present below a table of the defect classifications and their average duration for both C++ and Eiffel. Note that this table does include design injections, as they were too difficult to separate for this analysis.
Table 15-1. Average duration of defect types, C++ and Eiffel
Defect Type | Avg Duration - C++ | Avg Duration - Eiffel |
ct | 0.89 | 0.62 |
ic | 3.3 | 1.63 |
is | 1.72 | 0.23 |
iu | 3.78 | 0.16 |
ma | 3.42 | 1.05 |
mc | 0.4 | 1.04 |
md | 3.27 | 3.10 |
mi | 0.72 | 2.18 |
sy | 0.54 | 0.44 |
wa | 6.85 | 6.49 |
wc | 3.33 | 1.72 |
wn | 0.9 | 0.78 |
wt | 2.69 | 0.68 |
Most of these numbers aren't significant, but a few drew my attention. Note particularly the big split between wt (wrong type) in C++ (2.69 minutes) and Eiffel (0.68 minutes)-- significant, and understandable. The C++ compiler is very lazy about types, allowing easy (and often cryptic) conversion between real and integer values. The Eiffel compiler would have none of that, and quickly identified these problems.
The numbers for iu (interface use, 3.78 vs 0.16) are even more interesting, and I believe strongly reflect the easy-to-use documentation which can be generated from Eiffel classes. While it's true that similar utilities exist for C++, they are 1) not standard, and 2) do not include the contractual information (pre- and post-conditions) which describe the semantics of Eiffel features; this makes for a significant increase in reuse of Eiffel code as compared to C++ code, particularly as the Eiffel community tends to use more useful parameter names than the C++ community. I could use the Eiffel ARRAY and LIST classes "right out of the box" by examining their automatic documentation. Reading the header files for the C++ vector and list classes was both irritating and error-prone.
Several other errors were easier to catch under Eiffel; ma (missing assignment) was generally easy to catch in the expansive stack traces printed out after each Eiffel exception trap (the messages printed by C++ and my contract macros were not nearly as helpful). Wrong calls (wc) were similarly easy to find. And some variants of syntax (sy) from C++, such as the need to maintain parity between header and implementation files, simply went away (as would memory management issues, although they were not a problem with these programs).
On the other hand, Eiffel did take a few hits here, mostly in mc (missing call) and mi (missing implementation), both of which were used by me when I ran into something that I didn't have a standard library class for. The Eiffel standard library is extremely good, but did have a few shortcomings. Overall, however, I found the process of debugging Eiffel code to be significantly more pleasant than that of C++ code, even though (and this is the really interesting part, to me) I had a very nice debugger for C++ and no debugger at all for Eiffel.