rfc:dbc2

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
rfc:dbc2 [2015/02/10 11:49] dmitryrfc:dbc2 [2018/03/01 23:19] (current) – Typo "Under Discussion" carusogabriel
Line 3: Line 3:
   * Date: 2015-02-10   * Date: 2015-02-10
   * Author: Yasuo Ohgaki <yohgaki@ohgaki.net>, Dmitry Stogov <dmitry@zend.com>, Joe Watkins <pthreads@pthreads.org>   * Author: Yasuo Ohgaki <yohgaki@ohgaki.net>, Dmitry Stogov <dmitry@zend.com>, Joe Watkins <pthreads@pthreads.org>
-  * Status: Draft+  * Status: Under Discussion
   * First Published at: http://wiki.php.net/rfc/dbc2   * First Published at: http://wiki.php.net/rfc/dbc2
  
-===== Important Note====+===== Important Note ====
 + 
 +This RFC is part of "Design by Contract Introduction" RFC 
 +  * https://wiki.php.net/rfc/introduce_design_by_contract
  
 This RFC is an alternative approach to "Native DbC support" RFC. This RFC is an alternative approach to "Native DbC support" RFC.
-http://wiki.php.net/rfc/dbc+  * http://wiki.php.net/rfc/dbc
  
-This RFC proposes PHP syntax extension for contracts declaration.+Contracts can be defined without modification to the language, however, the D documentation calls the resulting implementation "clumsy and inconsistent".
  
-===== Introduction =====+Other advantages of a native implementation, also taken from the D manual:
  
-Design by Contract (DbC) or Contract Programming is powerful program design concept based on **Contracts** that+  a consistent look and feel for the contracts 
 +  tool support 
 +  compiler optimizations 
 +  easier management and enforcement of contracts 
 +  * handling of contract inheritance
  
-  - Define **precondition** contract for methods/functions. i.e. Define Parameter value specifications/conditions. +All of the above applies to PHP.
-  - Define **postcondition** contract for methods/functions. i.e. Define Return value specifications/conditions. +
-  - Define **invariant** contract for methods/functions. i.e. Define class state must be true always.+
  
-These contracts are evaluated at run-time, usually durunf development and testing only. It should be possible to switch off contracts validation for production.+===== Introduction =====
  
-  * http://dlang.org/contracts.html +The D manual contains the following succinct definition of contracts:
-  * http://en.wikipedia.org/wiki/Design_by_contract+
  
-====DbC Changes the Way Program is Designed/Developed/Tested====+> The idea of a contract is simple - it's just an expression that must evaluate to true. If it does not, the contract is broken, and by definition, the program has a bug in it. Contracts form part of the specification for a program, moving it from the documentation to the code itself. And as every programmer knows, documentation tends to be incomplete, out of date, wrong, or non-existent. Moving the contracts into the code makes them verifiable against the program.
  
-==CalleR and CalleE responsibility and validation:== +This should be easily comprehensibleit further validates the argument that the best implementation is a native oneso that the programmer really can "move the specification from the documentation to the code".
-  * With modularized design without DbC, the more code is consolidated, the better code is. \\ Thereforeparameter validity is checked deep into the code. Parameter validity check is __calleE__ responsibility. +
-  * With DbC, parameter checks are done as **precondition**. Passing valid parameter to a function is __calleR__ responsibility.+
  
-==Exit value validation:== +===== Proposal =====
-  * Without native DbC, return value validity cannot be checked without scattered assert() for every place function is used. \\ i.e. Programmers has to write "$ret func(); assert($ret > 0);" everywhere func() is used or code must have assert() for each func(). +
-  * With native DbC, return value validity is checked as **postcondition**. It does not require scattered assert(). +
- +
-==Class state validation:== +
-  * With native DbC, **invariant** condition may be defined. **Invariant** allows programmers consolidate class state which must be TRUE for always. \\ e.g. $account_balance >+
- +
-**precondition** check can be done with assert(), but other feature requires native DbC. +
- +
-DbC reverses the responsibility caller and callee, ensures parameters, return value and class state validity without performance penalty. This helps PHP to achieve more efficient development by contract errors, faster execution for production. +
- +
-DbC encourages users to control inputs/output/class state precisely. This helps application efficient/precise development. Languages designed lately have native DbC support. e.g. D language. Almost all languages have some kind of DbC supports today.  +
- +
-====Readability of Code / Testing Code==== +
- +
-Since contracts are declared together with function/method definition, it's much easier to find function/method spec compared to conditions written in UnitTests. It also enables contract check for running applications operated by humans.+
  
-DbC is __NOT__ a complement of UnitTest, but it provide additional way of testing programs. Programs should be tested by UnitTest with and without DbC. With this procedure, UnitTest condition coverage is improved and/or simplified.+Support for the following contracts will be introduced:
  
 +  * precondition       "require"( **precondition-expression** [,'Error msg'])
 +  * postcondition      "return"( **return_value**, **postcondition-expression** [,'Error msg'])
 +  * invariant          "require"( **invariant-expression** [,'Error msg'])
  
-====General Concern of Design by Contract====+===== Pre and Post Condition =====
  
-Some may concern that lack of checks under production environment. However, all inputs to programs should validate input parameter validity right after input parameters are passed to program+These contracts should be defined after the function declaration, but before the function body.
  
-This is basic principle of secure programs. Users should not DbC everywhere. User should have proper defense in depth as security measure. Security standard like "ISO 27000" or security guideline like "[[http://cwe.mitre.org/top25/#Mitigations|SANS TOP 25 Monster Mitigations]]" suggests to have proper output controls, as well as input controls. This applies with or without DbC. **DbC encourages proper input/output controls compare to program design without DbC.** +Multiple precondition and postcondition contracts may be used. The expressions are just a regular PHP expressions. They are evaluated in the function scope, and can access arguments and other scope variables, and return value (via a reserved name). Pre and post-conditions can't be defined for abstract methods and methods defined in interfaces.
- +
- +
-===== Proposal ===== +
- +
-We are going to introduce native PHP syntax for contracts declaration for functions and methods +
- +
-  * "require"( **precondition-expression** [,'Error msg']) +
-  * "return"( **return_variable**, **postcondition-expression** [,'Error msg']) +
- +
-These contracts should be defined after the function declaration, but before the function body. It's possible to have few **requre** and **return** constraints. The expressions are just a regular PHP expressions. They should validate input arguments (accessed through their names) or return value (accessed through special name $retand shouldn't make any side effects. Pre and post-conditions can't be defined for abstract methods and methods defined in interfaces.+
  
 <code> <code>
Line 91: Line 71:
 </code> </code>
  
-Invariant contracts for objects may be declared using **requre** inside a slass declaration statementThere are possible to have few invaiant constraints. They may access object or static properties through **$this** and **self** variables. Invariant contracts may be defined for classes, abstract classes and traits, but not for interfaces.+===== Invariant ===== 
 + 
 +Invariant contracts are declared using **require** inside class bodyMultiple invariant contracts may be used. They may access object or static properties through **$this** and **self**. Invariant contracts may be used for classes, abstract classes and traits, but not for interfaces.
  
 <code> <code>
Line 103: Line 85:
  }  }
  
- requre($this->sum > 0, "overflow detected");+ require($this->sum > 0, "overflow detected");
 } }
 </code> </code>
Line 123: Line 105:
 </code> </code>
  
-Invariant contracts are not validated when public object properties are changed not from the class scope.+**Invariant contracts are not evaluated when object properties are changed from outside the class scope.**
  
 ====Contracts Inheritance Rules==== ====Contracts Inheritance Rules====
-**TODO**+ 
 +Contracts are constant, this has the following implications: 
 + 
 +  a derived class must satisfy invariant contracts of it's parent 
 +  a derived class overriding a method must satisfy the pre and post condition contracts of it's prototype. 
 + 
 +Thus, given the following code: 
 + 
 +<code> 
 +class Child { 
 +    require ($this->age < 18); 
 +     
 +    public function someMethod($input)  
 +        require(somethingAbout($input)) { 
 +        /... *
 +    } 
 + 
 +    /* ... */ 
 +
 + 
 +class Monster extends Child { 
 +    require ($this->odour == OBNOXIOUS); 
 + 
 +    public function someMethod($input)  
 +        require(somethingElseAbout($input)) { 
 +        /* ... */ 
 +    } 
 + 
 +    /* ... */ 
 +
 +</code> 
 + 
 +//Monster// must not break **any** contract in //Child//.
  
 ====Execution Control==== ====Execution Control====
Line 136: Line 150:
   * dbc=zero_cost - don't generate code for contracts. This may be set only in php.ini and can't be changed through ini_set().   * dbc=zero_cost - don't generate code for contracts. This may be set only in php.ini and can't be changed through ini_set().
  
-  The default value if "off".+  The default value is "off".
  
-===Contracts Evaluation Order===+===Contracts Execution Order===
  
 If "dbc" is set to "on", the order of contracts validation is the following: If "dbc" is set to "on", the order of contracts validation is the following:
  
-  - all require() contracts (preconditions) defined for this methods (in defined order+  - all require() contracts (precondition) defined for this function (and prototype where applicable
-  - all require() contracts (invariantsdefined for this class (in defined oredrer)+  - all require() contracts (invariant) for this class and parents
   - method body   - method body
-  - all require() contracts (invariantsdefined for this class (in defined oredrer) +  - all require() contracts (invariant) for this class and parents 
-  - all return() contracts (postconditions) defined for this methods (in defined order)+  - all return() contracts (postcondition) defined for this function (and prototype where applicable)
  
 **Invariant and Special Methods** **Invariant and Special Methods**
Line 152: Line 166:
   * <nowiki>__constructs()/__wakeup()/__set_state()</nowiki> will NOT execute invariant before method body.   * <nowiki>__constructs()/__wakeup()/__set_state()</nowiki> will NOT execute invariant before method body.
   * <nowiki>__destruct()/__sleep()</nowiki> will NOT execute invariant after method body.   * <nowiki>__destruct()/__sleep()</nowiki> will NOT execute invariant after method body.
- 
-**Class Inheritance** 
- 
-  * When parent class methods are called, DbC conditions are executed 
-  * Special methods execution exception is the same 
  
 **Static Call** **Static Call**
  
-  * Only pre/post contracts are executed +  * Only pre and post conditions are executed.
- +
-**Interface** +
- +
-  * Cannot define DbC contracts.+
  
 ===== Backward Incompatible Changes ===== ===== Backward Incompatible Changes =====
Line 236: Line 241:
 ===== Rejected Features ===== ===== Rejected Features =====
 Keep this updated with features that were discussed on the mail lists. Keep this updated with features that were discussed on the mail lists.
- 
rfc/dbc2.1423568951.txt.gz · Last modified: 2017/09/22 13:28 (external edit)