TITLE: design by contract [ For those of you not familiar with the term, design by contract is a design style advocated by Bertand Meyer (Mr. Eiffel). His book "Object Oriented Software Construction", though Eiffel based, has worthwhile OO design principles in it. In my opinion, it should be on every programmer's required reading list. -adc ] (Newsgroups: comp.lang.c++.moderated, 7 Apr 97) GASPERINA: "Marco Dalla Gasperina" |> There has recently been some (a lot!) of discussion on |> the notions of design by contract (DBC) in comp.object. |> |> I was wondering what the C++ community has come up with |> to use DBC to document and enforce pre/post conditions, |> class invariance, etc. |> |> Some things I was wondering: |> |> (1) Can you set things up with appropriate macros |> to get pre/post conditions to work in the |> presence of inheritance. |> |> (2) Is exception handling required or can you |> get by with error return codes. |> |> (3) Maybe we can see some examples. KANZE: James Kanze I've seen one convention proposed, though I've not really used it rigorously myself. Basically, the convention requires all virtual functions to be private. Instead of writing: class X { public: virtual void f( int ) ; } ; you write: class X { public: void f( int i ) { assert( preconditions ) ; doF( i ) ; assert( postconditions ) ; } private: virtual void doF( int ) ; } ; Note that rigorously used, this is very, very close to what Eiffel does: the "contract" is defined by assertions in the interface code (the class definition), and is inherited by all of the derived classes (since the call always goes through the base class function `f'. The run-time assertions can be turned off and on by manipulating NDEBUG. And it shouldn't be too hard to write a tool which would extract them as part of the documentation. Formally, turning the assertions on in some modules and off in others is a violation of the one definition rule, and thus undefined behavior. Practically, it will in fact work as expected on all implementations I can think of. (At present. I expect that one thing compiler writers will turn their attention to, once the standard is stable, and they no longer have to spend all of their time tracking it, is detecting violations of the one definition rule. At such time, using NDEBUG in one module, and not in another, may result in the program failing to compile.) I suspect that one of the reason such techniques haven't caught on is the difficulty of capturing the full impact of the contract in the postconditions. I normally document the postconditions of all of my functions in the comments, and they frequently contain things like "such and such a window is displayed on the screen". I've yet to find a way to express such conditions in C++. (There is also the question of the infinite number of unexpressed post-conditions: the hard disk is in the same state it was on entering the function, etc., etc.)