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. 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 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