Boost logo

Boost :

From: Dan W. (danw_at_[hidden])
Date: 2004-01-03 00:50:01


Thorsten Ottosen wrote:
>>In public interfaces no, as the preconditions are in the extracted
>>header, but the preconditions in private functions, and all non-public,
>>implementation classes in the object code, preconditions are gone.
>>Wouldn't make sense to keep them without source code to debug.
> I meant from the object code. If you cannot remove debug stuff from your
> object code, then you might choose not to use it.

Yes, I misred your statement the first time; I thought you were saying
"one could not choose to remove" instead of "one could choose not to
remove", and so I thought you were talking about the classes forming the
interface of a library, which, indeed, you cannot remove the
preconditions (or postconditions) from, at the time you build the
library (otherwise client code could not interface with it using DBC).
But you were just talking about the fact that Eiffel allows you to
choose not to remove preconditions from compiled code. This is also
true; however I take issue with the feature, as I've said in another
post, on the basis that preconditions and postconditions are cheap and
dirty fuses for debugging, and are not intended as a substitute for
exception handling. And in fact I don't think any Eiffel programmer ever
left contracts in production code.

Debugging assertions and DBC are fuses: Something goes wrong and the
program terminates. Is that something you'd want? Depends on the user's
application of the application. In some situations, continuing to run
with a program whose invariants are compromised is too great a risk --it
might corrupt a vital file. Sometimes, shutting down the program might
cause enormous damage, like the trivial assertion that brought down that
Arienne 5 rocket... Run-time exception handling in production code needs
to be designed with an explicit policy in mind; can't just use a fuse.

>>"..ruin the overview of a class"?! The class *IS* its contracts!
> yes, but from a design perspective you really want to keep an overview of
> your code, if you can. This is one of the problems with C++ and templates
> today.
> you either implements everything inline in the class and loose the overview
> of what you're
> doing or you implements everything after the class declaration and type in
> sooo many
> characters in the file that you get COBOL-fngers. (btw, there is a proposal
> that aims to solve this).

Oh, I see what you're saying. I thought you meant "overview" at an
abstract level. I definitely like to see my class fit 1024 pixels
vertical. I hope the proposal gets accepted, no matter what it says...
(can't be worse than the current state of affairs)... Yup, my carpal
tunnel syndrom suffers from a person condition sometimes. Still, I
prefer to type under the class, for now.

>>Maybe we're talking about different parts of DBC... Okay, variant and
>>invariants are not meant to be 'public DBC', and should NOT be in the
>>header file.
> Not the invariant? I would have said that a part of the invariant that
> describes
> certain relationsships between the public value returning functions would be
> usefull documentation.

Yeah, first I said that it 'should' be in the header, then I went to say
that it 'shouldn't'. The thing is, the invariant of a class is
absolutely nobody-else's business. Sure it documents the class, to the
implementer; but a client of the class needs to know nothing about its
invariants. Invariants ARE documentation; I totally agree; but it's
just not *public* documentation; --rather meant to be an X-file, and be
kept in the CPP cabinet. On the other hand, the class variables are
declared in the header file, and the invariants are closely related to
them... Maybe that's why I like the pimpl idiom so much...

>>Maybe I should have clarified that; sorry, my fault. But preconditions
>>and postconditions in public functions are what defines and documents
>>what those public functions demand and promise, for all to see. If they
>>were non-header, it would mean that the contract could be secretly
>>altered, without the consent of the class' clients.
> yes, but couldn't one just extract documentation from the source file? As I

"One" could, but can the compiler do so on behalf of the client class?
The client class includes the header of your class, and the public
function preconditions and postconditions need to be there, otherwise my
class won't compile. The precondition, in Eiffel, is technically,
neither a member of the class in which it is declared, nor of the
client; it is rather like a free function, or static function. If it
hides from me, I can't link to it. And as a programmer, if I want to
know whether your function is any good, I need to look at its
postconditions, and I expect to find its postconditions hanging on the
front window, with lights flashing around it; not hidden somewhere with
the X-files. Else I wouldn't think much of your marketing skills.. :-)
Postconditions are the product your function sells, and preconditions
are the price-tag. It would make no sense to hide them in the cpp file.

> the Eiffel headers is already an extract of the source files? No matter what
> scheme, you would still
> have to read the updated documentation (whether a header or something else).

Precisely, you don't want to read an html doc where you could read a
much more eloquent hpp doc, which has the built-in guarantee of being in
synch with the latest code.. ;-) That's one of the vivid memories I
have of working with Eiffel: you read through a class header, and every
line of DBC code is worth 100 lines of dubious plain language
documentation; and you *know* it's current; and, if it works, accurate.

No matter how much overview you may have of a C++ class, and no matter
how well named the functions are, you're still full of doubts, unless
you read detailed documentation, or have access to the source.

   static void insert_char( char* s, int len, int pos, char const & c );

Fairly well written, wouldn't you say? Yet, I'm not sure what happens if
pos is greater than len. I don't know if MAXLEN is taken care of by the
caller or not. I don't know what happens if I give it a null pointer
for a string. Chances are it throws, or crashes, or maybe it allocates
the string itself, if it's not there. Who knows? There goes another half
hour of my precius time looking for where is it documented.. But...

   static void insert_char( char* s, int len, int pos, char const & c )
   {
   preconditions:
      s && strlen(s)==len && pos>=0 && pos<=len && (int)c<128;
   postconditions:
      s && len && strlen(s)==len+1 && s[pos]==c;
   }

That tells me a bit more... Well, I'm preaching to the converted. What
I was saying is that this needs to be in the header file. I cannot
extract it from your cpp file anyhow, since I have no access to it, as
you won't give it to me, otherwise I wouldn't have to pay you for your
fancy library :)

Cheers!


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk