Re: Design by Contract
| From: | Yasuo Ohgaki | Date: | Tue, 10 Feb 2015 06:25:00 +0000 |
| Subject: | Re: Design by Contract | ||
| References: | 1 2 3 4 5 6 7 8 9 10 11 12 | Groups: | php.internals |
| Request: | Send a blank email to internals+get-82331@lists.php.net to get a copy of this message | ||
Hi Dmitry,
On Tue, Feb 10, 2015 at 1:43 PM, Dmitry Stogov <dmitry@zend.com> wrote:
> On Feb 9, 2015 11:20 PM, "Yasuo Ohgaki" <yohgaki@ohgaki.net> wrote:
> >
> > Hi Dmitry and Joe,
> >
> > On Mon, Feb 9, 2015 at 8:27 PM, Dmitry Stogov <dmitry@zend.com> wrote:
> >>
> >> yes. this may work.
> >> probably better to put it after extends and implements.
> >>
> >>
> >> Dmitry.
> >>
> >> On Mon, Feb 9, 2015 at 2:19 PM, Joe Watkins <pthreads@pthreads.org>
> wrote:
> >>>
> >>> Could this be described as a requirement of the class ?
> >>>
> >>> class Mine
> >>> require(invariant-expr)
> >>> extends Something
> >>> implements Someface {
> >>>
> >>> public function method($param) : return
> >>> require(input-expr),
> >>> return(output-expr) {
> >>>
> >>> }
> >>> }
> >>>
> >>> To avoid invariant keyword maybe.
> >
> >
> > This would work.
> > If users have adopted DbC in some way, 'invariant' may be used already.
> >
> > I see two issues.
> >
> > Interface works, but most classes are class without interfaces. Then
> users have to repeat
> > require()/return() many times to check class state or have to use
> interface for DbC.
> >
>
> In D classes may have "invariant" constraints. We may use "require"
> keyword for it. The constraints ineritance rules and order of calls to
> constrains must be the same s in D.
>
> class Foo {
> private $sum = 0;
> require($this->sum >= 0); // invariant constraint will be called
> before and after every method
> function add($n) {
> $this->sum += $n;
> }
> }
>
OK. I'll update the RFC.
> > Since compiler does not know a method() is for DbC invariant, it will be
> compiled and exists
> > in production execution.
> >
> > Use of interface:
> > - no additional keyword (pros)
> > - requires interface for DbC, most classes does not require interface
> (cons)
> > - if interface is not used, user has to repeat invariant conditions
> over and over (cons)
> > - requires to define method that should not exist in production (cons)
>
> I didn't understand you idea.
>
Joe's idea was to use Interface for invariant condition grouping.
If we use your idea, issue is solved.
class Foo {
> private $sum = 0;
> require($this->sum >= 0); // invariant constraint will be called
> before and after every method
> function add($n) {
> $this->sum += $n;
> }
> }
>
Ok.
> >
> > New keyword:
> > - does not require interface for efficient definition (pros).
> > - new keyword (cons)
> >
> > It seems we are better to choose proper keyword for 'invariant'.
> 'invariant' is not common, so 'invariant'
> > may be good enough choice. Does anyone use 'invariant' as
> function/method/class/constant names?
> > If there is better name, suggestion is appreciated.
> >
> > On place closure call like javascript is not supported in PHP, but
> function works with assert.
> >
> > <?php
> > function foo() { return FALSE; }
> > assert(foo());
> > ?>
> > PHP Warning: assert(): Assertion failed in - on line 3
> >
> > This wouldn't be changed for require()/return()/invariant()?
> >
> > We need a switch to change development/production. I'll use "dbc=On/Off"
> for now.
> > If you have any better idea, please let me know. (dbc will be INI_SYSTEM)
>
> Check the "expectations" RFC. I think, it's going to be 3 state switch,
> zero-cost disable, run-time disable, run-time enable. So, it may be
> INI_ALL, but it won't be possible to switch from/to zero-cost at run-time.
>
Ok.
> >
> > For CLI, there will be no command line switch for dbc. It executes
> script production mode by
> > default. If user needs development mode
> >
> > php -d dbc=1 script.php
> >
> > should be used.
> >
> >
> > And finally, are we going to allow custom assertion error message? e.g.
> >
> > require($a > 0, 'Parameter $a must be positive number');
>
> I think, it may be useful.
>
Ok. I'll use it.
> >
> > Since this contract is definition like "implements"/"extends", we may
> not allow
> > custom error message. I'll write the RFC not to allow custom error
> messages unless
> > you dislike it.
> >
> > I think we have enough consensus/information to start writing the RFC.
> > If I have any concern, I'll ask here.
>
> Ok, go forward :)
>
Updated wiki page.
https://wiki.php.net/rfc/dbc2
If you would like to change something, please let me know.
I don't think finished draft at all and I don't mind going back and forth.
Regards,
--
Yasuo Ohgaki
yohgaki@ohgaki.net