> -----Ursprüngliche Nachricht----- > Von: François Laupretre [mailto:franc...@php.net] > 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 : yohg...@gmail.com [mailto:yohg...@gmail.com] 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 <yohg...@ohgaki.net> wrote: > > On Sat, Feb 14, 2015 at 12:03 PM, François Laupretre <franc...@php.net> 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 > yohg...@ohgaki.net -- PHP Internals - PHP Runtime Development Mailing List To unsubscribe, visit: http://www.php.net/unsub.php