Hi all,
I'm wandering if we could have DbC (Design by Contract) for PHP 6.
http://en.wikipedia.org/wiki/Design_by_contract
There is user land implementation already.
https://gitorious.org/higher-order-php/php-contracts/source/5b0a53b9732f0e4dbe79345212c84c74526def3b:
It could be done with dbc mode INI switch as follows.
When dbc=on, automatically includes
include _dbc . SCRIPT_NAME;
when a script is loaded. No error if there is not the script.
When function/method is called
_dbc_pre. FUNCTION() is called before calling function().
_dbc_post._FUNCTION() is called after function() call.
No error if there is not the function.
Class methods would be more complex, but basic idea is the same.
Issue would be what we should do with $this with class methods.
Automatic namespace might be nice to have for both function and class.
When dbc=off, these would be skipped at all.
It does not sacrifice performance at all for production while it could catch
various errors during development. It could do more complex assertion
than assert()
and it could check post condition that is difficult to achieve
by assert()
. User could have their own strong type safety as long as they
have strict input validation. It could be used as complement of annotation.
Just an idea.
Any comments?
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
2014-01-28 Yasuo Ohgaki yohgaki@ohgaki.net
Hi all,
I'm wandering if we could have DbC (Design by Contract) for PHP 6.
http://en.wikipedia.org/wiki/Design_by_contractThere is user land implementation already.
https://gitorious.org/higher-order-php/php-contracts/source/5b0a53b9732f0e4dbe79345212c84c74526def3b
:It could be done with dbc mode INI switch as follows.
When dbc=on, automatically includes
include _dbc . SCRIPT_NAME;
when a script is loaded. No error if there is not the script.
When function/method is called_dbc_pre. FUNCTION() is called before calling function().
_dbc_post._FUNCTION() is called after function() call.No error if there is not the function.
Couldn't you achieve the same with assert()
?
Class methods would be more complex, but basic idea is the same.
Issue would be what we should do with $this with class methods.Automatic namespace might be nice to have for both function and class.
When dbc=off, these would be skipped at all.
It does not sacrifice performance at all for production while it could
catch
various errors during development. It could do more complex assertion
thanassert()
and it could check post condition that is difficult to
achieve
byassert()
. User could have their own strong type safety as long as they
have strict input validation. It could be used as complement of annotation.Just an idea.
Any comments?Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hello!
Design by Contract can be achieved with Aspect-Oriented technology, as it
provides set of hooks, such as before method execution, after method
execution, around method execution, etc. Logic of contract can be easily
defined as an aspect - class that will receive a control before or after
method execution to check the contract. For example, we can introduce an
annotation as a contract for method and just verify (eval) this contract
during method execution.
Here is my one-minute implementation with Go! AOP framework. First step is
to define an empty Contract annotation:
use Doctrine\Common\Annotations\Annotation;
/**
- @Annotation
- @Target("METHOD")
*/
class Contract extends Annotation
{
}
Next step is to create an aspect, that will be called before each method
that has "Contract" annotation:
class ContractAspect implements Aspect
{
/**
* Verify a contract for a methods annotated with Contract annotation
*
* @param MethodInvocation $invocation
* @Before("@annotation(Annotation\Contract)")
*/
public function beforeContract(MethodInvocation $invocation)
{
$__parameters = $invocation->getMethod()->getParameters();
$__argumentNames = array_map(function (\ReflectionParameter
$parameter) {
return $parameter->name;
}, $__parameters);
$__parameters = array_combine($__argumentNames,
$invocation->getArguments());
extract($__parameters, EXTR_SKIP);
$contract =
$invocation->getMethod()->getAnnotation(Contract::class);
$result = eval("return {$contract->value}; ?>");
if (!$result) {
$obj = $invocation->getThis();
$objName = is_object($obj) ? get_class($obj) : $obj;
$methodName = $invocation->getMethod()->name;
throw new \LogicException("Contract {$contract->value} violated
for {$objName}->{$methodName}");
}
}
}
And now it's possible to use this annotation anywhere to define a contract
for method:
use Annotation\Contract;
class Test
{
/**
* @Contract("strlen($foo) > 6")
*/
public function bar($foo)
{
echo $foo;
}
}
// test.php
$foo = new Test;
$foo->bar('1234567'); // no error
$foo->bar('12'); // LogicException: Contract strlen($foo) > 6 violated for
Test->bar;
What do you think about such implementation of contracts? Feedback is
appreciated.
2014-01-28 Sebastian Krebs krebs.seb@gmail.com
2014-01-28 Yasuo Ohgaki yohgaki@ohgaki.net
Hi all,
I'm wandering if we could have DbC (Design by Contract) for PHP 6.
http://en.wikipedia.org/wiki/Design_by_contractThere is user land implementation already.
https://gitorious.org/higher-order-php/php-contracts/source/5b0a53b9732f0e4dbe79345212c84c74526def3b
:
It could be done with dbc mode INI switch as follows.
When dbc=on, automatically includes
include _dbc . SCRIPT_NAME;
when a script is loaded. No error if there is not the script.
When function/method is called_dbc_pre. FUNCTION() is called before calling function().
_dbc_post._FUNCTION() is called after function() call.No error if there is not the function.
Couldn't you achieve the same with
assert()
?Class methods would be more complex, but basic idea is the same.
Issue would be what we should do with $this with class methods.Automatic namespace might be nice to have for both function and class.
When dbc=off, these would be skipped at all.
It does not sacrifice performance at all for production while it could
catch
various errors during development. It could do more complex assertion
thanassert()
and it could check post condition that is difficult to
achieve
byassert()
. User could have their own strong type safety as long as they
have strict input validation. It could be used as complement of
annotation.Just an idea.
Any comments?Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Here is my one-minute implementation with Go! AOP framework.
[...]class Test
{
/**
* @Contract("strlen($foo) > 6")
*/
public function bar($foo)
{
echo $foo;
}
}
So, dozens of lines of boilerplate, Reflection, and other obscure
features (including, presumably, a userland implementation of
annotations) and the end result is ... an assertion. The pre-condition
is not being added as an aspect, it's hard-coded right there next to the
function, doing exactly the same thing as adding this single line at the
top of the function:
assert('strlen($foo) > 6');
Post-conditions are a little trickier: they require a
single-point-of-return (something which has its advocates anyway, and
could easily be enforced as a project coding standard) and potentially
introduce an intermediate variable that could otherwise be skipped. But
this seems like a lot of overhead to work around that.
Now, I realise that this was a simple example, but I would be interested
to see what such an approach could actually offer in return for its
complexity.
Regards,
--
Rowan Collins
[IMSoP]
Hi Sebastian,
On Tue, Jan 28, 2014 at 5:36 PM, Sebastian Krebs krebs.seb@gmail.comwrote:
I'm wandering if we could have DbC (Design by Contract) for PHP 6.
http://en.wikipedia.org/wiki/Design_by_contract
There is user land implementation already.
https://gitorious.org/higher-order-php/php-contracts/source/5b0a53b9732f0e4dbe79345212c84c74526def3b
:It could be done with dbc mode INI switch as follows.
When dbc=on, automatically includes
include _dbc . SCRIPT_NAME;
when a script is loaded. No error if there is not the script.
When function/method is called_dbc_pre. FUNCTION() is called before calling function().
_dbc_post._FUNCTION() is called after function() call.No error if there is not the function.
Couldn't you achieve the same with
assert()
?
Assert can be used for DbC and there are such implementations.
Precondition is easy with assert()
, but post condition is rather difficult
since
we need assert()
before every 'return'. This could damage production code
(code executed on production environment) and contract readability. It
increases
chances of omitting post condition check by mistake.
Similar mistake may happen with this.
We may better to have option to warn non existent pre/post check.
Like Alexander explained, pure OO code can use DbC. It may be enough
for people who are interested in DbC.
This is just an idea. It's simple, powerful and easy to adopt. Since there
is no DbC code in production code, it's fast while assert()
need
compilation
overhead. It does not matter much with opcache, though.
With this approach, user has to look up contract in other file. This is
disadvantage over other methods.
I wander how many of us are interested in such feature.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
2014-01-29 Yasuo Ohgaki yohgaki@ohgaki.net
Hi Sebastian,
On Tue, Jan 28, 2014 at 5:36 PM, Sebastian Krebs krebs.seb@gmail.comwrote:
I'm wandering if we could have DbC (Design by Contract) for PHP 6.
http://en.wikipedia.org/wiki/Design_by_contract
There is user land implementation already.
https://gitorious.org/higher-order-php/php-contracts/source/5b0a53b9732f0e4dbe79345212c84c74526def3b
:It could be done with dbc mode INI switch as follows.
When dbc=on, automatically includes
include _dbc . SCRIPT_NAME;
when a script is loaded. No error if there is not the script.
When function/method is called_dbc_pre. FUNCTION() is called before calling function().
_dbc_post._FUNCTION() is called after function() call.No error if there is not the function.
Couldn't you achieve the same with
assert()
?Assert can be used for DbC and there are such implementations.
Precondition is easy with
assert()
, but post condition is rather difficult
since
we needassert()
before every 'return'.
Well .. Yeah. But that is difficult?
This could damage production code
(code executed on production environment) and contract readability. It
increases
chances of omitting post condition check by mistake.
This is possible with every implementation...
Similar mistake may happen with this.
We may better to have option to warn non existent pre/post check.Like Alexander explained, pure OO code can use DbC. It may be enough
for people who are interested in DbC.This is just an idea. It's simple, powerful and easy to adopt. Since there
is no DbC code in production code, it's fast whileassert()
need
compilation
overhead. It does not matter much with opcache, though.
No, at least not measurable. You can disable it. In that case it behaves
like an empty function body.
With this approach, user has to look up contract in other file. This is
disadvantage over other methods.I wander how many of us are interested in such feature.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net
Hi all,
Hello :-),
I'm wandering if we could have DbC (Design by Contract) for PHP 6.
http://en.wikipedia.org/wiki/Design_by_contractThere is user land implementation already.
https://gitorious.org/higher-order-php/php-contracts/source/5b0a53b9732f0e4dbe79345212c84c74526def3b:It could be done with dbc mode INI switch as follows.
When dbc=on, automatically includes
include _dbc . SCRIPT_NAME;
when a script is loaded. No error if there is not the script.
When function/method is called_dbc_pre. FUNCTION() is called before calling function().
_dbc_post._FUNCTION() is called after function() call.No error if there is not the function.
What kind of errord would you like to print? “The precondition has
failed”, ok but why? With what data?
Class methods would be more complex, but basic idea is the same.
Issue would be what we should do with $this with class methods.Automatic namespace might be nice to have for both function and class.
When dbc=off, these would be skipped at all.
It does not sacrifice performance at all for production while it could catch
various errors during development. It could do more complex assertion
thanassert()
So the pre- and postconditions must be predicates, i.e. computing a boolean.
and it could check post condition that is difficult to achieve
byassert()
. User could have their own strong type safety as long as they
have strict input validation. It could be used as complement of annotation.Just an idea.
Any comments?
What about invariants which is the third part of DbC?
Did you heard about Praspel [1]. Praspel is a BISL (Behavioral Interface
Specification Language), i.e. a specification language for
contract-based testing I develop in my PhD thesis (in INRIA
laboratories). You will find some materials here [2]. I recommend you to
start by the presentations/keynotes. The idea is to allow the user to
write contracts (precondition, postcondition, exceptional postcondition,
invariant, behavior etc.), and we exploit them in order to generate
(unit) tests automatically.
I'm reaching the end of my PhD and I'm currently writing the
documentation and finalizing the tools. Today, we are able to:
(1) generate very different kinds of data (strings with regexs or
grammars thanks to grammar-based testing algorithms [3, 4], arrays
thanks to an array-solver [5] etc.)
(2) verify a contract with a Runtime Assertion Checker (please, see
articles or directly the code [6])
(3) automatically generate (unit) tests that are executable with
atoum's API [7, 8]
We are preparing videos and documentations in order to promote it up to
June. I suggest to read the presentations, you will get an overview of
all the work.
I think DbC must stay annotations, so in comments of the code. If
contracts would be part of the PHP grammar, it would be disappointed for
everyone because there is no unique way to express a contract: either
with the language syntax itself (such as JML [9]) or with a dedicated
language, such as Praspel. Both have pros and cons that I won't describe
here (except if you ask).
However, having the Aspect Oriented Programming paradigm would be very
appreciated. It would avoid a lot of instrumentations and static analyzes.
Regards.
[1] https://en.wikipedia.org/wiki/Praspel
[2] http://hoa-project.net/En/Literature.html#Research
[3] http://keynote.hoa-project.net/Amost12/EDGB12.pdf
[4] https://github.com/hoaproject/Compiler (documentation is under
translation)
[5] http://keynote.hoa-project.net/Cstva13/EGB13.pdf
[6] https://github.com/hoaproject/Praspel/tree/master/AssertionChecker
[7] http://atoum.org/
[8] https://github.com/hoaproject/Hoathis-Atoum
[9] https://en.wikipedia.org/wiki/Java_Modeling_Language
--
Ivan Enderlin
Developer of Hoa
http://hoa-project.net/
PhD. student at DISC/Femto-ST (Vesontio) and INRIA (Cassis)
http://disc.univ-fcomte.fr/ and http://www.inria.fr/
Member of HTML and WebApps Working Group of W3C
http://w3.org/
Hi Ivan,
On Wed, Jan 29, 2014 at 5:48 PM, Ivan Enderlin @ Hoa <
ivan.enderlin@hoa-project.net> wrote:
I think DbC must stay annotations, so in comments of the code. If
contracts would be part of the PHP grammar, it would be disappointed for
everyone because there is no unique way to express a contract: either with
the language syntax itself (such as JML [9]) or with a dedicated language,
such as Praspel. Both have pros and cons that I won't describe here (except
if you ask).
However, having the Aspect Oriented Programming paradigm would be very
appreciated. It would avoid a lot of instrumentations and static analyzes.
This idea is a too simple and leaving almost all to user land scripts.
I agree that DbC must stay annotations. It's easier to write/read/maintain.
Unfortunately, annotation RFC is not accepted.
I agree that comprehensive implementation should be chosen if it's possible.
Thank you for your inputs!
[1] https://en.wikipedia.org/wiki/Praspel
[2] http://hoa-project.net/En/Literature.html#Research
[3] http://keynote.hoa-project.net/Amost12/EDGB12.pdf
[4] https://github.com/hoaproject/Compiler (documentation is under
translation)
[5] http://keynote.hoa-project.net/Cstva13/EGB13.pdf
[6] https://github.com/hoaproject/Praspel/tree/master/AssertionChecker
[7] http://atoum.org/
[8] https://github.com/hoaproject/Hoathis-Atoum
[9] https://en.wikipedia.org/wiki/Java_Modeling_Language
I'll read them later.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net