> -----Ursprüngliche Nachricht-----
> Von: François Laupretre [mailto:[email protected]]
> Gesendet: Samstag, 14. Februar 2015 07:17
> An: 'Yasuo Ohgaki'
> Cc: 'Dmitry Stogov'; 'Joe Watkins'; 'Stanislav Malyshev'; 'PHP Internals'
> Betreff: RE: [PHP-DEV] Design by Contract
>
> I will try to explain but that’s not so clear for me too.
>
>
>
> The theory (from Eiffel guru) states that, to respect this fucking LSP rule,
> the pre-conditions to check when entering a
> method must be less strict than when entering its parent method. Don’t ask
> why, I don’t understand the reason very well.
> But that’s his rule, and everyone seems to respect it.
>
The theory is actually quite simple. Roughly it says that if you use a type
hint of a certain class then you can rely on all pre/post-conditions of this
class even if a sub-class is passed. Hence the sub-class cannot have more
restrict conditions. Consider the following (no longer sure which syntax is the
one you intend to use, so I just use pre and post):
class A{
function foo($x){
pre($x > 100);
}
}
class B extends A{
function foo($x){
pre($x > 50); // less restrictive, that's fine
}
}
class C{
function foo($x){
pre($x > 150); //more restrictive that's not allowed
}
}
function foo(A $a){
$a->foo(101); // that is ok as long as LSP is not violated
}
foo(new A()); //that's fine
foo(new B()); //fine as well
foo(new C()); //nope, C violates LSP and thus will result in an error
>
> In your RFC, you say that, when we enter a method, we must check its
> pre-conditions, as well as the ones of every parents.
> As you can only add conditions, compared to what you would do for the parent,
> the checks can only be stricter (more
> conditions).
>
>
>
> The logic described in the D documentation is : if a method defines
> pre-conditions, check them and stop (don’t check
> parent’s pre-conditions). If the method does not define pre-conditions, go
> down one level and check if parent method
> defines some. As soon as a method defining pre-conditions is found, these are
> checked and control is returned without
> going further. This way, it is still the developer’s responsibility to loosen
> conditions in derived classes but it is possible. If you
> check every parent’s pre-conditions, it is just *not* possible.
>
>
>
> I am not sure I am clear.
I guess from the example above it should be clear why D has implemented it this
way
>
>
> I chose not to follow exactly this logic as I think we can do it more ‘PHP
> way’ (something like the way constructors and
> destructors explicitly call their parent methods). My logic is : if the
> method we are entering has no pre-conditions, we don’t
> check anything (don’t search a parent method). If it defines some, we execute
> them. I introduce a ‘special’ condition : the
> ‘@parent’ pseudo-condition means ‘go down checking my parent’s conditions’.
> This way, similar to ‘parent::__construct()’
> logic allows the developer to decide if he wants to check parent’s conditions
> or not.
>
>
>
> Example :
>
>
>
> /**
>
> * @requires ($a < $b)
>
> * @requires @parent <- Go checking parent’s pre-conditions
>
> * @requires …
>
>
>
> For better consistence, I chose to implement the same for post-conditions and
> invariants, but I am not sure I will keep
>
> the same logic.
>
>
>
> The only thing that remains not clear for me is the role of conditions
> defined in interfaces, as the D documentation says that
> they can be defined but it does not explain when they are checked. I assume
> this is considered as a parent but the order
> matters in pre-conditions as we only execute the first conditions we find. I
> think I’ll assume that ‘@parent’ means ‘check
> the conditions defined in the parent method and the method of the interface
> that defines it’. Unfortunately, interfaces
> have parents too and can define methods with same name. So, it’s the same
> sort of problems as multiple inheritance. I will
> need to make a choice here. The simplest one would be ‘no support for DbC in
> interfaces’.
>
>
>
>
>
> De : [email protected] [mailto:[email protected]] De la part de Yasuo Ohgaki
> Envoyé : samedi 14 février 2015 05:16 À :
> francois Cc : Dmitry Stogov; Joe Watkins; Stanislav Malyshev; PHP Internals
> Objet : Re: [PHP-DEV] Design by Contract
>
>
>
> Hi Francois,
>
>
>
> On Sat, Feb 14, 2015 at 12:53 PM, Yasuo Ohgaki <[email protected]> wrote:
>
> On Sat, Feb 14, 2015 at 12:03 PM, François Laupretre <[email protected]> wrote:
>
> > For method calls, overridden method should not evaluate parents contract on
> > entry.
> > It should be evaluated when parent method is called.
>
> I already told you : the logic you are using for pre-conditions is NOT
> compatible with Eiffel and D logic, although this is what
> you're supposed to mimic. It is actually the opposite. Is it a wanted
> behavior ? because you should be aware that it does not
> respect the LS principle.
>
>
> Did you mean "Least Concern Principle" here?
>
>
> I'm lost here. Eiffel does not even allow method overriding. Therefore, child
> class's method contract
>
> will never evaluated unless it is explicitly called. Semantics is basically
> the same as what I wrote.
>
> (Eiffel requires to drop parent method by "redefine" or rename parent method
> by "rename" when
>
> the same method name is needed)
>
>
>
> I agree that Eiffel's approach is stricter with respect to least concern
> principle.
>
> It's just not suitable for PHP, is it?
>
>
>
> Similar argument can be done for D's invariant. D dropped invariant from
> class in favor of
>
> immutables. Immutable is better for least concern, but we don't have
> immutables now.
>
> Even if we have it, people would like to manage object state. We may have
> both.
>
>
>
> Anyway, could you explain what kind of issues we may have?
>
>
>
> Regards,
>
>
>
>
> --
> Yasuo Ohgaki
> [email protected]
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php