July 14, 2004
Arcane Jill wrote:

>In article <cd33r9$1cjn$1@digitaldaemon.com>, Arcane Jill says...
>  
>
>>In article <cd2rij$tra$1@digitaldaemon.com>, Matthew says...
>>
>>    
>>
>>>I don't agree. Exceptions are for exceptional conditions, i.e failures, not human
>>>errors. If you want to be "strict", then the right thing to do when a DbC
>>>condition is violated is to halt. An exception is not the appropriate response.
>>>      
>>>
>>Eh?
>>    
>>
>
>
>
>So what's wrong with this then?
>
>#    Int sqrt(Int x)
>#    {
>#        if (x < 0) throw new IntException("sqrt(x) not defined for x < 0");
>#        //...
>#    }
>
>An assert is DEFINITELY not the right thing here. The input could come from the
>intermediate result in a long calculation. Whether or not x is negative may not
>be deducable at compile time. So it's an error, and that's EXACTLY what
>exceptions are for.
>  
>
I would be fired on the spot if I wrote code like that in my industry.  For a small function like sqrt, you don't want the extra overhead of exceptions in a release versions of the code.  It really is an error on the caller, its not the sqrts fault that such a value was passed in.  Assertions are about contracts, making sure the pre and post conditions are correct.  Exceptions are about handling errors that arise in the code that you may not be there to fix when they occur.


-- 
-Anderson: http://badmama.com.au/~anderson/
July 14, 2004
"J Anderson" <REMOVEanderson@badmama.com.au> wrote in message news:cd0odg$4rp$1@digitaldaemon.com...
> Matthew Wilson wrote:
>
> >Can I register yet another request for this long-looked-for feature?
> >
> >I'm finding it rather painful that the output just prints "Error: AssertError Failure vector(390)". It's just a PITA.
> >
> >Can we get this for 1.0?
> >
> >
> >
> >
> Yes, please.
>
> Speaking of asserts, another useful feature would be a continue (ie ignore/ignore all) option.  That is particularly useful when working in a large group of people and someone stuffs up part of the build that is not very important to you (ie you working on graphics and someone stuff up the sound engine).  Although I'm not exactly sure how that would work though.

Agreed. I was thinking along the same lines.

> I think the best option (parhaps 2.0) is to allow for our own customisable asserts. That way we can stop things like timers, things over networks and graphics cards and re-start them again when continued.  We can then also put up a nice OS based interface to deal with asserts.  That is the safest option.

Sounds useful


July 14, 2004
On Wed, 14 Jul 2004 22:46:12 +0800, J Anderson wrote:

> teqDruid wrote:
> 
>>void myAssert(bit condition, char[] message) {
>>	if (condition)
>>		throw new myException(message);
>>}
>>}
>>I'm not sure what it is you're looking for that can't be done with
>>Exceptions.
>>
>>
>> 
>>
> The thing is the line-number+filename.  Now you can do a stack trace but that's not very convenient in many situations, particularly if your working on a different OS which has no general console.
Asserts are useful, but I believe it would make the language more powerful if the line numbers and filenames were exposed to it, so Exceptions had access to that info.

> 
> Also message assert need to be standardised.  Its an extreamly useful tool.  Each developer (and they will) should not need to write their own.

July 14, 2004
Firstly, I don't read Arcane Jills caps to be shouting but rather emphasis of key/important words. I use things like *this* to mean emphasis, Jill uses THIS, I can handle both.

Secondly, lets take a step back and look at this with a broader example..

Say I write a word processor, say I use your recls code to list files in a directory, say the user specifies a path, I don't check thier input, and call a fn in your API with an invalid parameter.

You API will assert, my app will terminate, the user will loose their work.

This is not a good outcome.

Should I have checked the parameter I passed to you? Perhaps, that is one solution, assuming I did that, now my program checks the parameter, and then so does your API call, so we're checking something twice, what is the point of the seccond check?

Obviously the seccond check is required, your API needs to ensure it's input is not erroneous, so then I ask what is the point of the first check?

So we're back to not checking the input, but, we cannot have the app asserting and loosing the users work. *If* your assert was an exception I could catch it, give an error to the user and continue. The exception gives me the *user* of your API the choice.

I think I'll grab a copy of "Meyers book" what is it's title? (It must be here somewhere but I can't find it)

I typically only use asserts for internal functions/methods, ones that are *not* published in my API. To me asserts represent bugs/failures in my API, not in it's use.

Regan.

On Wed, 14 Jul 2004 21:47:06 +1000, Matthew <admin@stlsoft.dot.dot.dot.dot.org> wrote:
> "Arcane Jill" <Arcane_member@pathlink.com> wrote in message
> news:cd35jt$1fll$1@digitaldaemon.com...
>> In article <cd33r9$1cjn$1@digitaldaemon.com>, Arcane Jill says...
>> >
>> >In article <cd2rij$tra$1@digitaldaemon.com>, Matthew says...
>> >
>> >>I don't agree. Exceptions are for exceptional conditions, i.e 
>> failures, not
> human
>> >>errors. If you want to be "strict", then the right thing to do when a 
>> DbC
>> >>condition is violated is to halt. An exception is not the appropriate
> response.
>> >
>> >Eh?
>>
>>
>>
>> So what's wrong with this then?
>>
>> #    Int sqrt(Int x)
>> #    {
>> #        if (x < 0) throw new IntException("sqrt(x) not defined for x < 0");
>> #        //...
>> #    }
>>
>> An assert is DEFINITELY not the right thing here. The input could come from the
>> intermediate result in a long calculation. Whether or not x is negative may not
>> be deducable at compile time. So it's an error, and that's EXACTLY what
>> exceptions are for.
>
> You're making assertions here (pardon the pun) that totally miss the point. An
> assertion is a contract enforcement. Failure to meet the contract should result
> in failure.
>
> In the code above you would, one might hope, document that your sqrt function is
> happy to receive -ve values, in which case sqrt will throw an IntException. Given
> that, throwing the exception is valid.
>
> If I was writing it, I would have it as part of sqrt's precondition that x>=0.
> Thus, if x < 0, I would issue an assertion (in the broad sense of the term, not
> necessarily do assert()), and the process would halt.
>
> So, your assertion that "An assert is DEFINITELY not the right thing here" is
> only correct if you stipulate that -ve values are valid wrt to the contract for
> sqrt. If that's not the case, then it's just hot air, and your shouting is crass.
>
>> And it will only halt the program if the exception is not caught. (Which is
> fair
>> enough, I think). Anyone canny enough to wrap such calls in a try block can do
>> their own tidy-up. And if they don't they'll get a nice error message.
>
> And imagine all the nice extra code doing all this defensive programming. Yummy!
>
> I can only recommend you read Meyers book. A strong indication of the quality of
> the work is the degree to which it has influenced Walter's thinking (something
> notoriously difficult to do) despite the fact that he slags Walter off in Chapter
> 14.
>
>> On the other hand, the Int class also supplies some LOW LEVEL functions. Here's
>> one:
>>
>> #    uint bigintLLAdd(uint* d, uint* x, uint xLen, uint* y, uint yLen)
>> #    in
>> #    {
>> #        assert(xLen >= yLen);
>> #    }
>>
>> whereby the input MUST obey (xLen >= yLen), and if it doesn't then it's a bug
> on
>> the part of the caller. The assert tells whoever wrote the calling function to
>> fix /their/ bug. This sort of thing I only ever do on seriously low level code,
>> at the pointer and buffer level, where undefined behavior is the guaranteed
>> result of naff input. As Norbert (I think) said, an "in" condition is part of
>> the function's interface.
>>
>> So what do YOU think is the correct thing to do then, in both of these
>> circumstances? And when exactly would you throw an exception?
>
> I can't be bothered to plough through all the shouting in the second one, but I
> can tell you I'd make the function conform to its contract.
>
>> Note that the phrase "exceptional conditions, i.e failures" is nonsense, since
>> "exceptional conditions" does NOT mean the same thing as "failures". (The Latin
>> abbreviation i.e. stands for "id est", which means "that is", "that is to say",
>> or "in other words"). They're called "Exceptions" because they happen in
>> exceptional (that is, rare, uncommon) circumstances. They're not called
>> "Failures", a word which means something completely different. Perhaps you
> could
>> clarify your meaning?
>
>
>



-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 15, 2004
"Regan Heath" <regan@netwin.co.nz> wrote in message news:opsa5ilho05a2sq9@digitalmars.com...
> Firstly, I don't read Arcane Jills caps to be shouting but rather emphasis of key/important words. I use things like *this* to mean emphasis, Jill uses THIS, I can handle both.

Ok. I understand that netiquette decreed - and I've been served many rebukes from C++ gliterrati who enjoy pointing out e-manners more than they like debating how many empty bases you can stuff onto the head of a pin - that

    _this is emphasis_
   *this is a bit of a raised voice*
    THIS IS SHOUTING

and, furthermore, that *this* may be interpreted as aggressive and THIS most certainly is aggresive.

Oh well, hay ho!

> Secondly, lets take a step back and look at this with a broader example..
>
> Say I write a word processor, say I use your recls code to list files in a directory,

You cunning dog. You know a little flattery with recharge my battery. ;)

> say the user specifies a path, I don't check thier input, and call a fn in your API with an invalid parameter.
>
> You API will assert, my app will terminate, the user will loose their work.

Assuming you've passed in something that violates the pre-condition, yes.

(Although, recls does not assert on invalid patterns or directories, it returns a status code indicating such. But let's assume for the sake of argument.)

> This is not a good outcome.

Agreed.

> Should I have checked the parameter I passed to you? Perhaps, that is one solution, assuming I did that, now my program checks the parameter, and then so does your API call, so we're checking something twice, what is the point of the seccond check?

[Meyer1997]: "Assertions are not an input checking mechanism"

And I never use them as such.

However, I need to qualify that. In STLSoft there are some assertions for pre-condition checking that masquerade as input validation. That's an aide d'discoverbilitae (apologies to any French speakers for my bastardisation). We have a similar thing in much of Phobos, where the in{} clause checks that something's not null. This is acceptable because both D and C/C++ have it as part of their culture that libraries may expect their clients to be correct. Were this not the case, then we're in the fat realm of the defensive programmer.

In other words C/C++/D (can, they don't always do so) sacrifice DbC for release mode for the sake of efficiency. In and of itself, this does not negate the legitimacy of DbC, and all its ramifications. In practical terms, it simply means that the process will crash. Since a "caught" violation of a DbC contract is a halt, albeit one with some kind of message, the "uncaught" crash remains faithful to the cause.

So, now that we've got that out of the way, we can look again at your concerns ...

> Obviously the seccond check is required, your API needs to ensure it's input is not erroneous, so then I ask what is the point of the first check?

One is user input validation, the other is contract enforcement. Consider the main entry function, Recls_Search()

RECLS_FNDECL(recls_rc_t) Recls_Search(  recls_char_t const  *searchRoot
                                    ,   recls_char_t const  *pattern
                                    ,   recls_uint32_t      flags
                                    ,   hrecls_t            *phSrch);

Now, the contract for this function stipulates that it accepts NULL for searchRoot and for pattern. This means, respectively, to use the current directory, and to search for all files.

Conversely, the contract stipulates that phSrch is *not* NULL. There is an assertion to that effect.

Thus, if you pass a null pointer to Recls_Search, then you're going to get a halt, one way or another. In debug mode, you'll have a nice assertion and receive (since this is C/C++, not D) "Assertion failure: ...\recls_api.cpp(161): NULL != phSrch", or something similar. In release mode your halt will be less glamorous, since two lines later we have the statement "*phSrch = static_cast<hrecls_t>(0);"

Now, one can certainly write defensively and test for phSrch. I used to do a lot more of that than I do now. Aside from the tedium, there are very good reasons why this is a "bad thing". Meyers goes through this in detail. For me there are three reasons. First it's more effort. Second you tend not to catch errors (by which I mean human coding errors, not exceptions) anywhere near as you might - your development time increases. Third, the locality of an error is lost, making tracking down a non-functioning application _far_ harder. I promise you that over the last few years when I've got less defensive, and more "aggresive", my coding time has dropped enormously, and application robustness has increased significantly.

> So we're back to not checking the input, but, we cannot have the app asserting and loosing the users work. *If* your assert was an exception I could catch it, give an error to the user and continue. The exception gives me the *user* of your API the choice.
>
> I think I'll grab a copy of "Meyers book" what is it's title? (It must be here somewhere but I can't find it)

"Object Oriented Software Construction" (Prentice-Hall)

Be sure to write to him that it's a nice book, but you think Walter kicks his butt. ;)

> I typically only use asserts for internal functions/methods, ones that are *not* published in my API. To me asserts represent bugs/failures in my API, not in it's use.
>
> Regan.
>
> On Wed, 14 Jul 2004 21:47:06 +1000, Matthew <admin@stlsoft.dot.dot.dot.dot.org> wrote:
> > "Arcane Jill" <Arcane_member@pathlink.com> wrote in message news:cd35jt$1fll$1@digitaldaemon.com...
> >> In article <cd33r9$1cjn$1@digitaldaemon.com>, Arcane Jill says...
> >> >
> >> >In article <cd2rij$tra$1@digitaldaemon.com>, Matthew says...
> >> >
> >> >>I don't agree. Exceptions are for exceptional conditions, i.e
> >> failures, not
> > human
> >> >>errors. If you want to be "strict", then the right thing to do when a
> >> DbC
> >> >>condition is violated is to halt. An exception is not the appropriate
> > response.
> >> >
> >> >Eh?
> >>
> >>
> >>
> >> So what's wrong with this then?
> >>
> >> #    Int sqrt(Int x)
> >> #    {
> >> #        if (x < 0) throw new IntException("sqrt(x) not defined for x <
> >> 0");
> >> #        //...
> >> #    }
> >>
> >> An assert is DEFINITELY not the right thing here. The input could come
> >> from the
> >> intermediate result in a long calculation. Whether or not x is negative
> >> may not
> >> be deducable at compile time. So it's an error, and that's EXACTLY what
> >> exceptions are for.
> >
> > You're making assertions here (pardon the pun) that totally miss the
> > point. An
> > assertion is a contract enforcement. Failure to meet the contract should
> > result
> > in failure.
> >
> > In the code above you would, one might hope, document that your sqrt
> > function is
> > happy to receive -ve values, in which case sqrt will throw an
> > IntException. Given
> > that, throwing the exception is valid.
> >
> > If I was writing it, I would have it as part of sqrt's precondition that
> > x>=0.
> > Thus, if x < 0, I would issue an assertion (in the broad sense of the
> > term, not
> > necessarily do assert()), and the process would halt.
> >
> > So, your assertion that "An assert is DEFINITELY not the right thing
> > here" is
> > only correct if you stipulate that -ve values are valid wrt to the
> > contract for
> > sqrt. If that's not the case, then it's just hot air, and your shouting
> > is crass.
> >
> >> And it will only halt the program if the exception is not caught. (Which is
> > fair
> >> enough, I think). Anyone canny enough to wrap such calls in a try block
> >> can do
> >> their own tidy-up. And if they don't they'll get a nice error message.
> >
> > And imagine all the nice extra code doing all this defensive programming. Yummy!
> >
> > I can only recommend you read Meyers book. A strong indication of the
> > quality of
> > the work is the degree to which it has influenced Walter's thinking
> > (something
> > notoriously difficult to do) despite the fact that he slags Walter off
> > in Chapter
> > 14.
> >
> >> On the other hand, the Int class also supplies some LOW LEVEL
> >> functions. Here's
> >> one:
> >>
> >> #    uint bigintLLAdd(uint* d, uint* x, uint xLen, uint* y, uint yLen)
> >> #    in
> >> #    {
> >> #        assert(xLen >= yLen);
> >> #    }
> >>
> >> whereby the input MUST obey (xLen >= yLen), and if it doesn't then it's
> >> a bug
> > on
> >> the part of the caller. The assert tells whoever wrote the calling
> >> function to
> >> fix /their/ bug. This sort of thing I only ever do on seriously low
> >> level code,
> >> at the pointer and buffer level, where undefined behavior is the
> >> guaranteed
> >> result of naff input. As Norbert (I think) said, an "in" condition is
> >> part of
> >> the function's interface.
> >>
> >> So what do YOU think is the correct thing to do then, in both of these circumstances? And when exactly would you throw an exception?
> >
> > I can't be bothered to plough through all the shouting in the second
> > one, but I
> > can tell you I'd make the function conform to its contract.
> >
> >> Note that the phrase "exceptional conditions, i.e failures" is
> >> nonsense, since
> >> "exceptional conditions" does NOT mean the same thing as "failures".
> >> (The Latin
> >> abbreviation i.e. stands for "id est", which means "that is", "that is
> >> to say",
> >> or "in other words"). They're called "Exceptions" because they happen in
> >> exceptional (that is, rare, uncommon) circumstances. They're not called
> >> "Failures", a word which means something completely different. Perhaps
> >> you
> > could
> >> clarify your meaning?
> >
> >
> >
>
>
>
> -- 
> Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/


July 15, 2004
On Thu, 15 Jul 2004 10:15:09 +1000, Matthew <admin@stlsoft.dot.dot.dot.dot.org> wrote:
> "Regan Heath" <regan@netwin.co.nz> wrote in message
> news:opsa5ilho05a2sq9@digitalmars.com...
>> Firstly, I don't read Arcane Jills caps to be shouting but rather emphasis
>> of key/important words. I use things like *this* to mean emphasis, Jill
>> uses THIS, I can handle both.
>
> Ok. I understand that netiquette decreed - and I've been served many rebukes from
> C++ gliterrati who enjoy pointing out e-manners more than they like debating how
> many empty bases you can stuff onto the head of a pin - that
>
>     _this is emphasis_
>    *this is a bit of a raised voice*
>     THIS IS SHOUTING
>
> and, furthermore, that *this* may be interpreted as aggressive and THIS most
> certainly is aggresive.
>
> Oh well, hay ho!

I find myself using both *this* and THIS to mean emphasis, I did not even know _this_ existed, you learn something new every day. I'll _try_ and change my habits :)

>> Secondly, lets take a step back and look at this with a broader example..
>>
>> Say I write a word processor, say I use your recls code to list files in a
>> directory,
>
> You cunning dog. You know a little flattery with recharge my battery. ;)

:) It seemed as good an example as any other. To tell the truth I have not had cause to use it, yet.

>> say the user specifies a path, I don't check thier input, and
>> call a fn in your API with an invalid parameter.
>>
>> You API will assert, my app will terminate, the user will loose their
>> work.
>
> Assuming you've passed in something that violates the pre-condition, yes.

"invalid parameter" to me means "violates the pre-condition"

> (Although, recls does not assert on invalid patterns or directories, it returns a
> status code indicating such. But let's assume for the sake of argument.)
>
>> This is not a good outcome.
>
> Agreed.

Funny how everyone agrees on the end result, just not how to get there.

>> Should I have checked the parameter I passed to you? Perhaps, that is one
>> solution, assuming I did that, now my program checks the parameter, and
>> then so does your API call, so we're checking something twice, what is the
>> point of the seccond check?
>
> [Meyer1997]: "Assertions are not an input checking mechanism"
>
> And I never use them as such.
>
> However, I need to qualify that. In STLSoft there are some assertions for
> pre-condition checking that masquerade as input validation. That's an aide
> d'discoverbilitae (apologies to any French speakers for my bastardisation). We
> have a similar thing in much of Phobos, where the in{} clause checks that
> something's not null. This is acceptable because both D and C/C++ have it as part
> of their culture that libraries may expect their clients to be correct.

That does not make it 'good' only 'consistent'.

> Were this
> not the case, then we're in the fat realm of the defensive programmer.

I was once told to program my APIs as if my input was from a 'half sane monkey on crack' I guess that makes me a defensive programmer.

> In other words C/C++/D (can, they don't always do so) sacrifice DbC for release
> mode for the sake of efficiency.

I can understand that, however IMO you cannot possibly find/catch _all_ the bugs in debug mode/testing. So some will creep thru into the relase build.

Who cares how fast it runs if it's gonna crash? Your program will simply crash faster.

> In and of itself, this does not negate the
> legitimacy of DbC, and all its ramifications. In practical terms, it simply means
> that the process will crash. Since a "caught" violation of a DbC contract is a
> halt, albeit one with some kind of message, the "uncaught" crash remains faithful
> to the cause.

I don't think I like this cause, it casues:
 - me to rely on the OS for a backtrace to find my bugs
 - the user to loose thier work.

An exception solves the above problems.

> So, now that we've got that out of the way, we can look again at your concerns
> ...
>
>> Obviously the seccond check is required, your API needs to ensure it's
>> input is not erroneous, so then I ask what is the point of the first check?
>
> One is user input validation, the other is contract enforcement.

I think your "contract enforcement" is simply another way of saying "input checking" which would mean you were breaking Meyers rule:
  "Assertions are not an input checking mechanism"

Perhaps the above rule when it refers to 'input' is referring to 'end user' input?

Using your example below, in _most_ cases the phSrch parameter will _not_ be affected by user input, meaning, so long as the developer passes one they'll never see the assert. And if they fail to pass one they'll see the assert once causing them to pass one in future.

However, if it were affected by user input then you would not want an assert, you'd want an exception. I could dream up some buggy code where this is the case but I believe you can imagine it too.

So whether you want to assert or throw an exception is based on the program calling your API, your API cannot possibly make this choice. By using an assert here, you're either:
 - achieving nothing (the developer never sees it, or sees it once)
 - causing problems (the app terminates the user loose their work)

Given that, API input _must_ be treated as end user input and thus you cannot use assertions.

> Consider the
> main entry function, Recls_Search()
>
> RECLS_FNDECL(recls_rc_t) Recls_Search(  recls_char_t const  *searchRoot
>                                     ,   recls_char_t const  *pattern
>                                     ,   recls_uint32_t      flags
>                                     ,   hrecls_t            *phSrch);
>
> Now, the contract for this function stipulates that it accepts NULL for
> searchRoot and for pattern. This means, respectively, to use the current
> directory, and to search for all files.
>
> Conversely, the contract stipulates that phSrch is *not* NULL. There is an
> assertion to that effect.

It could be a InvalidParameterException instead.

> Thus, if you pass a null pointer to Recls_Search, then you're going to get a
> halt, one way or another. In debug mode, you'll have a nice assertion and receive
> (since this is C/C++, not D) "Assertion failure: ...\recls_api.cpp(161): NULL !=
> phSrch", or something similar. In release mode your halt will be less glamorous,
> since two lines later we have the statement "*phSrch = static_cast<hrecls_t>(0);"

If it was an exception you could get it in both debug and release modes.
You would not get a crash.
The user would not loose their work.

> Now, one can certainly write defensively and test for phSrch. I used to do a lot
> more of that than I do now. Aside from the tedium, there are very good reasons
> why this is a "bad thing". Meyers goes through this in detail. For me there are
> three reasons. First it's more effort.

Nothing is free, stability costs development time and effort.

> Second you tend not to catch errors (by
> which I mean human coding errors, not exceptions) anywhere near as you might -
> your development time increases.

An exception will still catch human coding errors.
Their development time will not change. Yours wont either, you just code "throw.." instead of "assert(.."

> Third, the locality of an error is lost, making
> tracking down a non-functioning application _far_ harder.

Why? Assuming exceptions have access to __FILE__ and __LINE__ (or their D equivalent) then you get just as much from them as an assert. This is the change I think we _need_.

If __FILE__ and __LINE__ are only available in debug mode (which seems likely) an exception is still better than an assert as you can place any text you want in one. I know, this is what you're asking to be added to asserts, to me that suggests you want to use an exception instead.

> I promise you that over
> the last few years when I've got less defensive, and more "aggresive", my coding
> time has dropped enormously, and application robustness has increased
> significantly.

I cannot confirm or deny that. ;)

Regan.

-- 
Using M2, Opera's revolutionary e-mail client: http://www.opera.com/m2/
July 15, 2004
> So what's wrong with this then?
>
> #    Int sqrt(Int x)
> #    {
> #        if (x < 0) throw new IntException("sqrt(x) not defined for x <
0");
> #        //...
> #    }

I interpret assertions as a subtyping mechanism. E.g. the expression

    x >= 0

is an implicit construction of the type "natural", on a conceptual level. Its not as safe as compile time checking but useful nonetheless.

It seems appropriate to use an assertion here. Defensive programming still has its place and probably beyond input validation for critical systems; no experience there though. :-)

I don't know though, if it is possible to catch an assertion violation as an exception. That appears to be useful to me. Then if an assertion violation is caught then the assertion would not be turned off in the release build. But since assertions have no labels in D, it wouldn't be possible to catch a particular assertion violation, e.g. as in

    sqrt(Int x): Int
        require
            natural: x >= x.Zero

Just a thought...


July 15, 2004
> Perhaps the above rule when it refers to 'input' is referring to 'end user' input?

That what it refers to. Its not input from some function that is part of your program/system -- contracts works to make them correct, its input from some human or from outside the system where no correctness can be assumed -- you can't debug a human into allways inputting a correct e-mail address. :-) You can't ever assume "my users will input a correct e-mail address."

So, the rule is

- "defensive" for user-module messages (forms, files, etc.)
- "offensive" for inter-module messages

My guess is that a contract syntax motivates setting up traps against coding errors more than using exceptions do. Not that exceptions don't have their place. Its also nice to read a specification with concise and precise contracts.

I can also recommend Object-Oriented Software Construction, its a great book; and also looking at EiffelSoft code for examples of contracts. In fact, some weeks ago I stumbled upon this link which may be a good introduction to contracts

http://www.eiffel.com/developers/presentations/


July 15, 2004
"Bent Rasmussen" <exo@bent-rasmussen.info> escribió en el mensaje
news:cd6nm7$2ddq$1@digitaldaemon.com
| I interpret assertions as a subtyping mechanism. E.g. the expression
|
|     x >= 0
|
| is an implicit construction of the type "natural", on a conceptual level.
| Its not as safe as compile time checking but useful nonetheless.
|

read below

| It seems appropriate to use an assertion here. Defensive programming still
| has its place and probably beyond input validation for critical systems;
no
| experience there though. :-)
|
| I don't know though, if it is possible to catch an assertion violation as
an
| exception. That appears to be useful to me. Then if an assertion violation
| is caught then the assertion would not be turned off in the release build.
| But since assertions have no labels in D, it wouldn't be possible to catch
a
| particular assertion violation, e.g. as in
|
|     sqrt(Int x): Int
|         require
|             natural: x >= x.Zero
|
| Just a thought...

It'd be better (and easier for the programmers) if D had ranges. Then you would declare your own natural type with that condition. And it'd be compile time.

-----------------------
Carlos Santander Bernal


July 15, 2004
> It'd be better (and easier for the programmers) if D had ranges. Then you would declare your own natural type with that condition. And it'd be
compile
> time.

It would indeed. That's one of the things I liked when I saw some Pascal code awhile ago. It probably wouldn't extend well beyond primitive types though.