This is an old revision of the document!
PHP RFC: Native DbC support as definition
- Version: 0.1
- Date: 2015-02-10
- Author: Yasuo Ohgaki yohgaki@ohgaki.net
- Status: Draft
- First Published at: http://wiki.php.net/rfc/dbc2
Important Note
This RFC is a part of “Native DbC support” RFC. http://wiki.php.net/rfc/dbc
There are many way to achieve DbC. This RFC proposes DbC as function/method definition.
Introduction
Design by Contract (DbC) or Contract Programming is powerful program design concept based on Contracts that
- Define precondition contract for methods/functions. i.e. Define Parameter value specifications/conditions.
- 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 development time only. Therefore, there is no performance penalty with DbC.
DbC changes the way program is designed
- With modularized design without DbC, the more code is consolidated, the better code is.
Therefore, parameter 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.
- 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 func() must have assert() for every return. - With native DbC, return value validity is checked as postcondition definition. It does not require scattered assert().
- With native DbC, invariant condition may be defined. Invariant allows programmers consolidate class state which must be TRUE for always.
e.g. $account_balance >= 0
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.
With proper use of DbC concept, it is known programs to be more robust/secure and faster. Languages design lately have native DbC support. e.g. D language. Almost all languages have some kind of DbC supports today.
Proposal
Introduce native contracts “require”( precondition ), “return”( postcondition ) definition to function/method and special “__invaliant()” method to class.
require, return behave just like assert(). (require, return accepts message. i.e. require($a > 0, '$a must be positive') )
Example without **invariant**
class Product { protected $inventory; // User is supposed to check inventory first function haveEnoughInventory($quantity) require($quantity > 0) { return (bool) ($this->inventory - $quantity) >= 0; } // Sell inventory function sell($quantity) require($quantity > 0) return($ret >= 0) // We have to think of how to specify $ret. Use block? return($ret) {assert($ret >= 0);} { $ret = $this>amount - $quantity; return $ret; } }
Example with **invariant**
class Product { protected $inventory; // Invariants must be TRUE for this class always - $inventory should not be negative function __invariant() { assert($this->inventory >= 0); } // User is supposed to check inventory first function haveEnoughInventory($quantity) require($quantity > 0) { return (bool) ($this->inventory - $quantity) >= 0; } // Sell inventory function sell($quantity) require($quantity > 0) { return $this>amount - $quantity; } }
Execution Control
Introduce “dbc” INI switch, Off by default. No additional CLI option for DbC.
A method/function is executed as follows
Development mode: dbc=On
- require() conditions
- invariant() - method() - invariant()
- return() conditions
Production mode: dbc=Off
- method()
Backward Incompatible Changes
None
- No additional keyword
- __invariant() is a reserved method name
Proposed PHP Version(s)
- PHP7
RFC Impact
To SAPIs
None
To Existing Extensions
None
To Opcache
Dmitry, could you write impact when discussion is finished?
New Constants
None
php.ini Defaults
dbc=Off for all
- hardcoded default values
- php.ini-development values
- php.ini-production values
Open Issues
- Need to discuss syntax
- How to manage votes for 2 RFCs
Unaffected PHP Functionality
This RFC does not affect any existing features
Future Scope
Documentation systems may adopt native DbC syntax for documentation purpose.
Proposed Voting Choices
Include these so readers know where you are heading and can discuss the proposed voting options.
State whether this project requires a 2/3 or 50%+1 majority (see voting)
Patches and Tests
Links to any external patches and tests go here.
If there is no patch, make it clear who will create a patch, or whether a volunteer to help with implementation is needed.
Make it clear if the patch is intended to be the final patch, or is just a prototype.
Implementation
After the project is implemented, this section should contain
- the version(s) it was merged to
- a link to the git commit(s)
- a link to the PHP manual entry for the feature
References
Rejected Features
Keep this updated with features that were discussed on the mail lists.