> It can be perfectly ok to allow the lib to be extended and the constructor
> extended/replaced with a compatible one.

Well sure, it's great to override constructors completely. If the lib
authors didn't want you to do that, they should've made it final
(which is what I said they should do now). You have every reason to
expect this will work and keep working. Without call super.

But "extending" a constructor in some made-up way where you override
and just *guess* you need to call super if one exists -- after your
additional code? before? why one over the other? -- without any formal
documentation at all about the consequences? I think that's a stink
bomb and I'm sticking with that view. It's like you're treating the
superctor as simultaneously opaque and knowable.

Say it happens to work at first b/c you don't touch any resources that
the superctor needs, or you assign them and the superctor runs
afterward and resets them to a workable state (unbeknownst to you).
For the sake of argument, let's call this compatibility instead of
luck. And how do you keep it compatible? You don't. They could change
the superctor signature (oops! you're out of luck because you don't
pass them what they need). Internally, they could change what
resources superctor expects you to leave alone, what it doesn't, and
in what order. It's simple to break this kind of thing, where a
third-party doesn't want you to do something but they forgot to stop
you.

> Either the lib author needs to add an empty constructor into every class
> just to make sure that it will be there to provide a painless upgrade when
> the need arises for a constructor 

There's no guarantee at all that it will be painless, because the
signatures could mismatch, not to mention every single other
dependency being subject to your guesswork. If the authors change
their approach, it should be to the Template Method/subinit pattern,
not making an "official" Call Super reqt that'll still be doomed to
failure.

> otherwise the lib consumer has to write boilerplate to make sure
> that the parent constructor will be only called whet ot is there.

Which is still just a guess, and basically doomed. Why would you think
you can run an opaque parent:__construct() at any time? I would never
just trust that. And I'm hardly risk-averse. :)

Look, my gripe isn't with silencing/catching the call to unknown
methods in lieu of method_exists(). If that gets easier to do in the
language, fine. But I think this use case stinks as a justification.
Still, I'll lay off after this e-mail because I will have said my
piece. :P

> Your example also shows an overengineered solution for a simple problem.

But it's 4 lines long! The rest is comments and examples of usage. And
it's a _real_ solution to the problem, so it could only be
overengineered vs. something else that is functionally equivalent.

The Template Method pattern ensures that the child classes do not need
to "remember" to invoke a particular method within their initializer.
Simply by having an init() method in your derived class, you ensure
that upper-level dependencies will be taken care of, and you don't
have to have an init() method at all if you don't want to, or you can
have an empty one with no side effects. The initialization hierarchy
is baked into the object model at the outermost possible layer (since
you can't go one more level out into language constructs). This
doesn't mean you don't need documentation of what you should/shouldn't
do when you init, but it is way closer to being manageable over time.

The Call Super pattern requires that the user remember to call within
their ctor code, and even worse, the situation under discussion is
truly the worst possible argument for the pattern, since _you don't
even have any word from the library author_ that call super is
recommended or required... so not only can you not enforce the
contract, you're making up the notion of the contract off the top of
your head.

Cheers regardless --

-- S.


-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to