[Mono-list] Design by Contract
Robert Shade
rshade@dvsconsulting.com
Fri, 31 Dec 2004 18:17:21 -0500
This is a really neat design idea. I originally thought you were
talking about something like what unit testing is for; but, after some
research, I see that this is much more.
Just to add my two cents, I think I would discourage the attribute idea.
For one, it would mean that your compiled application would have to link
with your DBC library. This would mean that the user would have to deal
with a bunch of #if's so that those attributes would not be compiled in
production code. Otherwise, the user would be forced to distribute your
library with their product.
Secondly, attributes would force the checking to be done by a modified
compiler. This would seriously limit your target audience to mono
folks. Love mono, but the masses are using Microsoft's compiler.
Finally, I would imagine that adding this (admittedly wonderful)
complexity into the compiler is not something the maintainers would
like. It would also increase the learning curve of someone wanting to
join up on the project.
I would recommend using an external processor similar to some of the
tools available for aspect oriented programming. You'd add the DBC
"hooks" by some sort of special comments or macros. The former would be
kind of nice because you'd still be able to compile it with a regular
compiler. The latter would require the user to run his or her code
through the tool before compiling. Both could then be used as
placeholders for runtime checking code to be inserted.
An external tool would also allow you to investigate the code flow in
ways that the compiler may not. For example, you could do "process"
time checking of the code to see if your "contracts" are always
true/false. (I belive the MS compiler does this for conditionals) For
things that were marked "invariant", you could follow the code flow to
see if these are modified at any point. You'd perhaps even be able to
warn the user under exactly what conditions the contracts would fail.
If you had that functionality, you would completely eliminate the need
for the user to have the (runtime) contract checking code present. The
user would already know precisely under what conditions errors would
occur and could add exception handling to take care of it.
/end of brain dump :)
rob
Stephen Touset wrote:
> I've been using C# for quite awhile now, but one feature that I wish was
> available in the language is support for Design by Contract:
> automatically-enforced preconditions and postconditions on functions, and
> invariants on classes.
>
> Having done some research into the problem, the best approach seems to be
> using attributes. Using statements inside functions works, but induces a
> lot of programmatic overhead; specifically, inheritance rules for DBC
> would need to be implemented manually. Invariants, also, would be tedious:
> code to check against the invariant would need to be added before the
> preconditions and after the postconditions of every function in the class.
> Worse still is that postconditions must be inserted above every return
> statement. This isn't too bad if you insist upon only one return statement
> per function, but for anyone with multiple returns, this becomes tedious
> quickly. And of course, all of these are clear violations of the Don't
> Repeat Yourself rule.
>
> Attributes seem to be the way to go. The pre/postconditions and invariants
> are, at the core, metadata about the functions and class. The attributes
> themselves would be able to understand their own inheritance criteria, and
> code can automatically be generated to verify the terms of the contract
> wherever needed. Unfortunately, the way attributes in C# are implemented,
> there seems to be no way to practically use them. Reflection may be
> powerful, but there doesn't appear to be a way that an attribute can
> access (or even determine) the function or class that it applies to.
>
> My initial approach was to use the CodeDom libraries to insert code into
> functions that would be dynamically based upon the applicable attributes,
> and enforce the conditions correctly. However, the inability for
> attributes to access the "calling" class all but cripples this attempt. My
> next thought was to simply have a script which would understand the
> attributes and insert the applicable statements at compile-time. However,
> the need for attribute inheritance quickly caused this approach to become
> unwieldy.
>
> Does anyone have an idea about how this could be done in a reasonable
> fashion? If so, would anyone be willing to help on the project?
>