Andrei Alexandrescu Wrote:

> On 06/20/2010 06:18 PM, Vladimir Panteleev wrote:
> > On Mon, 21 Jun 2010 00:17:28 +0300, Walter Bright
> > <newshou...@digitalmars.com> wrote:
> >
> >> An input to a dll is user input, and should be validated (for the sake
> >> of security, and other reasons). Validating it is not debugging.
> >
> > I don't understand why you're saying this. Security checks in DLL
> > functions are pointless, for the reasons I already outlined:
> [snip]
> 
> I think the matter is simpler than that. Essentially DbC is modular 
> integrity checking. If Phobos enforce()s parameters in calls, then it 
> considers its own integrity a different matter than the integrity of the 
> application it's used with.
> 
> If Phobos used contracts to validate parameters, it would directly share 
> responsibility for the integrity of the entire application. That way, 
> users will not be sure whether the failure is a bug in Phobos or one in 
> their own code.

If a unrecoverable failure occurs within the process, does it matter where the 
error originated?

I've been thinking about this a bit and am starting to wonder about the benefit 
of distinguishing API boundary integrity checking vs. internal integrity 
checking.  First, what if a library eats its own dogfood?  If my library 
provides a public method to spawn threads and the library itself uses threads 
internally then I have two different methods of checking the integrity of my 
own library, each possibly throwing different exceptions (enforce throws 
Exception while assert throws AssertError).  At the very least, this seems like 
it could cause maintenance issues because a logic change deep within the 
library may require additional exception handling to deal with what are 
intended to be user-facing errors.

In a similar vein, if contracts are used within an API but a different mode of 
checking is used at the API boundary, when contracts are enabled in that API 
the user is faced with the bizarre issue of receiving AssertErrors from 
internal API logic errors but only Exceptions from his own logic errors for API 
boundary calls.  When you say that DbC is modular I'd presume that means it's 
encapsulated within each distinct subsystem, but it seems like this isn't true 
at all.  The alternative is to turn DbC off in the library and either live with 
undefined behavior or a hard crash if there's a bug in the library, a 
circumstance which is again forced upon the user.

Regarding DbC, I can't say that I've ever worked on a system where lives hung 
in the balance (an admittedly extreme example of where DbC is useful), but if I 
were sufficiently concerned about process integrity that I had contracts 
enabled then I don't think I would trust that a third-party library was 
bug-free and therefore didn't need its own contract checking in place.  Once 
I've accepted the cost of integrity checking I want it everywhere, not just in 
my own code.  It makes for consistent error checking behavior (I'd assume there 
is a system in place to trap DbC errors specifically) and provides full-process 
integrity checking.

I think the only boundary that really matters is the process boundary.  Any 
error within a process has the same effect regardless of whether it's in user 
code or library code--corrupted memory, segfaults, etc--so why make a 
distinction between code I wrote and code someone else wrote?  By the same 
token, if the user chooses to disable contracts then why force them upon him 
for some errors but not others?  The user is making the explicit choice to run 
his process through a meat-grinder if something unexpected happens, he's 
effectively asserting that his code is perfect, so why tell him that "no, it's 
actually not."

For me, the more difficult issue is how much integrity checking should be done. 
 For example, I created an AVL tree a while back that verified that the tree 
was still properly balanced after every API call.  This was great from a code 
verification standpoint, but the check completely violated the complexity 
guarantees and ultimately checked something that could have been proven to a 
reasonable degree of confidence through code reviews and unit testing.  Should 
checks like this be enabled automatically when DbC is turned on?  Should there 
be different levels of DbC?  In some respects I feel like there's a difference 
between in/out contracts and invariants, but even that doesn't seem completely 
right.  Thoughts?

Reply via email to