Feasability of Design By Contract (DBC) approach in standard C++

  • Thread starter christopher diggins
  • Start date
C

christopher diggins

Bertrand Meyers' DBC (Design By Contract) has an important characteristic,
which is oftentimes ignored, of separating the contract (preconditions /
postconditions / invariants) from the implementation. So it would seem that
ideally we would write the class separate from the contract, and then merge
them. For a small example we could have the following class MFuBar (M for
iMplementation):

class MFuBar {
public:
Fu() { std::cout << "fu" << endl; };
Bar() { std::cout << "bar" << endl; };
};

Let's say that the contract that must be enforced is (in English): any call
to Bar must be precedeed by at least one call to Fu. We could express that
in code as follows:

template<typename T>
class FuBarContract : public T {
public:
FuBarContract() { bCanCallBar = false; };
void Fu() { bCanCallBar = true; T::Fu(); };
void Bar() { assert(bCanCallBar); T::Bar(); bCanCallBar = false; };
private:
bool bCanCallBar;
};

What we could then do is use a conditionally defined typedef, to define a
new type:

#ifdef DEBUG
typedef FuBarContract<MFuBar> FuBar;
#else
typedef MFuBar FuBar;
#endif

Some of the advantages of this technique are that our original type does not
care about the details of the contract and retains a very low complexity.
Another advantage that I see of this technique is that the Contract can
actually be applied to any type that has two Fu and Bar signatures.

What I would like to know is how well this technique accomplishes the spirit
and goals of DBC, along with its viability for production quality code.
Thanks in advance!
 
T

Thorsten Ottosen

Hi Christopher,

For more info, see my paper at

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/n1613.pdf

| Bertrand Meyers' DBC (Design By Contract) has an important characteristic,
| which is oftentimes ignored, of separating the contract (preconditions /
| postconditions / invariants) from the implementation.

I'm not sure what you mean here? Do you mean contracts on declarations as
opposed to on definitions?

|So it would seem that
| ideally we would write the class separate from the contract, and then
merge
| them. For a small example we could have the following class MFuBar (M for
| iMplementation):
|
| class MFuBar {
| public:
| Fu() { std::cout << "fu" << endl; };
| Bar() { std::cout << "bar" << endl; };
| };
|
| Let's say that the contract that must be enforced is (in English): any
call
| to Bar must be precedeed by at least one call to Fu.

that can be accomplshied by the template patterrn. Just wrap the
three function calls in a new function.

| What I would like to know is how well this technique accomplishes the
spirit
| and goals of DBC, along with its viability for production quality code.
| Thanks in advance!

IMO, not that close to DBC.

Btw, if you have ideas about DBC, you are welcome to mail me privately about
them.
Just make sure they are not discussed in my paper.

best regards

Thorsten
 
A

Alf P. Steinbach

* "Thorsten Ottosen said:

Interesting read. I'm too tired right now to do the full honors, or
perhaps I'm just plain fed-up with DBC... ;-) But I do wonder, and I'm
absolutely too lazy to try to find that in your document:

Have you considered interaction of 'the postcondition cannot be weaker',
with the proposal to allow contra-variant reference arguments, which
just about everyone except me in clc++m thought was an excellent idea?

Heh, thought not! ;-)

(Of course I agree that what 'the postcondition cannot be weaker' implies
is exactly what is needed. But in the clc++m discussion slicing was
dismissed as a problem because you can slice and dice in so many other
ways in current C++, so it wouldn't matter. Perhaps DBC can put that
contra-variance proposal on a sound footing type-system-wise.)

Second, in your discussion of where to put the contracts it seems you
have not considered the need for DBC on pure interfaces. That's where
DBC is really needed. For implementations assertions are good enough.

Third, your proposal -- in its current early form -- seems to tie
DBC to ordinary inheritance only. But in template code there is usually
a need for asserting that a template parameter fulfills some contract,
and one absolutely do not want to impose a restriction "well any type
T you pass in here must be derived from my DBC-adorned TInterface". The
reason I think this is very much worth considering is that there's a good
chance that supporting some kind of DBC for template parameters and
template coding in general might not be compatible with just any chosen
"ordinary OO" DBC, then requiring two separate mechanisms, whereas if it
is considered now before choosing anything, it might turn out that there
is at least _one_ mechanism that can be used for both, with small diffs.

Now these are very obvious points, which fast scan of the document did not
turn up, so I suggest a round with perhaps far more reviewers.


PS: I liked the idea about implementing static_assert as DBC... ;-)
 
T

Thorsten Ottosen

Hi Alf,


[snip]

| Have you considered interaction of 'the postcondition cannot be weaker',
| with the proposal to allow contra-variant reference arguments, which
| just about everyone except me in clc++m thought was an excellent idea?
|
| Heh, thought not! ;-)

depends on what you mean :) Would this show it:

#include <iostream>

struct X
{
virtual X& foo()
{
std::cout << "X";
return *this;
}
virtual ~X() {}
};

struct Y : public X
{
virtual Y& foo() // return type "stronger"
{
std::cout << "Y";
return *this;
}
};

?

| (Of course I agree that what 'the postcondition cannot be weaker' implies
| is exactly what is needed. But in the clc++m discussion slicing was
| dismissed as a problem because you can slice and dice in so many other
| ways in current C++, so it wouldn't matter. Perhaps DBC can put that
| contra-variance proposal on a sound footing type-system-wise.)

perhaps. what do you mean with "sound footing"?

| Second, in your discussion of where to put the contracts it seems you
| have not considered the need for DBC on pure interfaces. That's where
| DBC is really needed. For implementations assertions are good enough.

I have considered that; and argue it should be allowed. I'm for allowing
inline
definitions of assertions on pure virtual functions.

| Third, your proposal -- in its current early form -- seems to tie
| DBC to ordinary inheritance only. But in template code there is usually
| a need for asserting that a template parameter fulfills some contract,
| and one absolutely do not want to impose a restriction "well any type
| T you pass in here must be derived from my DBC-adorned TInterface". The
| reason I think this is very much worth considering is that there's a good
| chance that supporting some kind of DBC for template parameters and
| template coding in general might not be compatible with just any chosen
| "ordinary OO" DBC, then requiring two separate mechanisms, whereas if it
| is considered now before choosing anything, it might turn out that there
| is at least _one_ mechanism that can be used for both, with small diffs.

The proposal is in a very early stage. Interactions with something like
concepts
need to be investigated.

br

Thorsten
 
C

christopher diggins

Thorsten Ottosen said:
Hi Christopher,

For more info, see my paper at

http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/n1613.pdf

| Bertrand Meyers' DBC (Design By Contract) has an important characteristic,
| which is oftentimes ignored, of separating the contract (preconditions /
| postconditions / invariants) from the implementation.

I'm not sure what you mean here? Do you mean contracts on declarations as
opposed to on definitions?

I am not aware of the difference between these two kinds of contracts. What
I am trying to get to to is that a contract can, and should, be considered
as a separate, reusable entity which should not interfere in anyway with the
implementation. By defining the contract separately we can wrap any class
with compatible signatures with that the specific contract.
|So it would seem that
| ideally we would write the class separate from the contract, and then
merge
| them. For a small example we could have the following class MFuBar (M for
| iMplementation):
|
| class MFuBar {
| public:
| Fu() { std::cout << "fu" << endl; };
| Bar() { std::cout << "bar" << endl; };
| };
|
| Let's say that the contract that must be enforced is (in English): any
call
| to Bar must be precedeed by at least one call to Fu.

that can be accomplshied by the template patterrn. Just wrap the
three function calls in a new function.

Why would that be superior to the technique that I am proposing?
| What I would like to know is how well this technique accomplishes the
spirit
| and goals of DBC, along with its viability for production quality code.
| Thanks in advance!

IMO, not that close to DBC.

Please explain why.
Btw, if you have ideas about DBC, you are welcome to mail me privately about
them.
Just make sure they are not discussed in my paper.

best regards

Thorsten

Christopher Diggins
 
T

Thorsten Ottosen

| | > Hi Christopher,
| >
| > For more info, see my paper at
| >
| > http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/n1613.pdf
| >
| > | > | Bertrand Meyers' DBC (Design By Contract) has an important
| characteristic,
| > | which is oftentimes ignored, of separating the contract (preconditions
/
| > | postconditions / invariants) from the implementation.
| >
| > I'm not sure what you mean here? Do you mean contracts on declarations
as
| > opposed to on definitions?
|
| I am not aware of the difference between these two kinds of contracts.
What
| I am trying to get to to is that a contract can, and should, be considered
| as a separate, reusable entity which should not interfere in anyway with
the
| implementation. By defining the contract separately we can wrap any class
| with compatible signatures with that the specific contract.

The only such thing I know from Eiffel is to have assertions on pure virtual
functions
(or "deferred" as they are called). Then the assertions are inherited. I'm
in favor of
this feature.

You might also be suggesting that it should apply to any function, not just
virtual ones. That is indeed interesting and I suspect that it could be
discusssed to merge
such facility with the concepts proposal that is being discussed.

| > | Let's say that the contract that must be enforced is (in English): any
| > call
| > | to Bar must be precedeed by at least one call to Fu.
| >
| > that can be accomplshied by the template patterrn. Just wrap the
| > three function calls in a new function.
|
| Why would that be superior to the technique that I am proposing?

I must admit I did not understand exactly what you proposed. I don't see
what
calling two function in a particular order has to do with contracts.

br

Thorsten
 
C

christopher diggins

Thorsten Ottosen said:
| | > Hi Christopher,
| >
| > For more info, see my paper at
| >
| > http://anubis.dkuug.dk/jtc1/sc22/wg21/docs/papers/2004/n1613.pdf
| >
| > | > | Bertrand Meyers' DBC (Design By Contract) has an important
| characteristic,
| > | which is oftentimes ignored, of separating the contract (preconditions
/
| > | postconditions / invariants) from the implementation.
| >
| > I'm not sure what you mean here? Do you mean contracts on declarations
as
| > opposed to on definitions?
|
| I am not aware of the difference between these two kinds of contracts.
What
| I am trying to get to to is that a contract can, and should, be considered
| as a separate, reusable entity which should not interfere in anyway with
the
| implementation. By defining the contract separately we can wrap any class
| with compatible signatures with that the specific contract.

The only such thing I know from Eiffel is to have assertions on pure virtual
functions
(or "deferred" as they are called). Then the assertions are inherited. I'm
in favor of
this feature.

I am proposing a mechanism in order to use DBC as a design technique in C++.
This has nothing to do with Eiffel. With all due respect, I think you may be
confusing DBC with Eiffel's particular syntactic approach.
You might also be suggesting that it should apply to any function, not just
virtual ones. That is indeed interesting and I suspect that it could be
discusssed to merge
such facility with the concepts proposal that is being discussed.

I am suggesting that. Making functions virtual in order to use DBC is a
violation of DBC because you are manipulating implementation to effect a
contract.
| > | Let's say that the contract that must be enforced is (in English): any
| > call
| > | to Bar must be precedeed by at least one call to Fu.
| >
| > that can be accomplshied by the template patterrn. Just wrap the
| > three function calls in a new function.
|
| Why would that be superior to the technique that I am proposing?

I must admit I did not understand exactly what you proposed. I don't see
what
calling two function in a particular order has to do with contracts.

br

Thorsten

That was just a sample contract. A contract is a set of constraints on the
usage of a function or type that should be adhered to but we do not wish to
make part of the implementation. See Meyers' example at
http://archive.eiffel.com/doc/manuals/technology/contract/ labelled
4-Contracts in Analysis where he uses a comparable analogy of in_valve /
out_valve which has a temporal dependence between functions.
 
T

Thorsten Ottosen

[snip]
| > | implementation. By defining the contract separately we can wrap any
| class
| > | with compatible signatures with that the specific contract.
| >
| > The only such thing I know from Eiffel is to have assertions on pure
| virtual
| > functions
| > (or "deferred" as they are called). Then the assertions are inherited.
I'm
| > in favor of
| > this feature.
|
| I am proposing a mechanism in order to use DBC as a design technique in
C++.
| This has nothing to do with Eiffel. With all due respect, I think you may
be
| confusing DBC with Eiffel's particular syntactic approach.

I guess it depends on how you define
DBC.

| > You might also be suggesting that it should apply to any function, not
| just
| > virtual ones. That is indeed interesting and I suspect that it could be
| > discusssed to merge
| > such facility with the concepts proposal that is being discussed.
|
| I am suggesting that. Making functions virtual in order to use DBC is a
| violation of DBC because you are manipulating implementation to effect a
| contract.

Could you explain that last sentence, please.

| > I must admit I did not understand exactly what you proposed. I don't see
| > what
| > calling two function in a particular order has to do with contracts.
|
| That was just a sample contract. A contract is a set of constraints on the
| usage of a function or type that should be adhered to but we do not wish
to
| make part of the implementation. See Meyers' example at
| http://archive.eiffel.com/doc/manuals/technology/contract/ labelled
| 4-Contracts in Analysis where he uses a comparable analogy of in_valve /
| out_valve which has a temporal dependence between functions.

I've looked at the example, and I don't see any temporal constraints beyond
some functions are called in preconditions and some in postconditions.
fill() is btw a pure virtual function.

Anyway, the idea about having assertions separated from code is ok and needs
to
be investigated.

br

Thorsten
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,567
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top