rfc:dbc
Differences
This shows you the differences between two versions of the page.
Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
rfc:dbc [2015/02/05 13:15] – francois | rfc:dbc [2018/03/01 23:19] (current) – Typo "Under Discussion" carusogabriel | ||
---|---|---|---|
Line 1: | Line 1: | ||
- | ====== PHP RFC: Native | + | ====== PHP RFC: Implementing |
- | * Version: 0.1 | + | * Version: 0.4 |
- | * Date: 2015-02-04 | + | * Date: 2015-02-09 |
- | * Author: | + | * Author: François Laupretre < |
- | * Status: | + | * Status: |
* First Published at: http:// | * First Published at: http:// | ||
+ | |||
+ | This RFC is waiting for the decisions that will be made about scalar | ||
+ | type hinting. The reason is that the design and syntax | ||
+ | decisions that will be made about scalar type hinting heavily impact the | ||
+ | contents of this RFC. Proposal is subject to be changed according scalar type | ||
+ | hinting implementation. | ||
+ | |||
+ | ===== Preamble ===== | ||
+ | |||
+ | This RFC is part of " | ||
+ | |||
+ | * https:// | ||
+ | |||
+ | There is alternative implementation proposal by " | ||
+ | |||
+ | * https:// | ||
+ | |||
+ | |||
+ | The original idea of introducing DbC in PHP comes from Yasuo Ohgaki | ||
+ | < | ||
+ | |||
+ | Then, I offered to write an RFC where I propose to include DbC constraints in | ||
+ | doc comments. This is the present document. | ||
+ | |||
+ | While we agree on the concept, Yasuo is preferring a D-like syntax, which he's proposing in [[https:// | ||
+ | IMO, adopting the D syntax would be fine if we designed the language from scratch, but is not the | ||
+ | best way to include the concept in PHP (more details below). | ||
===== Introduction ===== | ===== Introduction ===== | ||
- | For more than 10 years (roughly | + | For more than 10 years (since PHP 5 was released), the PHP core community has |
seen a lot of discussions about strict vs loose typing, type hinting and | seen a lot of discussions about strict vs loose typing, type hinting and | ||
- | related features. | + | related features. Through these discussions, |
+ | them as early as possible. Strictifying types is an approach but, unfortunately, | ||
+ | so well with PHP as a loose-typed language. | ||
- | To summarize years of flame wars, developers argue that strict typing and type hinting | + | This RFC proposes an alternative approach, already present in several |
- | will make their source code cleaner and easier to debug. On the other side, these | + | languages, named 'Design by Contract' |
- | features must remain optional and compatible with 'basic' | + | |
- | And the debate generally dies in endless discussions about the concept | + | |
- | ' | + | |
- | With this RFC, we propose an alternative approach, already present in several | + | Here is the definition of a contract, according |
- | languages, named ' | + | |
- | We won't detail | + | The idea of a contract is simple - it's just an expression that must evaluate |
- | the reference section below. Just note that DbC is a way to define constraints on | + | to true. If it does not, the contract is broken, and by definition, the program |
- | function arguments, return values, and class properties. The key | + | has a bug in it. Contracts form part of the specification for a program, moving |
- | point is that DbC checks are performed during | + | it from the documentation |
- | phase only. In production phase, DbC checks are turned off. | + | |
+ | | ||
- | So, the most important points are : | + | For more info on the DbC theory, use the links in the ' |
- | * DbC constraints can be extremely detailed as performance | + | An important point in DbC theory |
- | | + | A global switch allows to turn DbC checks |
- | * The DbC and 'Test Driven Development' | + | |
- | ===== Example ===== | + | So, what we need to retain : |
- | First, an example of a function defining input, inline | + | * DbC constraints can be highly sophisticated as we don't care about performance. |
+ | * As they are checked at runtime, DbC constraints can check types AND values. | ||
+ | * DbC checks must not handle checks that must always run, even in production. Validating user input, for instance, must remain out of DbC constraints. | ||
+ | * DbC and 'Test Driven Development' | ||
+ | |||
+ | ===== Examples ===== | ||
+ | |||
+ | First, an example of a function defining input and output constraints | ||
+ | (' | ||
<code php> | <code php> | ||
+ | // | ||
/** | /** | ||
* Compute area of a triangle | * Compute area of a triangle | ||
Line 43: | Line 77: | ||
* This function computes the area of a triangle using Heron' | * This function computes the area of a triangle using Heron' | ||
* | * | ||
- | * @param | + | * @param |
- | * @param float([0:) $b Length of 2nd side | + | * @requires |
- | * @param float([0:) $c Length of 3rd side | + | * @param number |
- | * @assert.in | + | * @requires |
- | * @assert.in | + | * @param number |
- | * @assert.in | + | * @requires ($c >= 0) |
+ | * @requires | ||
+ | * @requires | ||
+ | * @requires | ||
* | * | ||
- | * @return | + | * @return |
- | * @assert.out | + | * @ensures |
*/ | */ | ||
Line 57: | Line 94: | ||
{ | { | ||
$halfPerimeter = ($a + $b + $c) / 2; | $halfPerimeter = ($a + $b + $c) / 2; | ||
- | |||
- | // @assert ($halfPerimeter >= 0) | ||
return sqrt($halfPerimeter | return sqrt($halfPerimeter | ||
Line 67: | Line 102: | ||
</ | </ | ||
- | Notes: | + | Then : |
- | * '$>' means ' | + | <code php> |
- | * 'float([0:)' means 'a floating point number in the range from 0 (included) to infinite', | + | $area=triangleArea(4,2,3); |
- | * I added an ' | + | -> OK |
- | You may also note that this code is fully backwards compatible. | + | $area=triangleArea(' |
+ | -> PHP Fatal error: triangleArea: | ||
- | Another example with a clone of str_replace() : | + | $area=triangleArea(10, |
+ | -> PHP Fatal error: triangleArea: | ||
+ | </ | ||
+ | |||
+ | Another example with a PHP clone of str_replace() : | ||
<code php> | <code php> | ||
+ | // | ||
/** | /** | ||
* Replace all occurrences of the search string with the replacement string | * Replace all occurrences of the search string with the replacement string | ||
* | * | ||
- | * ... | + | * This function returns a string or an array with all occurrences of search |
+ | * in subject replaced with the given replace value. | ||
* | * | ||
- | * @param array(string)|string | + | * @param |
- | * @param array(string)|string | + | * @param |
- | * @param array(string)|string | + | * @param |
- | * @param.out int([0:) $count The number of replacements performed | + | * @param.out int $count The number of replacements performed |
- | * @return array(string)|string | + | * @ensures ($count >= 0) |
- | * @assert.out | + | * @return |
+ | * | ||
+ | * Ensure that returned value is the same type as input subject : | ||
+ | * @ensures | ||
*/ | */ | ||
Line 96: | Line 141: | ||
</ | </ | ||
- | Note that, while it would be supported, | + | Note that we didn't provide any constraint on $count input, as this |
parameter is used for output only. | parameter is used for output only. | ||
- | ===== Proposal ===== | + | Finally, we rewrite the first example as a class : |
- | DbC typically defines three basic constraint types : | + | <code php> |
+ | <?php | ||
+ | /** | ||
+ | * @invariant ($this-> | ||
+ | * @invariant ($this-> | ||
+ | * @invariant ($this-> | ||
+ | */ | ||
- | * pre-conditions: checked when entering a function/method. Generally check that | + | class triangle |
- | passed arguments are valid. | + | { |
+ | /*-- Properties */ | ||
- | * post-conditions: | + | /** @var number Side lengths */ |
- | return type/value and the returned type/value of arguments passed by reference. | + | |
- | * class inveriants: Constraints | + | private $a,$b,$c; |
- | dynamic | + | |
+ | // | ||
+ | /** | ||
+ | * @param number $a Length of 1st side | ||
+ | * @param number $b Length of 2nd side | ||
+ | * @param number $c Length of 3rd side | ||
+ | * | ||
+ | * No need to repeat constraints | ||
+ | */ | ||
+ | |||
+ | public function __construct($a,$b,$c) | ||
+ | { | ||
+ | $this-> | ||
+ | $this-> | ||
+ | $this-> | ||
+ | } | ||
+ | |||
+ | // | ||
+ | /** | ||
+ | * Compute area of a triangle | ||
+ | * | ||
+ | * This function computes the area of a triangle using Heron' | ||
+ | * | ||
+ | * @return number The triangle area | ||
+ | * @ensures ($> >= 0) | ||
+ | */ | ||
+ | |||
+ | public function area() | ||
+ | { | ||
+ | $halfPerimeter = ($this-> | ||
+ | |||
+ | return sqrt($halfPerimeter | ||
+ | * ($halfPerimeter - $this-> | ||
+ | * ($halfPerimeter - $this-> | ||
+ | * ($halfPerimeter - $this-> | ||
+ | } | ||
+ | </ | ||
+ | |||
+ | and check DbC constraints | ||
+ | |||
+ | <code php> | ||
+ | $t= new triangle(4, | ||
+ | -> OK | ||
+ | |||
+ | $t=new triangle(' | ||
+ | -> PHP Fatal error: triangle:: | ||
+ | |||
+ | $area=triangleArea(10,2,3); | ||
+ | -> PHP Fatal error: triangle: DbC invariant violation (($this-> | ||
+ | </ | ||
+ | |||
+ | ===== Proposal ===== | ||
+ | |||
+ | DbC defines three constraint types : | ||
+ | |||
+ | * pre-conditions: | ||
+ | * post-conditions: | ||
+ | * class invariants: Constraints on class properties. | ||
+ | |||
+ | In this document, we propose a mechanism to implement these constraints in the PHP world. | ||
==== Syntax ==== | ==== Syntax ==== | ||
- | We propose to include the DbC directives | + | We propose to include the DbC directives in phpdoc blocks. Here are the |
- | constraints will be included | + | main reasons, that make it, in my opinion, a better choice than every other syntaxes |
- | inline assertions will be included in plain comments. | + | proposed so far : |
- | The benefits are : | + | * it allows to keep the source code executable on previous PHP interpreters. |
+ | * Phpdoc comments, while not perfect, have always played the role of annotations in PHP. ' | ||
+ | * DbC can use a great part of the already-written phpdoc informations (@param and @return types, @throws information too). So, unchanged code could already benefit of DbC. | ||
- | - As directives | + | Note: Some people on the mailing list are religiously opposed to including information |
- | fully compatible with every past and future PHP interpreter (NO BC break). | + | in phpdoc blocks, despite |
+ | for this purpose. The reason is that the parser cannot handle that. I agree, but | ||
+ | that's not a task for the parser, that's a task for an external tool. We just need | ||
+ | the hooks. | ||
+ | |||
+ | ==== Side effects ==== | ||
- | - phpdoc blocks already contain arguments and return types. | + | As DbC, by nature, can be turned on and off, DbC checks must not modify |
- | information, unchanged code will automatically benefit of DbC. | + | anything in the environment. |
- | - phpDocumentor | + | While enforcing this is partially possible in theory, this implementation |
- | to the phpdoc syntax and will easily generate a more detailed documentation. | + | the developer' |
- | There is no BC break here as, even using the current version of phpDocumentor, | + | |
- | DbC-specific keywords are ignored and the documentation is correctly generated. | + | |
- | - PHP IDEs already use phpdoc blocks. So, it will be easier for them to | + | ==== DbC types ==== |
- | exploit | + | |
- | ==== Pre-conditions ==== | + | DbC types are an extension and formalization of the pre-existing phpdoc |
+ | argument/ | ||
+ | |||
+ | DbC types are not present in original DbC syntax (like Eiffel or D implementation), | ||
+ | This is a PHP-specific addition to enhance simplicity and readability. DbC types can be | ||
+ | seen as built-in conditions. | ||
+ | |||
+ | Here are the main benefits of defining a set of DbC types : | ||
+ | |||
+ | * PHP is_xxx() functions are not as intuitive as they may seem, as they are based on zval types (an equivalent of strict type checks). They are not appropriate for people who just want to accept a limited set of type juggling (accepting a numeric string from a DB, for instance). Unfortunately, | ||
+ | * As it was already said, tons of source code already contains argument return/ | ||
+ | * Readability is a key point too: just compare a type like ' | ||
+ | * DbC types allow static analysis, which is practically impossible with conditions. | ||
+ | * A lot of other analyzis/ | ||
+ | |||
+ | DbC types are used to check : | ||
+ | |||
+ | * arguments sent to a function | ||
+ | * arguments passed by ref returned by a function | ||
+ | * the function' | ||
+ | * the type of class properties | ||
+ | |||
+ | === Syntax | ||
- | === Argument | + | DbC types don't contain whitespaces. |
- | == Syntax == | + | Here is a pseudo-grammar of DbC types : |
< | < | ||
- | line = " | + | dbc-type |
compound-type = type, { " | compound-type = type, { " | ||
- | type = array-type | + | type = " |
- | | numeric-type | + | | " |
- | | string-type | + | | " |
+ | | " | ||
+ | | "string" | ||
+ | | " | ||
+ | | array-type | ||
+ | | " | ||
| object-type | | object-type | ||
| resource-type | | resource-type | ||
- | | scalar-type | + | | " |
- | | simple-type | + | | "scalar" |
+ | | " | ||
+ | | " | ||
+ | | " | ||
- | simple-type = "null" | "scalar" | + | array-type = "array" |
+ | | "array(", compound-type, | ||
- | array-type = "array" | + | object-type = "object" |
+ | | "object(", class-name, " | ||
- | < | + | resource-type = " |
+ | | " | ||
</ | </ | ||
- | == DbC types vs zval types == | + | === DbC types vs zval types === |
+ | DbC types follow specific rules to match PHP zvals. These rules are less permissive than | ||
+ | PHP API type juggling and previously-proposed scalar ' | ||
+ | these types try to be a more intuitive compromise between both. | ||
+ | Strict typing is sometimes required. That's why DbC types also include a set of | ||
+ | strict types. | ||
+ | |||
+ | Note that the benefit of DbC, here, is that we can match depending on zval values, as | ||
+ | we don't care about performance. | ||
+ | |||
+ | ^ ^ Zval type ^^^^^^^^ | ||
+ | ^ DbC type ^ IS_NULL ^ IS_LONG ^ IS_DOUBLE ^ IS_BOOL(1) ^ IS_ARRAY ^ IS_OBJECT ^ IS_STRING ^ IS_RESOURCE ^ | ||
+ | ^ integer | ||
+ | ^ integer! | ||
+ | ^ number | ||
+ | ^ float! | ||
+ | ^ string | ||
+ | ^ string! | ||
+ | ^ array | No | ||
+ | ^ callable | ||
+ | ^ object | ||
+ | ^ resource | ||
+ | ^ scalar | ||
+ | ^ null | ||
+ | ^ mixed | Yes | Yes | Yes | Yes | ||
+ | ^ boolean | ||
+ | ^ boolean! | ||
+ | |||
+ | * (1) IS_TRUE/ | ||
+ | * (2) only if decimal part is null\\ | ||
+ | * (3) only if is_numeric(string) returns true and decimal part is null\\ | ||
+ | * (4) only if is_numeric(string) returns true\\ | ||
+ | * (5) only if is_callable(arg, | ||
+ | * (6) only if class defines a %%__%%toString() method\\ | ||
+ | * (7) O is false, 1 is true. Other values don't match (to be discussed) | ||
+ | |||
+ | === DbC types === | ||
+ | |||
+ | == integer == | ||
+ | |||
+ | An integer value, positive or negative. | ||
+ | |||
+ | Note: This type is NOT equivalent to is_int($arg), | ||
+ | accepts the IS_LONG zval type. | ||
+ | |||
+ | Synonyms: ' | ||
+ | |||
+ | == integer! == | ||
+ | |||
+ | A zval-type-based integer value, positive or negative. | ||
+ | |||
+ | Note: This type is equivalent to is_int($arg). | ||
+ | |||
+ | Synonyms: ' | ||
+ | |||
+ | == number == | ||
+ | |||
+ | Any value that returns true through is_numeric(). | ||
+ | |||
+ | Equivalent to ' | ||
+ | |||
+ | Synonyms: ' | ||
+ | |||
+ | == float! == | ||
+ | |||
+ | A zval-type-based float value. | ||
+ | |||
+ | Note: This type is equivalent to is_float($arg). | ||
+ | |||
+ | == string == | ||
+ | |||
+ | An entity that can be represented by a string. Numeric values are accepted as strings, | ||
+ | as well as objects whose class defines a __toString() method. | ||
+ | |||
+ | == string! == | ||
+ | |||
+ | Accepts IS_STRING zvals and objects whose class defines a __toString() method. | ||
+ | |||
+ | == array == | ||
+ | |||
+ | A PHP array. | ||
+ | |||
+ | Complements: | ||
+ | This defines the acceptable types of the array values. This definition can be nested. | ||
+ | |||
+ | Examples: | ||
+ | |||
+ | < | ||
+ | * @param array $arr ... | ||
+ | * @param string|array(string) $... # Matches a string or an array of strings | ||
+ | * @param array(array(string|integer)) $... # A 2-dimension array containing strings and int only | ||
+ | </ | ||
+ | |||
+ | == callable == | ||
+ | |||
+ | A string, object or array returning true through ' | ||
+ | |||
+ | Please consult the [[http:// | ||
+ | |||
+ | == object == | ||
+ | |||
+ | An instance object. | ||
+ | |||
+ | Synonyms: ' | ||
+ | |||
+ | Complements: | ||
+ | the object is of this class or has this class as one of its parents (equivalent to is_a()). | ||
+ | |||
+ | Examples: | ||
+ | |||
+ | < | ||
+ | * @param object $arg | ||
+ | * @param object(Exception) $e | ||
+ | * @param object(MongoClient)|null $conn | ||
+ | </ | ||
+ | |||
+ | == resource == | ||
+ | |||
+ | A PHP resource. | ||
+ | |||
+ | Synonyms: ' | ||
+ | |||
+ | Complements: | ||
+ | string provided when defining a resource via zend_register_list_destructors_ex(). As | ||
+ | we don't support whitespaces in argument types, whitespaces present in the original resource | ||
+ | type must be replaced with an underscore character (' | ||
+ | |||
+ | The easiest way to display the string corresponding to a resource type is to display | ||
+ | an existing resource using var_dump(). | ||
+ | |||
+ | Examples: | ||
+ | |||
+ | < | ||
+ | * @param resource(OpenSSL_key) $... | ||
+ | * @param resource(pgsl_link) $... | ||
+ | </ | ||
+ | |||
+ | == scalar == | ||
+ | |||
+ | Shortcut for ' | ||
+ | |||
+ | Equivalent to ' | ||
+ | |||
+ | == null == | ||
+ | |||
+ | This corresponds exactly to the IS_NULL zval type. | ||
+ | |||
+ | Equivalent to ' | ||
+ | |||
+ | Note that a number with a 0 value does not match ' | ||
+ | |||
+ | Synonyms: ' | ||
+ | |||
+ | Examples: | ||
+ | |||
+ | < | ||
+ | * @param string|null $... | ||
+ | * @param resource(pgsl_link) $... | ||
+ | * @return null | ||
+ | </ | ||
+ | |||
+ | == mixed == | ||
+ | |||
+ | Accepts any zval type & value (catch-all). | ||
+ | |||
+ | Synonyms: ' | ||
+ | |||
+ | == boolean == | ||
+ | |||
+ | A boolean value (true or false). | ||
+ | |||
+ | In PHP 7, IS_BOOL is replaced with IS_TRUE and IS_FALSE. | ||
+ | |||
+ | Equivalent to ' | ||
+ | |||
+ | Synonyms: ' | ||
+ | |||
+ | == boolean! == | ||
+ | |||
+ | Accepts IS_BOOL zvals only (IS_TRUE/ | ||
+ | |||
+ | Synonyms: ' | ||
+ | |||
+ | ==== Pre-conditions ==== | ||
+ | |||
+ | These conditions are checked at the beginning of a function or method, after | ||
+ | arguments have been received, but before starting executing the function body. | ||
+ | |||
+ | Pre-conditions are expressed in two forms : argument types, and explicit assertions. | ||
+ | Argument types are used first and explicit assertions supplement argument types | ||
+ | with additional conditions (like conditions between arguments). | ||
+ | |||
+ | Argument types are checked before explicit assertions, meaning that | ||
+ | explicit assertions can assume correct types. | ||
=== Optional arguments === | === Optional arguments === | ||
- | When an optional argument is not set by the caller, its input/output types are not | + | When an optional argument is not set by the caller, its input (and possibly |
checked. This allows to set a default value which does not match the argument' | checked. This allows to set a default value which does not match the argument' | ||
declared input type. | declared input type. | ||
Line 188: | Line 528: | ||
=== Input assertions === | === Input assertions === | ||
+ | |||
+ | These conditions supplement argument types for more complex conditions. They | ||
+ | are executed in the function scope before executing the function' | ||
+ | |||
+ | Syntax : | ||
< | < | ||
- | line = "*", " | + | /** |
+ | * ... | ||
+ | * @requires <php-condition> | ||
+ | * ... | ||
</ | </ | ||
+ | |||
+ | where < | ||
+ | |||
+ | These assertions can appear anywhere in the phpdoc block. They are executed in | ||
+ | the same order as they appear in the doc block. | ||
=== Inheritance === | === Inheritance === | ||
+ | |||
+ | The DbC theory, in accordance with the [[http:// | ||
+ | states that a subclass can override pre-conditions only if it loosens them. | ||
+ | |||
+ | The logic we implement is in the spirit of the way PHP handles class constructors/ | ||
+ | |||
+ | * Function pre-conditions are checked. If the function does not define any pre-condition, | ||
+ | * A special pre-condition is introduced. The ' | ||
+ | * The special ' | ||
==== Post-conditions ==== | ==== Post-conditions ==== | ||
+ | |||
+ | Post-conditions are checked at function' | ||
+ | executed in the function scope. | ||
+ | |||
+ | They are generally used to check the returned type and value, and arguments | ||
+ | returned by ref. | ||
+ | |||
+ | When a function exits because an exception was thrown, | ||
+ | the function' | ||
+ | checked. | ||
=== Returned type === | === Returned type === | ||
- | line = "*", "@return", | + | Syntax: |
+ | |||
+ | < | ||
+ | * @return | ||
+ | </ | ||
+ | |||
+ | The syntax of < | ||
+ | |||
+ | Examples: | ||
+ | |||
+ | < | ||
+ | * @return resource|null | ||
+ | |||
+ | // For a factory: | ||
+ | |||
+ | * @return object(MyClass) | ||
+ | </ | ||
=== Argument return type === | === Argument return type === | ||
Line 205: | Line 593: | ||
This is the return type & value of the arguments passed by reference. | This is the return type & value of the arguments passed by reference. | ||
- | @param.out < | + | Syntax: |
+ | |||
+ | < | ||
+ | * @param.out < | ||
+ | </code> | ||
+ | |||
+ | Note that an argument passed by reference can have a ' | ||
+ | its input type and/or a ' | ||
+ | In the str_replace() example above, we don't define an input type for $count | ||
+ | because it is undefined. | ||
=== Output assertions === | === Output assertions === | ||
- | @assert.out | + | Syntax: |
+ | |||
+ | < | ||
+ | * @ensures < | ||
+ | </ | ||
+ | |||
+ | As with input assertions, < | ||
+ | in the function scope. The only addition is that the ' | ||
+ | replaced with the function' | ||
+ | |||
+ | As with pre-conditions, | ||
=== Inheritance === | === Inheritance === | ||
- | ==== Class-wide constraints ==== | + | The inheritance rules are the same as the ones for pre-conditions. |
- | === Static constraints === | + | Unlike the Eiffel or D implementations, |
+ | only if the child requires it using a ' | ||
- | == Syntax | + | ==== Class constraints ==== |
- | @assert.static | + | These constraints are called ' |
+ | that properties must always verify a set of ' | ||
- | == Execution == | + | Class constraints take two forms : property types and class assertions. |
- | == Scope == | + | Each property type is defined in its own docblock, just before the definition of its property and |
+ | class assertions are defined in the class docblock (the block just before the class | ||
+ | definition). | ||
- | == Inheritance == | + | Note that we don't define a specific constraint type for static properties. They |
+ | will be checked using the same syntax as dynamic properties. | ||
- | === Instance constraints | + | === Property types === |
- | @assert.instance | + | Syntax: |
- | == Execution == | + | < |
+ | /** @var < | ||
+ | </ | ||
- | == Scope == | + | where < |
- | == Inheritance | + | === Class assertions === |
- | ==== Inline assertions ==== | + | These are defined in class docblocks. |
- | === Syntax | + | Syntax: |
< | < | ||
- | // @assert | + | * @invariant |
</ | </ | ||
- | === Scope === | + | < |
+ | |||
+ | == Execution == | ||
+ | |||
+ | Property types are checked before class assertions. | ||
+ | |||
+ | This set of constraints is checked : | ||
+ | |||
+ | * after the execution of the constructor, | ||
+ | * before destroying the object, even if no destructor exists. | ||
+ | * before and after execution of a public dynamic method. | ||
+ | |||
+ | Class constraints are executed before pre-conditions and/or after post-conditions. | ||
+ | |||
+ | == Scope == | ||
+ | |||
+ | These constraints are executed in the class scope (' | ||
+ | |||
+ | == Inheritance == | ||
+ | |||
+ | The same mechanism is used as with pre/ | ||
+ | checked only if explicitely called using ' | ||
+ | |||
+ | ==== Nested calls ==== | ||
+ | |||
+ | When a function or method is called from a DbC condition, its constraints are | ||
+ | not checked. | ||
- | ==== Exception thrown | + | ==== Constraint violations |
- | ContractException | + | When a DbC condition fails, an E_ERROR is raised, containing the file and line number of the failing condition. |
===== Backward Incompatible Changes ===== | ===== Backward Incompatible Changes ===== | ||
Line 257: | Line 697: | ||
===== Proposed PHP Version(s) ===== | ===== Proposed PHP Version(s) ===== | ||
- | PHP 7 | + | As the plan is to implement this in a separate extension, it should be availbale for PHP 5 ans PHP 7. |
===== RFC Impact ===== | ===== RFC Impact ===== | ||
Line 266: | Line 706: | ||
==== To Existing Extensions ==== | ==== To Existing Extensions ==== | ||
- | Compatibility with Xdebug ? < | + | None |
==== To Opcache ==== | ==== To Opcache ==== | ||
- | < | + | None |
==== New Constants ==== | ==== New Constants ==== | ||
Line 278: | Line 718: | ||
==== php.ini Defaults ==== | ==== php.ini Defaults ==== | ||
- | dbc.enforce : boolean | + | A boolean |
* php.ini-development value: true | * php.ini-development value: true | ||
Line 287: | Line 727: | ||
===== Unaffected PHP Functionality ===== | ===== Unaffected PHP Functionality ===== | ||
- | When DbC is off, there' | + | When DbC is turned |
===== Future Scope ===== | ===== Future Scope ===== | ||
- | | + | |
- | | + | - Add exception checks (using |
+ | - Extend type syntax (define a syntax for ranges, enums, etc) | ||
+ | | ||
+ | - Extend DbC to interfaces and traits | ||
===== Proposed Voting Choices ===== | ===== Proposed Voting Choices ===== | ||
- | Required majority ? | + | Required majority ? To be defined. |
===== Patches and Tests ===== | ===== Patches and Tests ===== | ||
- | Dmitry Stogov volunteered | + | This should be implemented in a Zend extension, not in the core. This would be a perfect addition |
- | + | ||
- | ===== Implementation ===== | + | |
- | + | ||
- | < | + | |
===== References ===== | ===== References ===== | ||
Line 315: | Line 753: | ||
[[http:// | [[http:// | ||
- | ===== Rejected Features ===== | + | [[https:// |
- | + |
rfc/dbc.1423142106.txt.gz · Last modified: 2017/09/22 13:28 (external edit)