Design by Contract in C++?
An anonymous reader asks: "I have read some of the stuff on Eiffel, watched their tutorial videos about design by contract, and the entire thing sounds like a pretty good idea. However, the problem is that we don't use Eiffel at work, and I highly doubt I could get people to come around to the idea of switching to it. Although we use a lot of C++, I can imagine that a lot of the ideas from Eiffel can be applied there. I have looked around on the net and found a few articles talking about different ways of applying design by contract using assert statements and the like. I also found the dlib C++ library on SourceForge which, among other things, puts a design by contract face on a lot of API calls. So, there are obviously people doing it. What is everyone's experience with Design by Contract in C++? What tools are there that help make it a workable system? Lastly, are there any pitfalls to taking this approach in C++?"
You know, not _every_ programming design method or management method is necessarily a "fad". Some of these things are popular because they are useful.
For what it's worth, design by contract is *very* useful when you are writing software for things that absolutely need to work, guaranteed (eg; medical, aviation, energy, etc). Eiffel is so good at this particular way of describing software that it literally changes how you think about programs.
Maybe you should take a look at it before going off about conspiracies..
Here are some pitfalls you might run into:
1. Real DBC inherits the contracts from ancestor versions. Preconditions are or-ed together and postconditions are anded together. Invariants are also anded together. If you just use assertions you won't get this.
2. Eiffel allows you to disable the run-time execution of contracts at a fine level of detail. Again, if you use assertions you can only enable all or disable all.
3. There is no 'old' keyword in C++. Therefore you can't use 'old' in assertions.
4. According to DBC, a routine is in a transitional state during the execution of a routine. What happens if a routine calls another routine in the same class? Should it check the invariant? The answer is no. There are other cases as well.
5. It's difficult to implement a loop variant with an assertion. Not a big deal since most Eiffel code I've seen doesn't use loop variants.
If you don't want to use assertions, you can try some of the class pre-processors that are out there. You will see mixed results. In particular, I don't know of one that can handle 4. This is a show stopper.
I think you only have two choices. Use Eiffel or don't use contracts.
Brian
>I suggest you read it.
:o)
I agree. It's a great read. Made me glad to be a programmer.
I'd also recommend "Code Complete".
Read both once a year
Design by contract, like all the others, are just tools. Treat them as such, and use them when you feel appropriate. No matter how good a screwdriver you have, one is never enough.
Open Source Drum Kit, LPLC deve board - mjhdesigns.com
Besides the many very good points you mention there's also the question of documentation - good DbC systems are integrated into the autogenerated documentation elegantly. All that said, you do have more options then Eiffel if you want to use contracts. If you use Java you can use JML which I believe covers all your points, and my point about documentation. If you use Ada you can use SPARK which again, covers your points quite well. Both SPARK and JML also offer (via ESC/Java2 for JML) extended static checking as well as the usual runtime checking of contracts. Finally for C# there's Spec#, but I don't know too much about that one.
Still, Eiffel is actually an extremely elegant language with powerful DbC built into at the core. If DbC is something that's important to you Eiffel probably is your best choice.
Craft Beer Programming T-shirts