Newsgroups: php.internals Path: news.php.net Xref: news.php.net php.internals:82680 Return-Path: Mailing-List: contact internals-help@lists.php.net; run by ezmlm Delivered-To: mailing list internals@lists.php.net Received: (qmail 2023 invoked from network); 14 Feb 2015 11:06:51 -0000 Received: from unknown (HELO lists.php.net) (127.0.0.1) by localhost with SMTP; 14 Feb 2015 11:06:51 -0000 Authentication-Results: pb1.pair.com header.from=php@tutteli.ch; sender-id=pass Authentication-Results: pb1.pair.com smtp.mail=php@tutteli.ch; spf=pass; sender-id=pass Received-SPF: pass (pb1.pair.com: domain tutteli.ch designates 80.74.154.78 as permitted sender) X-PHP-List-Original-Sender: php@tutteli.ch X-Host-Fingerprint: 80.74.154.78 ns73.kreativmedia.ch Linux 2.6 Received: from [80.74.154.78] ([80.74.154.78:48591] helo=hyperion.kreativmedia.ch) by pb1.pair.com (ecelerity 2.1.1.9-wez r(12769M)) with ESMTP id 1A/91-25612-84C2FD45 for ; Sat, 14 Feb 2015 06:06:49 -0500 Received: (qmail 8902 invoked from network); 14 Feb 2015 12:06:44 +0100 Received: from cm56-153-252.liwest.at (HELO RoLaptop) (86.56.153.252) by ns73.kreativmedia.ch with ESMTPSA (AES256-SHA encrypted, authenticated); 14 Feb 2015 12:06:44 +0100 To: , "'Yasuo Ohgaki'" Cc: "'Dmitry Stogov'" , "'Joe Watkins'" , "'Stanislav Malyshev'" , "'PHP Internals'" References: <54DAFD32.3000005@gmail.com> <54DB0BC0.20304@gmail.com> <54DBA801.8060403@gmail.com> <011e01d04802$cbd78ce0$6386a6a0$@php.net> <013801d0481d$d34c5170$79e4f450$@php.net> In-Reply-To: <013801d0481d$d34c5170$79e4f450$@php.net> Date: Sat, 14 Feb 2015 12:06:42 +0100 Message-ID: <002701d04846$50c0d630$f2428290$@tutteli.ch> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Mailer: Microsoft Outlook 14.0 Thread-Index: AQGgxP9HPTh52uHWkGo6jLSeXRdtNAHjmxmHAVkKc8gBfNJbegGHSzWZAVLQRzQCoXlWsAGB4HqFAsDJgekCOAevPAH9iUyEAXhQrm4CanwAQAHshXVfAlKjS7cCbhkxVQIVHKPQAgp4FX0A+MmcAQGuA/NIAiGQVlqcHdXAIA== Content-Language: de-ch Subject: AW: [PHP-DEV] Design by Contract From: php@tutteli.ch ("Robert Stoll") > -----Urspr=C3=BCngliche Nachricht----- > Von: Fran=C3=A7ois Laupretre [mailto:francois@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 >=20 > I will try to explain but that=E2=80=99s not so clear for me too. >=20 >=20 >=20 > 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=E2=80=99t ask why, I don=E2=80=99t understand the reason very well. > But that=E2=80=99s his rule, and everyone seems to respect it. >=20 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 >=20 > 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). >=20 >=20 >=20 > The logic described in the D documentation is : if a method defines = pre-conditions, check them and stop (don=E2=80=99t check > parent=E2=80=99s 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=E2=80=99s = responsibility to loosen conditions in derived classes but it is = possible. If you > check every parent=E2=80=99s pre-conditions, it is just *not* = possible. >=20 >=20 >=20 > I am not sure I am clear. I guess from the example above it should be clear why D has implemented = it this way >=20 >=20 > I chose not to follow exactly this logic as I think we can do it more = =E2=80=98PHP way=E2=80=99 (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=E2=80=99t > check anything (don=E2=80=99t search a parent method). If it defines = some, we execute them. I introduce a =E2=80=98special=E2=80=99 condition = : the > =E2=80=98@parent=E2=80=99 pseudo-condition means =E2=80=98go down = checking my parent=E2=80=99s conditions=E2=80=99. This way, similar to = =E2=80=98parent::__construct()=E2=80=99 > logic allows the developer to decide if he wants to check = parent=E2=80=99s conditions or not. >=20 >=20 >=20 > Example : >=20 >=20 >=20 > /** >=20 > * @requires ($a < $b) >=20 > * @requires @parent <- Go checking parent=E2=80=99s pre-conditions >=20 > * @requires =E2=80=A6 >=20 >=20 >=20 > For better consistence, I chose to implement the same for = post-conditions and invariants, but I am not sure I will keep >=20 > the same logic. >=20 >=20 >=20 > 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=E2=80=99ll assume that =E2=80=98@parent=E2=80=99 means = =E2=80=98check > the conditions defined in the parent method and the method of the = interface that defines it=E2=80=99. Unfortunately, interfaces > have parents too and can define methods with same name. So, = it=E2=80=99s the same sort of problems as multiple inheritance. I will > need to make a choice here. The simplest one would be =E2=80=98no = support for DbC in interfaces=E2=80=99. >=20 >=20 >=20 >=20 >=20 > De : yohgaki@gmail.com [mailto:yohgaki@gmail.com] De la part de Yasuo = Ohgaki Envoy=C3=A9 : samedi 14 f=C3=A9vrier 2015 05:16 =C3=80 : > francois Cc : Dmitry Stogov; Joe Watkins; Stanislav Malyshev; PHP = Internals Objet : Re: [PHP-DEV] Design by Contract >=20 >=20 >=20 > Hi Francois, >=20 >=20 >=20 > On Sat, Feb 14, 2015 at 12:53 PM, Yasuo Ohgaki = wrote: >=20 > On Sat, Feb 14, 2015 at 12:03 PM, Fran=C3=A7ois Laupretre = wrote: >=20 > > For method calls, overridden method should not evaluate parents = contract on entry. > > It should be evaluated when parent method is called. >=20 > 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. >=20 >=20 > Did you mean "Least Concern Principle" here? >=20 >=20 > I'm lost here. Eiffel does not even allow method overriding. = Therefore, child class's method contract >=20 > will never evaluated unless it is explicitly called. Semantics is = basically the same as what I wrote. >=20 > (Eiffel requires to drop parent method by "redefine" or rename parent = method by "rename" when >=20 > the same method name is needed) >=20 >=20 >=20 > I agree that Eiffel's approach is stricter with respect to least = concern principle. >=20 > It's just not suitable for PHP, is it? >=20 >=20 >=20 > Similar argument can be done for D's invariant. D dropped invariant = from class in favor of >=20 > immutables. Immutable is better for least concern, but we don't have = immutables now. >=20 > Even if we have it, people would like to manage object state. We may = have both. >=20 >=20 >=20 > Anyway, could you explain what kind of issues we may have? >=20 >=20 >=20 > Regards, >=20 >=20 >=20 >=20 > -- > Yasuo Ohgaki > yohgaki@ohgaki.net