# Design by Contract

- Thread: https://externals.io/message/81898
- Original archive: https://news-web.php.net/php.internals/81898
- Started by Dmitry Stogov on 2015-02-05T11:14:04+00:00
- Messages: 203
- Page 1 of 9: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/81898.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #81898 — Dmitry Stogov — 2015-02-05T11:14:04+00:00

URL: https://externals.io/message/81898#81898

Hi Yasuo,

Following our conversation, I tried to imagine how DbC should look like in
PHP from user perspective. Finally, I was influenced by the semantic
proposed in D, and syntax proposed for Java. So, these are my initial
thoughts:

For php it may look like the following:

function foo()
    requre(<input-assert-expression>)
    ensure(<output-assert-expression>)
{
  ...
}

It would require only one new reserved word "ensure".

The assert expressions may be checked or not depending on ini directive.
It should be also possible to prevent code generation for assertions (zero
cost asserts). It was already implemented for
https://wiki.php.net/rfc/expectations

For inherited methods, only the self <input-assert-expression> should be
checked, and all parent <output-asser-expression>. This is borrowed from D
but not necessary to be repeated exactly.

I think we shouldn't introduce "invariant" constraints for classes now. May
be later.

Implementation is going to generate code for input constraint after all
RECV opcodes and before code for function body, and code for output
constraint before RETURN opcode (may be reusing implementation of
"finally").

See:
http://dlang.org/contracts.html
http://jan.newmarch.name/java/contracts/paper-long.html

Thanks. Dmitry.

---

## #81900 — Patrick Schaaf — 2015-02-05T11:38:17+00:00

URL: https://externals.io/message/81898#81900 · In reply to: #81898

Am 05.02.2015 12:14 schrieb "Dmitry Stogov" <dmitry@zend.com>:
>
> For php it may look like the following:
>
> function foo()
>     require(<input-assert-expression>)
>     ensure(<output-assert-expression>)
> {
>   ...
> }
>
> It would require only one new reserved word "ensure".

How would one access the function return value in the
output-assert-expression?

And what about side effects in these expressions? Could they be suppressed
/ made into errors somehow?

best regards
  Patrick

---

## #81901 — Dmitry Stogov — 2015-02-05T11:46:16+00:00

URL: https://externals.io/message/81898#81901 · In reply to: #81900

> Am 05.02.2015 12:14 schrieb "Dmitry Stogov" <dmitry@zend.com>:
> > […]
>
> How would one access the function return value in the
> output-assert-expression?
>

good point. we may use a reserved name. e.g. $result.or $return_value

> And what about side effects in these expressions? Could they be suppressed
> / made into errors somehow?
>
I afraid, we won't be able catch possible side effects of assert
expressions.
For now, we may just relay on user, in the same way as with `assert()` now.

Thanks. Dmitry.


> best regards
>   Patrick

---

## #81902 — Robert Stoll — 2015-02-05T11:47:40+00:00

URL: https://externals.io/message/81898#81902 · In reply to: #81898

Hi Dimitry

> -----Ursprüngliche Nachricht-----
> Von: Dmitry Stogov [mailto:dmitry@zend.com]
> Gesendet: Donnerstag, 5. Februar 2015 12:14
> An: Yasuo Ohgaki; PHP Internals
> Betreff: [PHP-DEV] Design by Contract
> 
> Hi Yasuo,
> 
> Following our conversation, I tried to imagine how DbC should look like in PHP from user perspective. Finally, I was
> influenced by the semantic proposed in D, and syntax proposed for Java. So, these are my initial
> thoughts:
> 
> For php it may look like the following:
> 
> function foo()
>     requre(<input-assert-expression>)
>     ensure(<output-assert-expression>)
> {
>   ...
> }
> 
> It would require only one new reserved word "ensure".
> 
> The assert expressions may be checked or not depending on ini directive.
> It should be also possible to prevent code generation for assertions (zero cost asserts). It was already implemented for
> https://wiki.php.net/rfc/expectations
> 
> For inherited methods, only the self <input-assert-expression> should be checked, and all parent <output-asser-
> expression>. This is borrowed from D but not necessary to be repeated exactly.
> 
> I think we shouldn't introduce "invariant" constraints for classes now. May be later.
> 
> Implementation is going to generate code for input constraint after all RECV opcodes and before code for function body,
> and code for output constraint before RETURN opcode (may be reusing implementation of "finally").
> 
> See:
> http://dlang.org/contracts.html
> http://jan.newmarch.name/java/contracts/paper-long.html
> 
> Thanks. Dmitry.

I am not sure if this new syntactic sugar really improves readability. What is the difference between the above and having something like?

function foo($x, $y){
  if(validateFoo($x, $y)){}
  
  //do something
  $result = 'some value';

  if(postValidateFoo($result){
    return $ result;
  }
}

Actually putting everything in one function seems even worse from a single responsibility point of view. But I suppose I am missing something essential here.

Cheers,
Robert

---

## #81904 — Dmitry Stogov — 2015-02-05T11:56:32+00:00

URL: https://externals.io/message/81898#81904 · In reply to: #81902

Hi Robert,

This is about "declarative" vs "imperative" programming.
Also constraints may be enabled for debugging and completely disabled for
production.
I'm not the inventor of this approach, I just started to think about it
myself :)

You opinion makes sense as well. PHP doesn't have to support all the
possible features.

Thanks. Dmitry.




> Hi Dimitry
>
> > […]
> in PHP from user perspective. Finally, I was
> > […]
> So, these are my initial
> > […]
> (zero cost asserts). It was already implemented for
> > […]
> checked, and all parent <output-asser-
> > […]
> exactly.
> > […]
> May be later.
> > […]
> RECV opcodes and before code for function body,
> > […]
> implementation of "finally").
> > […]
>
> I am not sure if this new syntactic sugar really improves readability.
> What is the difference between the above and having something like?
>
> function foo($x, $y){
>   if(validateFoo($x, $y)){}
>
>   //do something
>   $result = 'some value';
>
>   if(postValidateFoo($result){
>     return $ result;
>   }
> }
>
> Actually putting everything in one function seems even worse from a single
> responsibility point of view. But I suppose I am missing something
> essential here.
>
> Cheers,
> Robert

---

## #81906 — Patrick Schaaf — 2015-02-05T12:13:45+00:00

URL: https://externals.io/message/81898#81906 · In reply to: #81898

On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
>
> function foo()
>     requre(<input-assert-expression>)
>     ensure(<output-assert-expression>)
> {
>   ...
> }
> 
> It would require only one new reserved word "ensure".

Regarding syntax.... This could be another place where the irrationally-
dreaded declare would make sense:

function foo() {
    declare(pre) {
      if (whatever...) return false;
      // arbitrary PHP code
    }
    declare(post=$resultvar) {
      if ($resultvar == XXX) return true;
      return false;
    }
}

This way, no new reserved words are needed at all, and the programmer can give 
a name to the "variable that holds the result" locally to avoid clashes with 
anything else in the function.

I'm a bit undecided whether returning true/false there to give the verdict, 
would be the best way. Maybe better would be another use for declare, without 
a block, to declare that the pre/postcondition failed - giving a nice place to 
put a suitable message, too. And again without introducing any extra keywords:

function foo() {
    declare(post=$resultvar) {
        if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
    }
}
    
best regards
  Patrick

---

## #81911 — Alexander Lisachenko — 2015-02-05T12:24:38+00:00

URL: https://externals.io/message/81898#81911 · In reply to: #81906

Hello, internals!

From my point of view, contracts should not affect execution of source code
in production env, or can be enabled partially. I have implemented DbC
paradigm on top of the AOP layer, so each contract can be defined via
annotation and looks pretty nice, for example :

use PhpDeal\Annotation as Contract;

/**
 * Simple trade account class
 * @Contract\Invariant("$this->balance > 0")
 */
class Account implements AccountContract
{

    /**
     * Current balance
     *
     * @var float
     */
    protected $balance = 0.0;

    /**
     * Deposits fixed amount of money to the account
     *
     * @param float $amount
     *
     * @Contract\Verify("$amount>0 && is_numeric($amount)")
     * @Contract\Ensure("$this->balance == $__old->balance+$amount")
     */
    public function deposit($amount)
    {
        $this->balance += $amount;
    }

    /**
     * Returns current balance
     *
     * @Contract\Ensure("$__result == $this->balance")
     * @return float
     */
    public function getBalance()
    {
        return $this->balance;
    }
}

All contracts (verify|ensure) are enforced only when DbC is enabled and
doesn't have an impact on execution for production mode. Moreover, all
annotations are parsed only once, decorators are generated too, so overhead
is minimal even for debug mode. Engine takes care to insert appropriate
before/around checks via an aspect
https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.php

Here is a simple snippet of pointcut definition and advice body:

    /**
     * Verifies pre-condition contract for the method
     *
     * @param MethodInvocation $invocation
     * @Before("@annotation(PhpDeal\Annotation\Verify)")
     *
     * @throws ContractViolation
     */
    public function preConditionContract(MethodInvocation $invocation)
    {
        $object = $invocation->getThis();
        $args   = $this->getMethodArguments($invocation);
        $scope  = $invocation->getMethod()->getDeclaringClass()->name;

        foreach ($invocation->getMethod()->getAnnotations() as $annotation) {
            if (!$annotation instanceof Contract\Verify) {
                continue;
            }

            if (!$this->isContractSatisfied($object, $scope, $args,
$annotation)) {
                throw new ContractViolation($invocation, $annotation->value);
            };
        }
    }





2015-02-05 15:13 GMT+03:00 Patrick Schaaf <php@bof.de>:

> On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
> > […]
>
> Regarding syntax.... This could be another place where the irrationally-
> dreaded declare would make sense:
>
> function foo() {
>     declare(pre) {
>       if (whatever...) return false;
>       // arbitrary PHP code
>     }
>     declare(post=$resultvar) {
>       if ($resultvar == XXX) return true;
>       return false;
>     }
> }
>
> This way, no new reserved words are needed at all, and the programmer can
> give
> a name to the "variable that holds the result" locally to avoid clashes
> with
> anything else in the function.
>
> I'm a bit undecided whether returning true/false there to give the verdict,
> would be the best way. Maybe better would be another use for declare,
> without
> a block, to declare that the pre/postcondition failed - giving a nice
> place to
> put a suitable message, too. And again without introducing any extra
> keywords:
>
> function foo() {
>     declare(post=$resultvar) {
>         if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
>     }
> }
>
> best regards
>   Patrick

---

## #81912 — Dmitry Stogov — 2015-02-05T12:25:49+00:00

URL: https://externals.io/message/81898#81912 · In reply to: #81906

this way we would able to use in constraints any statements.
The require/ensure syntax was limited to expressions (to limit users in
making side effects).

May be we may reuse delare() a bit differently.

function foo() {
    declare(pre=<input-constraint>)
    declare(post=<output-constraint>)
{

}

However. I like require/ensure more.

Thanks. Dmitry.



> On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
> > […]
>
> Regarding syntax.... This could be another place where the irrationally-
> dreaded declare would make sense:
>
> function foo() {
>     declare(pre) {
>       if (whatever...) return false;
>       // arbitrary PHP code
>     }
>     declare(post=$resultvar) {
>       if ($resultvar == XXX) return true;
>       return false;
>     }
> }
>
> This way, no new reserved words are needed at all, and the programmer can
> give
> a name to the "variable that holds the result" locally to avoid clashes
> with
> anything else in the function.
>
> I'm a bit undecided whether returning true/false there to give the verdict,
> would be the best way. Maybe better would be another use for declare,
> without
> a block, to declare that the pre/postcondition failed - giving a nice
> place to
> put a suitable message, too. And again without introducing any extra
> keywords:
>
> function foo() {
>     declare(post=$resultvar) {
>         if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
>     }
> }
>
> best regards
>   Patrick

---

## #81913 — Alexander Lisachenko — 2015-02-05T12:27:23+00:00

URL: https://externals.io/message/81898#81913 · In reply to: #81911

So, is it possible to use annotations for defining such metadata on
engine-level? This will be a good way to do this and to define custom
handlers via AST hooks, that can be able to patch method definition node
with concrete opcodes.

2015-02-05 15:24 GMT+03:00 Alexander Lisachenko <lisachenko.it@gmail.com>:

> Hello, internals!
>
> From my point of view, contracts should not affect execution of source
> code in production env, or can be enabled partially. I have implemented DbC
> paradigm on top of the AOP layer, so each contract can be defined via
> annotation and looks pretty nice, for example :
>
> use PhpDeal\Annotation as Contract;
>
> /**
>  * Simple trade account class
>  * @Contract\Invariant("$this->balance > 0")
>  */
> class Account implements AccountContract
> {
>
>     /**
>      * Current balance
>      *
>      * @var float
>      */
>     protected $balance = 0.0;
>
>     /**
>      * Deposits fixed amount of money to the account
>      *
>      * @param float $amount
>      *
>      * @Contract\Verify("$amount>0 && is_numeric($amount)")
>      * @Contract\Ensure("$this->balance == $__old->balance+$amount")
>      */
>     public function deposit($amount)
>     {
>         $this->balance += $amount;
>     }
>
>     /**
>      * Returns current balance
>      *
>      * @Contract\Ensure("$__result == $this->balance")
>      * @return float
>      */
>     public function getBalance()
>     {
>         return $this->balance;
>     }
> }
>
> All contracts (verify|ensure) are enforced only when DbC is enabled and
> doesn't have an impact on execution for production mode. Moreover, all
> annotations are parsed only once, decorators are generated too, so overhead
> is minimal even for debug mode. Engine takes care to insert appropriate
> before/around checks via an aspect
> https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.php
>
> Here is a simple snippet of pointcut definition and advice body:
>
>     /**
>      * Verifies pre-condition contract for the method
>      *
>      * @param MethodInvocation $invocation
>      * @Before("@annotation(PhpDeal\Annotation\Verify)")
>      *
>      * @throws ContractViolation
>      */
>     public function preConditionContract(MethodInvocation $invocation)
>     {
>         $object = $invocation->getThis();
>         $args   = $this->getMethodArguments($invocation);
>         $scope  = $invocation->getMethod()->getDeclaringClass()->name;
>
>         foreach ($invocation->getMethod()->getAnnotations() as $annotation) {
>             if (!$annotation instanceof Contract\Verify) {
>                 continue;
>             }
>
>             if (!$this->isContractSatisfied($object, $scope, $args, $annotation)) {
>                 throw new ContractViolation($invocation, $annotation->value);
>             };
>         }
>     }
>
>
>
>
>
> 2015-02-05 15:13 GMT+03:00 Patrick Schaaf <php@bof.de>:
>
> > […]

---

## #81914 — Dmitry Stogov — 2015-02-05T12:32:22+00:00

URL: https://externals.io/message/81898#81914 · In reply to: #81911

Hi Alexander,

Defining contracts through doc-comments is also possible, but this way is
not native.
On the other hand, if you already have this implemented, we may just reuse
it.

Thanks. Dmitry.

On Thu, Feb 5, 2015 at 3:24 PM, Alexander Lisachenko <
lisachenko.it@gmail.com> wrote:

> Hello, internals!
>
> From my point of view, contracts should not affect execution of source
> code in production env, or can be enabled partially. I have implemented DbC
> paradigm on top of the AOP layer, so each contract can be defined via
> annotation and looks pretty nice, for example :
>
> use PhpDeal\Annotation as Contract;
>
> /**
>  * Simple trade account class
>  * @Contract\Invariant("$this->balance > 0")
>  */
> class Account implements AccountContract
> {
>
>     /**
>      * Current balance
>      *
>      * @var float
>      */
>     protected $balance = 0.0;
>
>     /**
>      * Deposits fixed amount of money to the account
>      *
>      * @param float $amount
>      *
>      * @Contract\Verify("$amount>0 && is_numeric($amount)")
>      * @Contract\Ensure("$this->balance == $__old->balance+$amount")
>      */
>     public function deposit($amount)
>     {
>         $this->balance += $amount;
>     }
>
>     /**
>      * Returns current balance
>      *
>      * @Contract\Ensure("$__result == $this->balance")
>      * @return float
>      */
>     public function getBalance()
>     {
>         return $this->balance;
>     }
> }
>
> All contracts (verify|ensure) are enforced only when DbC is enabled and
> doesn't have an impact on execution for production mode. Moreover, all
> annotations are parsed only once, decorators are generated too, so overhead
> is minimal even for debug mode. Engine takes care to insert appropriate
> before/around checks via an aspect
> https://github.com/lisachenko/php-deal/blob/master/src/PhpDeal/Aspect/ContractCheckerAspect.php
>
> Here is a simple snippet of pointcut definition and advice body:
>
>     /**
>      * Verifies pre-condition contract for the method
>      *
>      * @param MethodInvocation $invocation
>      * @Before("@annotation(PhpDeal\Annotation\Verify)")
>      *
>      * @throws ContractViolation
>      */
>     public function preConditionContract(MethodInvocation $invocation)
>     {
>         $object = $invocation->getThis();
>         $args   = $this->getMethodArguments($invocation);
>         $scope  = $invocation->getMethod()->getDeclaringClass()->name;
>
>         foreach ($invocation->getMethod()->getAnnotations() as $annotation) {
>             if (!$annotation instanceof Contract\Verify) {
>                 continue;
>             }
>
>             if (!$this->isContractSatisfied($object, $scope, $args, $annotation)) {
>                 throw new ContractViolation($invocation, $annotation->value);
>             };
>         }
>     }
>
>
>
>
>
> 2015-02-05 15:13 GMT+03:00 Patrick Schaaf <php@bof.de>:
>
> > […]

---

## #81918 — Dmitry Stogov — 2015-02-05T12:35:18+00:00

URL: https://externals.io/message/81898#81918 · In reply to: #81913

For now, we don't have any mechanism for annotations or attributes except
for doc-comments.

Thanks. Dmitry.

On Thu, Feb 5, 2015 at 3:27 PM, Alexander Lisachenko <
lisachenko.it@gmail.com> wrote:

> So, is it possible to use annotations for defining such metadata on
> engine-level? This will be a good way to do this and to define custom
> handlers via AST hooks, that can be able to patch method definition node
> with concrete opcodes.
>
> 2015-02-05 15:24 GMT+03:00 Alexander Lisachenko <lisachenko.it@gmail.com>:
>
> > […]

---

## #81919 — Alexander Lisachenko — 2015-02-05T12:42:59+00:00

URL: https://externals.io/message/81898#81919 · In reply to: #81914

2015-02-05 15:32 GMT+03:00 Dmitry Stogov <dmitry@zend.com>:

> Hi Alexander,
>
> Defining contracts through doc-comments is also possible, but this way is
> not native.
> On the other hand, if you already have this implemented, we may just reuse
> it.
>


Thanks, Dmitry! This would be a really nice feature on engine-level.
Ideally, for PHP7-8, I would like to see a hook system from compile-level
to userland, to define a language extension. This feature is highly
required for custom DSLs and much more. DbC technique can be also
implemented as parse-time weaver. E.g. we define a parser-extension:

register_parser_extension(ContractExtension::class);

this class will receive an AST of PHP file and check interesting nodes.
This node can be annotation or something else:

[Contract::Invariant => $this->value > 0]
class Test {
    public $value = 100;
    public function foo($newValue) {
        $this->value = $newValue;
    }
}

and parser extension change the compiled source code by inserting this
check into methods:

[Contract::Invariant => $this->value > 0]
class Test {
    public $value = 100;
    public function foo($newValue) {
        $this->value = $newValue;
        assert($this->value > 0); // Inserted by parser extension (via
opcodes)
    }
}

Is it possible to do this?

---

## #81921 — Dmitry Stogov — 2015-02-05T13:07:21+00:00

URL: https://externals.io/message/81898#81921 · In reply to: #81919

At this moment, I don't have any plans related to implementation of
hook-able compiler.
However the first step was already done, introducing "zend_ast_process"
callback.
In general it's should be possible to provide PHP API to manipulate with
AST and write compiler extensions in PHP.
Looks promising.. :)
Anyway, If you are interested - start working on it.

Thanks. Dmitry.



On Thu, Feb 5, 2015 at 3:42 PM, Alexander Lisachenko <
lisachenko.it@gmail.com> wrote:

>
> 2015-02-05 15:32 GMT+03:00 Dmitry Stogov <dmitry@zend.com>:
>
> > […]
>
>
> Thanks, Dmitry! This would be a really nice feature on engine-level.
> Ideally, for PHP7-8, I would like to see a hook system from compile-level
> to userland, to define a language extension. This feature is highly
> required for custom DSLs and much more. DbC technique can be also
> implemented as parse-time weaver. E.g. we define a parser-extension:
>
> register_parser_extension(ContractExtension::class);
>
> this class will receive an AST of PHP file and check interesting nodes.
> This node can be annotation or something else:
>
> [Contract::Invariant => $this->value > 0]
> class Test {
>     public $value = 100;
>     public function foo($newValue) {
>         $this->value = $newValue;
>     }
> }
>
> and parser extension change the compiled source code by inserting this
> check into methods:
>
> [Contract::Invariant => $this->value > 0]
> class Test {
>     public $value = 100;
>     public function foo($newValue) {
>         $this->value = $newValue;
>         assert($this->value > 0); // Inserted by parser extension (via
> opcodes)
>     }
> }
>
> Is it possible to do this?

---

## #81922 — francois@tekwire.net — 2015-02-05T13:19:55+00:00

URL: https://externals.io/message/81898#81922 · In reply to: #81898

Hi Dmitry,

> De : Dmitry Stogov [mailto:dmitry@zend.com]
>
> Following our conversation, I tried to imagine how DbC should look like in
> PHP from user perspective. Finally, I was influenced by the semantic
> proposed in D, and syntax proposed for Java. So, these are my initial
> thoughts:

Please have a look at https://wiki.php.net/rfc/dbc, just the beginning, up to 'Pre-conditions'. It contains 2 examples. This is not D syntax, while functionally similar,  because I want to preserve BC and provide built-in checks on phpdoc declared types.

Cheers

François

---

## #81923 — Alexander Lisachenko — 2015-02-05T13:34:31+00:00

URL: https://externals.io/message/81898#81923 · In reply to: #81921

2015-02-05 16:07 GMT+03:00 Dmitry Stogov <dmitry@zend.com>:

> In general it's should be possible to provide PHP API to manipulate with
> AST and write compiler extensions in PHP.
> Looks promising.. :)
> Anyway, If you are interested - start working on it.



Actually, it's almost done by Nikita Popov: https://github.com/nikic/php-ast.
Missing part is to put this extension into PHP core, create an interface
for hooks and then give PHP hooks a control during parsing of source code.

So maybe just make a vote to include this API into core? This will give a
lot of food for thoughts and implementations of AOP, DbC, SQL-like native
syntax and much more. From PHP Core developers it will be only the
implementation, all other things can be easily extended by userland
developers.

---

## #81925 — Dmitry Stogov — 2015-02-05T13:41:02+00:00

URL: https://externals.io/message/81898#81925 · In reply to: #81922

Yeah, this may work.
The only problem, that it looks not native and defines additional language
for constraints.
I don't talk it's wrong. Both approaches may make sense, but of course, we
have to select one.

Thanks. Dmitry.

On Thu, Feb 5, 2015 at 4:19 PM, François Laupretre <francois@tekwire.net>
wrote:

> Hi Dmitry,
>
> > […]
> in
> > […]
>
> Please have a look at https://wiki.php.net/rfc/dbc, just the beginning,
> up to 'Pre-conditions'. It contains 2 examples. This is not D syntax, while
> functionally similar,  because I want to preserve BC and provide built-in
> checks on phpdoc declared types.
>
> Cheers
>
> François

---

## #81926 — Dmitry Stogov — 2015-02-05T13:48:42+00:00

URL: https://externals.io/message/81898#81926 · In reply to: #81923

php-ast is not almost the same, but it may be extended.

Thanks. Dmitry.

On Thu, Feb 5, 2015 at 4:34 PM, Alexander Lisachenko <
lisachenko.it@gmail.com> wrote:

>
> 2015-02-05 16:07 GMT+03:00 Dmitry Stogov <dmitry@zend.com>:
>
> > […]
>
>
>
> Actually, it's almost done by Nikita Popov:
> https://github.com/nikic/php-ast. Missing part is to put this extension
> into PHP core, create an interface for hooks and then give PHP hooks a
> control during parsing of source code.
>
> So maybe just make a vote to include this API into core? This will give a
> lot of food for thoughts and implementations of AOP, DbC, SQL-like native
> syntax and much more. From PHP Core developers it will be only the
> implementation, all other things can be easily extended by userland
> developers.

---

## #81927 — francois@tekwire.net — 2015-02-05T13:53:49+00:00

URL: https://externals.io/message/81898#81927 · In reply to: #81925

De : Dmitry Stogov [mailto:dmitry@zend.com] 

> Yeah, this may work.
> The only problem, that it looks not native and defines additional language for constraints.
> I don't talk it's wrong. Both approaches may make sense, but of course, we have to select one.

Yes, it makes phpdoc more tied to the engine but is it a problem ?

I think BC is essential here. If people need to write PHP7-specific code, we'll loose them.

And remember : we already have tons of code with documented argument/return types ready for DbC checks.

François

---

## #81931 — Ivan Enderlin @ Hoa — 2015-02-05T14:25:05+00:00

URL: https://externals.io/message/81898#81931 · In reply to: #81898

Hi Internal :-),

I just would like to point out some stuff.


tl;dr: Contracts can be used to validate code (Design-by-Contract) or 
generate test data to validate code (Contract-based Testing). There are 
plenty of contract languages in the wild, each one addresses a specific 
problem (object, structured type, temporal logic, scenario etc.). If we 
try to develop a contract language, **IT WILL FAIL**, I guarantee it. 
The solution is to give tools to developers to ease the use of 
contracts, for example with Aspect Oriented Programming.


There is a whole research PhD thesis about Contract-based Testing in 
PHP, which includes Design-by-Contract, automatic generation of complex 
test data and automatic generation of test suites: 
https://dl.dropboxusercontent.com/u/26317193/PhdThesis.pdf. 
Unfortunately, the thesis is in French but research articles are in 
English. You can found them here 
(http://hoa-project.net/En/Literature.html#Research):
   * Praspel: A Specification Language for Contract-Driven Testing in 
PHP (article: http://hoa-project.net/En/Literature/Research/Ictss11.pdf, 
keynote: http://keynote.hoa-project.net/Ictss11/EDGB11.pdf),
   * Grammar-Based Testing using Realistic Domains in PHP (article: 
http://hoa-project.net/En/Literature/Research/Amost12.pdf, keynote: 
http://keynote.hoa-project.net/Amost12/EDGB12.pdf),
   * A Constraint Solver for PHP Arrays (article: 
http://hoa-project.net/En/Literature/Research/Cstva13.pdf, keynote: 
http://keynote.hoa-project.net/Cstva13/EGB13.pdf).

Concepts behind contracts are twofold:
   1. Design-by-Contract (DbC), validate code at compile time or at 
runtime (in the case of PHP, it will be at runtime),
   2. Contract-based Testing (CbT), generate test data based on 
contracts. Preconditions are used to generate inputs, and postconditions 
validate outputs. Invariants must hold before and after the execution of 
the SUT (System Under Test, here methods and functions).

So there are two goals with contracts. We can only address validation 
(DbC) or both (DbC and CbT).

 From my own experience and study in this field (I am a PhD in the test 
domain), I suggest you to NOT introduce DbC and CbT in PHP. Why? Because 
the language used to express contracts (even if we use PHP) will be too 
much poor or too much inappropriate for test data validation or test 
data generation (resp. DbC or CbT).

The articles listed above, in addition to the PhD thesis, present 
Praspel, a specification language for PHP, based on contracts. Praspel 
is used to validate and generate (test) data and test suites. This 
language is inspired from JML (Java Modeling Language) and ACSL (ANSI/C 
Specification Language) while addressing PHP features (weakly type for 
instance). But there is a lot more languages in the wild.
Inventing another language will lead to a fail at a particular time, 
believe me. Each contract language has a specificity: Handling 
structured data, handling events, handling scenario (see Dwyer patterns 
for temporal linear logic) etc. We CANNOT address all these needs.

However, there is a hope :-). DbC and CbT can be easily implemented with 
an Aspect Oriented Programming (AOP) paradigm. Before each “method 
execution”, we interpret or execute the invariants and the preconditions 
expressed in the contract, the method runs and after “method execution”, 
we interpret or execute the invariants and the postconditions expressed 
in the contract. No need to have a specific implementation in PHP's core 
for contracts.
Moreover, we can enable or disable AOP in development or production 
environment, which ensures performances.

Thoughts?



> Hi Yasuo,
>
> Following our conversation, I tried to imagine how DbC should look like in
> PHP from user perspective. Finally, I was influenced by the semantic
> proposed in D, and syntax proposed for Java. So, these are my initial
> thoughts:
>
> For php it may look like the following:
>
> function foo()
>      requre(<input-assert-expression>)
>      ensure(<output-assert-expression>)
> {
>    ...
> }
>
> It would require only one new reserved word "ensure".
>
> The assert expressions may be checked or not depending on ini directive.
> It should be also possible to prevent code generation for assertions (zero
> cost asserts). It was already implemented for
> https://wiki.php.net/rfc/expectations
>
> For inherited methods, only the self <input-assert-expression> should be
> checked, and all parent <output-asser-expression>. This is borrowed from D
> but not necessary to be repeated exactly.
>
> I think we shouldn't introduce "invariant" constraints for classes now. May
> be later.
>
> Implementation is going to generate code for input constraint after all
> RECV opcodes and before code for function body, and code for output
> constraint before RETURN opcode (may be reusing implementation of
> "finally").
>
> See:
> http://dlang.org/contracts.html
> http://jan.newmarch.name/java/contracts/paper-long.html
>
> Thanks. Dmitry.

---

## #81932 — Yasuo Ohgaki — 2015-02-05T14:55:00+00:00

URL: https://externals.io/message/81898#81932 · In reply to: #81898

Hi Dmitry,

Thank you for your time!



> Following our conversation, I tried to imagine how DbC should look like in
> PHP from user perspective. Finally, I was influenced by the semantic
> proposed in D, and syntax proposed for Java. So, these are my initial
> thoughts:
>
> For php it may look like the following:
>
> function foo()
>     require(<input-assert-expression>)
>     ensure(<output-assert-expression>)
> {
>   ...
> }
>
> It would require only one new reserved word "ensure".
>

Less reserved word is better.


>
> The assert expressions may be checked or not depending on ini directive.
> It should be also possible to prevent code generation for assertions (zero
> cost asserts). It was already implemented for
> https://wiki.php.net/rfc/expectations
>
> For inherited methods, only the self <input-assert-expression> should be
> checked, and all parent <output-asser-expression>. This is borrowed from D
> but not necessary to be repeated exactly.
>
> I think we shouldn't introduce "invariant" constraints for classes now.
> May be later.
>
> Implementation is going to generate code for input constraint after all
> RECV opcodes and before code for function body, and code for output
> constraint before RETURN opcode (may be reusing implementation of
> "finally").
>

It seems fine to me overall.
I have a few questions, but I think it's better to handle discussion as I
promised.
I'll ask later!

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #81934 — Pierre Joye — 2015-02-05T15:00:33+00:00

URL: https://externals.io/message/81898#81934 · In reply to: #81927

>
> De : Dmitry Stogov [mailto:dmitry@zend.com]
>
> > […]
language for constraints.
> > […]
we have to select one.
>
> Yes, it makes phpdoc more tied to the engine but is it a problem ?

And here I have to jump in and say: don't.

And remind about one of the exact purposes of annotations.

---

## #81935 — Yasuo Ohgaki — 2015-02-05T15:00:39+00:00

URL: https://externals.io/message/81898#81935 · In reply to: #81906

Hi Patrick,



> On Thursday 05 February 2015 15:14:04 Dmitry Stogov wrote:
> > […]
>
> Regarding syntax.... This could be another place where the irrationally-
> dreaded declare would make sense:
>
> function foo() {
>     declare(pre) {
>       if (whatever...) return false;
>       // arbitrary PHP code
>     }
>     declare(post=$resultvar) {
>       if ($resultvar == XXX) return true;
>       return false;
>     }
> }
>
> This way, no new reserved words are needed at all, and the programmer can
> give
> a name to the "variable that holds the result" locally to avoid clashes
> with
> anything else in the function.
>
> I'm a bit undecided whether returning true/false there to give the verdict,
> would be the best way. Maybe better would be another use for declare,
> without
> a block, to declare that the pre/postcondition failed - giving a nice
> place to
> put a suitable message, too. And again without introducing any extra
> keywords:
>
> function foo() {
>     declare(post=$resultvar) {
>         if ($resultvar == XXX) declare(fail="My $resultvar looks fishy");
>     }
> }
>

The idea of "declare(post=$resultvar)" seems interesting, even though
post=$resulvar
looks wired.

$resultvar is L value, but it's located as R value.

There may be better syntax.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #81937 — Yasuo Ohgaki — 2015-02-05T15:21:49+00:00

URL: https://externals.io/message/81898#81937 · In reply to: #81934

Hi all,



> 
> > […]
> language for constraints.
> > […]
> course, we have to select one.
> > […]
>
> And here I have to jump in and say: don't.
>
> And remind about one of the exact purposes of annotations.
>

We don't have to integrate DbC into phpdoc. phpdoc may have integration of
new DbC syntax.
I think it's helpful even if phpdoc copies post/pre condition as document.

There are too many possibility for DbC syntax.
We are better to choose something in common among languages.

All of us understand why DbC is good for weakly typed PHP especially, don't
we?
Let's concentrate we have clean syntax for DbC.

Dmitry's idea is good enough. IMHO. But if you have better one, it should
be written on
this thread now and discuss.

Regards,

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

## #81938 — francois@tekwire.net — 2015-02-05T15:40:02+00:00

URL: https://externals.io/message/81898#81938 · In reply to: #81934

De : Pierre Joye [mailto:pierre.php@gmail.com] 

> > […]
>
> And here I have to jump in and say: don't.
> And remind about one of the exact purposes of annotations.

Sorry, I am not sure I understand.

If you're talking about the link between the engine and phpdoc comments, I agree. It is not a job for the PHP engine. It is a job for a script pre-processor, contained in an extension, and called BEFORE the file starts to be parsed by the engine, not after the AST is generated. It is very easy to pre-process PHP scripts and insert PHP code for DbC checks, while doing the same using an AST and generated opcodes looks much harder to me.

As I told Alexander, in my opinion, phpdoc blocks already provide a lot of useful DbC information. My objective is to extend the syntax to support more complex directives, which are still legitimate phpdoc information. I see both concepts as closely related. One is generating documentation, one is generating runtime checks, but both use the same information.

About annotations, I don't know much about it, as I was naively thinking that phpdoc '@' directives were annotations, but I understand I was probably wrong. The only concern I have about introducing a new annotation syntax is BC break.

Cheers

François

---

## #81940 — Yasuo Ohgaki — 2015-02-05T16:09:42+00:00

URL: https://externals.io/message/81898#81940 · In reply to: #81931

Hi Ivan,

On Thu, Feb 5, 2015 at 11:25 PM, Ivan Enderlin @ Hoa <
ivan.enderlin@hoa-project.net> wrote:

> I just would like to point out some stuff.
>
>
> tl;dr: Contracts can be used to validate code (Design-by-Contract) or
> generate test data to validate code (Contract-based Testing). There are
> plenty of contract languages in the wild, each one addresses a specific
> problem (object, structured type, temporal logic, scenario etc.). If we try
> to develop a contract language, **IT WILL FAIL**, I guarantee it. The
> solution is to give tools to developers to ease the use of contracts, for
> example with Aspect Oriented Programming.
>
>
> There is a whole research PhD thesis about Contract-based Testing in PHP,
> which includes Design-by-Contract, automatic generation of complex test
> data and automatic generation of test suites:
> https://dl.dropboxusercontent.com/u/26317193/PhdThesis.pdf.
> Unfortunately, the thesis is in French but research articles are in
> English. You can found them here (http://hoa-project.net/En/
> Literature.html#Research):
>   * Praspel: A Specification Language for Contract-Driven Testing in PHP
> (article: http://hoa-project.net/En/Literature/Research/Ictss11.pdf,
> keynote: http://keynote.hoa-project.net/Ictss11/EDGB11.pdf),
>   * Grammar-Based Testing using Realistic Domains in PHP (article:
> http://hoa-project.net/En/Literature/Research/Amost12.pdf, keynote:
> http://keynote.hoa-project.net/Amost12/EDGB12.pdf),
>   * A Constraint Solver for PHP Arrays (article:
> http://hoa-project.net/En/Literature/Research/Cstva13.pdf, keynote:
> http://keynote.hoa-project.net/Cstva13/EGB13.pdf).
>
> Concepts behind contracts are twofold:
>   1. Design-by-Contract (DbC), validate code at compile time or at runtime
> (in the case of PHP, it will be at runtime),
>   2. Contract-based Testing (CbT), generate test data based on contracts.
> Preconditions are used to generate inputs, and postconditions validate
> outputs. Invariants must hold before and after the execution of the SUT
> (System Under Test, here methods and functions).
>
> So there are two goals with contracts. We can only address validation
> (DbC) or both (DbC and CbT).
>
> From my own experience and study in this field (I am a PhD in the test
> domain), I suggest you to NOT introduce DbC and CbT in PHP. Why? Because
> the language used to express contracts (even if we use PHP) will be too
> much poor or too much inappropriate for test data validation or test data
> generation (resp. DbC or CbT).
>
> The articles listed above, in addition to the PhD thesis, present Praspel,
> a specification language for PHP, based on contracts. Praspel is used to
> validate and generate (test) data and test suites. This language is
> inspired from JML (Java Modeling Language) and ACSL (ANSI/C Specification
> Language) while addressing PHP features (weakly type for instance). But
> there is a lot more languages in the wild.
> Inventing another language will lead to a fail at a particular time,
> believe me. Each contract language has a specificity: Handling structured
> data, handling events, handling scenario (see Dwyer patterns for temporal
> linear logic) etc. We CANNOT address all these needs.
>
> However, there is a hope :-). DbC and CbT can be easily implemented with
> an Aspect Oriented Programming (AOP) paradigm. Before each “method
> execution”, we interpret or execute the invariants and the preconditions
> expressed in the contract, the method runs and after “method execution”, we
> interpret or execute the invariants and the postconditions expressed in the
> contract. No need to have a specific implementation in PHP's core for
> contracts.
> Moreover, we can enable or disable AOP in development or production
> environment, which ensures performances.
>

It sounds you are looking for way beyond what we discuss.
If there are contracts, program correctness may be proven by contracts, but
this kind of validation is not in scope.
If you think D like DbC support in language is wrong, could you list the
reason why it is?

Thank you.

--
Yasuo Ohgaki
yohgaki@ohgaki.net

---

Next page: https://externals.io/message/81898.md?page=2
