[Typo3-dev] OT: Hooks, was: Pledge fo 3.8.1
Dimitri Tarassenko
dtarassenko at gmail.com
Fri Jun 3 00:38:24 CEST 2005
Hi Michael,
I'll try to explain what I mean. What hooks implement is "chained"
polymorphism, in other words, they create a possibility to extend the
existing functions in subclasses, and all the additional steps for a
hook implemented in ALL subclasses are going to be executed. This
somehow circumvents the bottleneck of XCLASSing - i.e. only 1 level of
subclassing.
XCLASsing limit to 1 custom extension to a class is huge design flow,
in particular inflicted by deficiencies of PHP itself.
Imagine, if we could build "chains" of classes in extensions, say in this way:
******************************************************
class Coreclass {
function SmokeCigar() {}
}
LastInCoreClassChain = Coreclass
===
class extension_chair implements LastInCoreClassChain {
function SmokeCigar() {
sit_in_the_Chair();
parent::SmokeCigar();
}
LastInCoreClassChain = extension_chair
===
class extension_cognac implements LastInCoreClassChain {
function SmokeCigar() {
parent::SmokeCigar();
drink_some_cognac();
}
}
LastInCoreClassChain = extension_cognac
====
instance = New LastInCoreClassChain();
instance->SmokeCigar();
*****************************
Obviously, in our fantasy world, both extensions "chair" and "cognac"
could be used either at the same time or just one of them to enhance
our cigar smoking experience. However, PHP does not let us do that
very easily. Unlike truly object oriented languages, where class
definition is an object as well, we'd have to do something like this
(tested and working sample):
=== lunch.php ===
#!/usr/bin/php
<?
class german {
function eat_salad() {
echo "Mmmm... salaad!\n";
}
function eat_main_course() {
echo "Mmmm... bratwurst!\n";
}
function lunch() {
$this->eat_salad();
$this->eat_main_course();
}
}
$guest = "german"; // let's record the last type name
// Let's imagine that we have this "french" extension that is
// optional, and may be in a different file.
eval("class french_proto extends $guest {}");
class french extends french_proto {
function eat_main_course() {
echo "Mmmm... filet mignon!\n";
}
function lunch() {
$this->eat_main_course();
$this->eat_salad();
}
}
// Note that if we exclude "french" from the subclassing chain by
// commenting out the next line, the program will still work, but
// the russian will eat bratwurst after salad.
$guest = "french";
// (in a real world, this would mean "french" extension disabled.
// And we'll override once more.
eval("class russian_proto extends $guest {} ");
class russian extends russian_proto {
function lunch() {
parent::lunch();
echo "...and a shot of Stoli.\n";
}
}
$guest = "russian";
// Now, let's create an instance.
echo "My $guest friend is here for lunch:\n";
eval("class LunchGuest extends $guest {}");
$myLunchGuest = New LunchGuest();
$myLunchGuest->lunch();
?>
=== end of lunch.php ===
Just for fun and for those of you hardcore PHP fans suspiciously
looking at Python, here is how similar construction looks in it:
=== lunch.py ===
#!/usr/bin/python
guest = None
class german:
mainCourse = "bratwurst"
def eat_salad(self):
print "Mmmm... salad!"
def eat_main_course(self):
print "Mmmm... %s" % self.mainCourse
def lunch(self):
self.eat_salad()
self.eat_main_course()
guest = german
class french(guest):
parent = guest
mainCourse = "filet mignon"
def lunch(self):
self.eat_main_course()
self.eat_salad()
guest = french
class russian(guest):
parent = guest
def lunch(self):
self.parent.lunch(self)
print "... and a shot of Stoli!"
guest = russian
print "My %s friend is here" % guest.__name__
myLunchGuest = guest();
myLunchGuest.lunch();
=== end of lunch.py ===
Unfortunately, with so many extensions based on XCLASS and hooks out
there I don't see TYPO3 likely to implement something like this in any
near future, and may be forever. (That's why I marked the topic OT,
BTW:).
However, this does look a bit better concept than XCLASSing+hooks.
Hope you enjoyed this;)
D.
On 6/2/05, Michael Scharkow <mscharkow at gmx.net> wrote:
> Dimitri Tarassenko wrote:
> > Am I the only one thinking that "hooks" are a sign of bad decoupling
> > in software? The more I look at how and where the hooks are used, the
> > more I think that whenever a hook is required and implemented what
> > really needs to be done is the method containing the hook needs to be
> > split in several and one of these submethods should be iplemented in a
> > subclass.
>
> Can you elaborate on this? I don't see how putting a method in a
> subclass (btw. we're subclassing exactly what?) works for hooks. Hooks
> are only only "announcing" that there is some data available for
> processing, but they know nothing about who "answers". The difficulty
> for the core code would then be to know when to use subclass Y instead
> of Z, right?
>
> > These "hooks" are going to be nightmare to manage and debug once their
> > number (and number of extensions that may use them) grow.
>
> I'm not sure how much effort it really is to maintain some two-line hook
> which is embedded in some method. And while there might me scalability
> issues with the number of hooks in the code, the number of extensions
> using them should not matter to the author of the hook code itself
> (given API stability).
>
> Anyway, I'd be interested in a better concept that is flexible but not
> quite as hackish as XClassing...
>
> Greetings,
> Michael
> _______________________________________________
> Typo3-dev mailing list
> Typo3-dev at lists.netfielders.de
> http://lists.netfielders.de/cgi-bin/mailman/listinfo/typo3-dev
>
--
Dimitri Tarassenko
More information about the TYPO3-dev
mailing list