www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Why no contracts for release build?

reply Andre <andre s-e-a-p.de> writes:
Hi,
I currently think about whether or not contracts should be available
in release builds.

Assuming a small example, you have an account class with a deposit 
method, the input parameter must always be > 0.

void deposit(int amount)
in
{
   enforce(amount > 0);
}
body
{
   this.amount += amount;
}

If in release build the Contracts sections is removed, this means, I 
also need to add in addition in another place the enforce method. 
Otherwise in the productive scenario, this coding isn't secure anymore. 
This leads to code duplication.

I think Contracts are not a feature solely for unittests, they are a
fundamental part of classes/interfaces and theirfore should be available
in all builds.

What do you think?

Kind regards
André
Jun 03 2014
next sibling parent "Dicebot" <public dicebot.lv> writes:
Contracts are not supposed to be use for error checking / input 
validation. Quoting docs for enforce: "Also, do not use enforce 
inside of contracts (i.e. inside of in and out blocks and 
invariants), because they will be compiled out when compiling 
with -release. Use assert in contracts. "

Contracts are supposed to verify that there are no fundamental 
flaws in internal logic of the program which will immediately pop 
up in test / debug runs. This may imply very expensive sanity 
checks that are not welcome in release builds for performance 
reasons.

In your case you should simply move `enforce` to the function 
body and remove contract.
Jun 03 2014
prev sibling next sibling parent reply Jonathan M Davis via Digitalmars-d <digitalmars-d puremagic.com> writes:
On Tue, 03 Jun 2014 16:29:20 +0200
Andre via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Hi,
 I currently think about whether or not contracts should be available
 in release builds.

 Assuming a small example, you have an account class with a deposit
 method, the input parameter must always be > 0.

 void deposit(int amount)
 in
 {
    enforce(amount > 0);
 }
 body
 {
    this.amount += amount;
 }

 If in release build the Contracts sections is removed, this means, I
 also need to add in addition in another place the enforce method.
 Otherwise in the productive scenario, this coding isn't secure
 anymore. This leads to code duplication.

 I think Contracts are not a feature solely for unittests, they are a
 fundamental part of classes/interfaces and theirfore should be
 available in all builds.

 What do you think?

Contracts are specifically intended for validating the input and output of a function with assertions. So, they're going to go away in any build that does not have assertions enabled. Contracts are very much the wrong place to use enforce. enforce throws an Exception and does not get compiled out. It is intended for error-handling rather than for validating the correctness of your code. - Jonathan M Davis
Jun 03 2014
parent Andre <andre s-e-a-p.de> writes:
Am 03.06.2014 19:13, schrieb Jonathan M Davis via Digitalmars-d:
 On Tue, 03 Jun 2014 16:29:20 +0200
 Andre via Digitalmars-d <digitalmars-d puremagic.com> wrote:

 Hi,
 I currently think about whether or not contracts should be available
 in release builds.

 Assuming a small example, you have an account class with a deposit
 method, the input parameter must always be > 0.

 void deposit(int amount)
 in
 {
     enforce(amount > 0);
 }
 body
 {
     this.amount += amount;
 }

 If in release build the Contracts sections is removed, this means, I
 also need to add in addition in another place the enforce method.
 Otherwise in the productive scenario, this coding isn't secure
 anymore. This leads to code duplication.

 I think Contracts are not a feature solely for unittests, they are a
 fundamental part of classes/interfaces and theirfore should be
 available in all builds.

 What do you think?

Contracts are specifically intended for validating the input and output of a function with assertions. So, they're going to go away in any build that does not have assertions enabled. Contracts are very much the wrong place to use enforce. enforce throws an Exception and does not get compiled out. It is intended for error-handling rather than for validating the correctness of your code. - Jonathan M Davis

As I known that assertions are only for unittest purposes I hoped, if I use enforce, this statements will not be removed in release build and will still be executed - wrong. I see, the idea of contracts in D differs to the idea of contracts e.g. in Java (http://c4j-team.github.io/C4J/ Here contracts are used for unittest but also for the productive code in release builds. I thought about writing a Contracts library, which works similiar to C4J but I see no chance to solve this issue without AST. Kind regards André
Jun 03 2014
prev sibling next sibling parent reply "Sean Kelly" <sean invisibleduck.org> writes:
On Tuesday, 3 June 2014 at 14:29:19 UTC, Andre wrote:
 Hi,
 I currently think about whether or not contracts should be 
 available in release builds.

 I think Contracts are not a feature solely for unittests, they 
 are a fundamental part of classes/interfaces and theirfore 
 should be available in all builds.

I think the problem is that "release" is a misnomer, because the presence of contracts has nothing to do with whether you're deploying a test or release build. For all the talk of how we should be profiling our code to find the trouble spots instead of prematurely optimizing, the release flag, by virtue of its name, exists as a giant red button we're all expected to press for "performance" or whatever before deploying our software for use in the first instance where safety actually matters. As for the idea that contracts simply aid in finding logic errors during testing... for testing to have any validity the test must be performed on the same build that will be released to the public. And the idea that testing will ever find all the problems that might occur in the field is laughable. In short, pretend "release" says something like "unchecked" and think hard before actually setting it in real code.
Jun 03 2014
parent reply Andre <andre s-e-a-p.de> writes:
Am 03.06.2014 23:43, schrieb Sean Kelly:
 I think the problem is that "release" is a misnomer, because the
 presence of contracts has nothing to do with whether you're
 deploying a test or release build.  For all the talk of how we
 should be profiling our code to find the trouble spots instead of
 prematurely optimizing, the release flag, by virtue of its name,
 exists as a giant red button we're all expected to press for
 "performance" or whatever before deploying our software for use
 in the first instance where safety actually matters.

 As for the idea that contracts simply aid in finding logic errors
 during testing... for testing to have any validity the test must
 be performed on the same build that will be released to the
 public.  And the idea that testing will ever find all the
 problems that might occur in the field is laughable.

 In short, pretend "release" says something like "unchecked" and
 think hard before actually setting it in real code.

Yes you are right. For my product "released" to customer, as business application developer, I am more focused on safety and less on performance. If in any case a customer is doing s.th which can be caught by contracts then it should be caught. Therefore the release switch is really dangerous. What I really want is a switch "stable", which contains all safety relevant features like Contracts/Asserts and so on. But this build should exclude debug information etc. I currently wonder what is included by adding no switch to DMD?
 dmd main

Kind regards André
Jun 04 2014
parent Andre <andre s-e-a-p.de> writes:
Am 04.06.2014 16:23, schrieb Martin Krejcirik:
 On Wednesday, 4 June 2014 at 13:48:04 UTC, Andre wrote:
 I currently wonder what is included by adding no switch to DMD?

default (no switch) = asserts, contracts, boundscheck=all -debug = include code marked with debug keyword -unittest = include unittests -g = include debug info -release = do not include asserts, contracs, boundscheck=safeonly, some switch optimizations -boundscheck option can override -release option for turning on or off all bounds checking (there is deprecated -noboundscheck in 2.065 or earlier)

thanks a lot for these informations, exactly what I need. Kind regards André
Jun 04 2014
prev sibling next sibling parent "Martin Krejcirik" <mk-junk i-line.cz> writes:
 What I really want is a switch "stable", which contains all 
 safety relevant features like Contracts/Asserts and so on. But

Just compile _without_ -release -debug -g -unittest options.
Jun 04 2014
prev sibling next sibling parent "Martin Krejcirik" <mk-junk i-line.cz> writes:
On Wednesday, 4 June 2014 at 13:48:04 UTC, Andre wrote:
 I currently wonder what is included by adding no switch to DMD?

default (no switch) = asserts, contracts, boundscheck=all -debug = include code marked with debug keyword -unittest = include unittests -g = include debug info -release = do not include asserts, contracs, boundscheck=safeonly, some switch optimizations -boundscheck option can override -release option for turning on or off all bounds checking (there is deprecated -noboundscheck in 2.065 or earlier)
Jun 04 2014
prev sibling parent "Kagamin" <spam here.lot> writes:
On Tuesday, 3 June 2014 at 14:29:19 UTC, Andre wrote:
 Hi,
 I currently think about whether or not contracts should be 
 available
 in release builds.

Use release build only if you proved the code is 100% correct. It's hardly useful in realistic scenarios. See the recently reported buffer overflow bug in druntime which would be otherwise caught twice by asserts: https://issues.dlang.org/show_bug.cgi?id=12848
Jun 04 2014