Hi folks,
after discussing the idea with various PHP developers I now felt safe enough that it's not a completely stupid idea to post an RFC for it. The idea is to add support the registration of custom factories which are responsible for instantiating certain classes.
Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactories
I suggest that we first discuss the implications and usefulness of this feature. In a second step I'd need to find some skilled internals wizard who can implement it, because not being a C developer myself, all I can offer is making suggestions and fine coffee.
Looking forward to hearing your comments!
Robert
--
Robert Lemke
Fluent Code Artisan
Lead Developer TYPO3 5.0 and FLOW3
TYPO3 Association co-founder
http://typo3.org
http://flow3.typo3.org
http://association.typo3.org
Hi folks,
after discussing the idea with various PHP developers I now felt safe enough that it's not a completely stupid idea to post an RFC for it. The idea is to add support the registration of custom factories which are responsible for instantiating certain classes.
Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactoriesI suggest that we first discuss the implications and usefulness of this feature. In a second step I'd need to find some skilled internals wizard who can implement it, because not being a C developer myself, all I can offer is making suggestions and fine coffee.
Looking forward to hearing your comments!
So, from the high-level point of view, you want to introduce mechanism, which would allow instantiate objects by their interface, instead of their class-name.
And this mechanism should use user-provided rules for choosing appropriate implementation.
Hi Alexey,
Am 18.11.2009 um 17:27 schrieb Alexey Zakhlestin:
So, from the high-level point of view, you want to introduce mechanism, which would allow instantiate objects by their interface, instead of their class-name.
And this mechanism should use user-provided rules for choosing appropriate implementation.
well, using interface was just an example, we'd need the ability to instantiate classes as well by custom factories. I tried to clarify this by an updated example:
class Foo {
public function bar() {
// Instantiate by class name:
$email = new Email();
// or even instantiate by interface name (the factory needs to find the right implementation):
$email = new EmailInterface();
}
}
So in the end the custom factory needs to find an appropriate implementation for EmailInterface.
Cheers,
robert
--
Robert Lemke
Fluent Code Artisan
Hi!
Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactories
Something I'm missing in this RFC: what's wrong with factory base class
doing:
public static function getInstance() {
if(static::$instance === NULL) {
static::$instance = new static;
}
return static::$instance;
}
instead of "new self", and then the client class doing:
$this->logger = WhateverLogger::getInstance();
or even:
$clientLogger = $this->config['logger'];
$this->logger = $clientLogger::getInstance();
Also, the whole thing, whatever it is, looks like something one would do
in user space in a framework, not on language level.
Stanislav Malyshev, Zend Software Architect
stas@zend.com http://www.zend.com/
(408)253-8829 MSN: stas@zend.com
what you call factory objects are "more" proxy objects, please make
the difference, semantics are sometimes important.
anyway , what I can read this document is a bit a mess, it needs to be
split by "topic", your approach is really confuse.
Best,
Hi folks,
after discussing the idea with various PHP developers I now felt safe enough that it's not a completely stupid idea to post an RFC for it. The idea is to add support the registration of custom factories which are responsible for instantiating certain classes.
Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactoriesI suggest that we first discuss the implications and usefulness of this feature. In a second step I'd need to find some skilled internals wizard who can implement it, because not being a C developer myself, all I can offer is making suggestions and fine coffee.
Looking forward to hearing your comments!
Robert--
Robert Lemke
Fluent Code ArtisanLead Developer TYPO3 5.0 and FLOW3
TYPO3 Association co-founderhttp://typo3.org
http://flow3.typo3.org
http://association.typo3.org
-----Original Message-----
From: Robert Lemke [mailto:robert@typo3.org]
Sent: 18 November 2009 16:07
To: internals@lists.php.net
Subject: [PHP-DEV] RFC: Custom Factories (SPL)Hi folks,
after discussing the idea with various PHP developers I now
felt safe enough that it's not a completely stupid idea to
post an RFC for it. The idea is to add support the
registration of custom factories which are responsible for
instantiating certain classes.Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactoriesI suggest that we first discuss the implications and
usefulness of this feature. In a second step I'd need to find
some skilled internals wizard who can implement it, because
not being a C developer myself, all I can offer is making
suggestions and fine coffee.Looking forward to hearing your comments!
Robert--
Robert Lemke
Fluent Code Artisan
Whilst I am a fan of IoC, I don't think its desirable to add language
features just to make legacy code more flexible.
Surely the route to take is to refactor the legacy code as and when
the extra flexibility is needed.
Also seems like a possible whole heap of wtf?! When a seemingly
absolute statement $a = new A(); gets mangled behind the scenes.
Jared
Le Thu, 19 Nov 2009 02:24:01 +0000, Jared Williams a écrit :
-----Original Message-----
From: Robert Lemke [mailto:robert@typo3.org] Sent: 18 November 2009
16:07
To: internals@lists.php.net
Subject: [PHP-DEV] RFC: Custom Factories (SPL)Hi folks,
after discussing the idea with various PHP developers I now felt safe
enough that it's not a completely stupid idea to post an RFC for it.
The idea is to add support the registration of custom factories which
are responsible for instantiating certain classes.Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactoriesI suggest that we first discuss the implications and usefulness of this
feature. In a second step I'd need to find some skilled internals
wizard who can implement it, because not being a C developer myself,
all I can offer is making suggestions and fine coffee.Looking forward to hearing your comments! Robert
--
Robert Lemke
Fluent Code ArtisanWhilst I am a fan of IoC, I don't think its desirable to add language
features just to make legacy code more flexible. Surely the route to
take is to refactor the legacy code as and when the extra flexibility is
needed.Also seems like a possible whole heap of wtf?! When a seemingly absolute
statement $a = new A(); gets mangled behind the scenes.Jared
I'm totaly agree with you Jared !
I'm a fan of IoC too.
A factory can provide an object by creating an instance of a class, the
choice of the class depends of some paramters. Those parameters can be
provided directly by the programmer but also by a final user.
PHP can not simply "choose" the class to instanciate by checking class's
interfaces.
What Robert Lemke wants to implement is called a "Service" or a
"Container".
You register a service and call the service instead of calling a class
directly.
Let me show it in an example of session registration :
// you register the service
Services::register('session', 'sessionStoredInCookie');
// and call it
$session = Services::load('session');
Tomorrow, if you want change the session registration mechanism, for
storing them in a database for exemple, you have just to change the
registred service and whole application has change its session
registration method :
// you register the service
Services::register('session', 'sessionStoredInDatabase');
This is very well treated by Fabien Potencier in this document : http://
fabien.potencier.org/talk/20/decouple-your-code-for-reusability-php-
forum-2008?position=41 (some parts are in french)
Implementing a service or container mechanism could be very simple or
very complicated. Fabien Potencier use a very complicated example in the
link above.
Use a service or container mechanism (and its implementation) is a
developper choice. this could not be traced by php core.
A service (or container) can create an instance of class or just return
an instance of class which is allready created.
// you register the service
Services::register('databaseConnexion', new databaseConnexionFactory
('mysql', array('server', 'database', 'user', 'password')));
// and call it
$db = Services::load('databaseConnexion');
How PHP should treat the singleton ? getInstance() is just a convention.
Create a service mechanism directly in php implies that php implements
singleton model too.
--
Alban Leroux seza@paradoxal.org
Alban a écrit :
Le Thu, 19 Nov 2009 02:24:01 +0000, Jared Williams a écrit :
-----Original Message-----
From: Robert Lemke [mailto:robert@typo3.org] Sent: 18 November 2009
16:07
To: internals@lists.php.net
Subject: [PHP-DEV] RFC: Custom Factories (SPL)Hi folks,
after discussing the idea with various PHP developers I now felt safe
enough that it's not a completely stupid idea to post an RFC for it.
The idea is to add support the registration of custom factories which
are responsible for instantiating certain classes.Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactoriesI suggest that we first discuss the implications and usefulness of this
feature. In a second step I'd need to find some skilled internals
wizard who can implement it, because not being a C developer myself,
all I can offer is making suggestions and fine coffee.Looking forward to hearing your comments! Robert
--
Robert Lemke
Fluent Code ArtisanWhilst I am a fan of IoC, I don't think its desirable to add language
features just to make legacy code more flexible. Surely the route to
take is to refactor the legacy code as and when the extra flexibility is
needed.Also seems like a possible whole heap of wtf?! When a seemingly absolute
statement $a = new A(); gets mangled behind the scenes.Jared
I'm totaly agree with you Jared !
I'm a fan of IoC too.A factory can provide an object by creating an instance of a class, the
choice of the class depends of some paramters. Those parameters can be
provided directly by the programmer but also by a final user.
PHP can not simply "choose" the class to instanciate by checking class's
interfaces.What Robert Lemke wants to implement is called a "Service" or a
"Container".
You register a service and call the service instead of calling a class
directly.Let me show it in an example of session registration :
// you register the service
Services::register('session', 'sessionStoredInCookie');// and call it
$session = Services::load('session');Tomorrow, if you want change the session registration mechanism, for
storing them in a database for exemple, you have just to change the
registred service and whole application has change its session
registration method :// you register the service
Services::register('session', 'sessionStoredInDatabase');This is very well treated by Fabien Potencier in this document : http://
fabien.potencier.org/talk/20/decouple-your-code-for-reusability-php-
forum-2008?position=41 (some parts are in french)Implementing a service or container mechanism could be very simple or
very complicated. Fabien Potencier use a very complicated example in the
link above.Use a service or container mechanism (and its implementation) is a
developper choice. this could not be traced by php core.A service (or container) can create an instance of class or just return
an instance of class which is allready created.// you register the service
Services::register('databaseConnexion', new databaseConnexionFactory
('mysql', array('server', 'database', 'user', 'password')));// and call it
$db = Services::load('databaseConnexion');How PHP should treat the singleton ? getInstance() is just a convention.
Create a service mechanism directly in php implies that php implements
singleton model too.
Some language have support for IoC. See newspeak:
http://gbracha.blogspot.com/2009/07/ban-on-imports-continued.html
-- Mathieu Suen
Le Thu, 19 Nov 2009 12:06:19 +0100, Mathieu Suen a écrit :
Alban a écrit :
Le Thu, 19 Nov 2009 02:24:01 +0000, Jared Williams a écrit :
-----Original Message-----
From: Robert Lemke [mailto:robert@typo3.org] Sent: 18 November 2009
16:07
To: internals@lists.php.net
Subject: [PHP-DEV] RFC: Custom Factories (SPL)Hi folks,
after discussing the idea with various PHP developers I now felt safe
enough that it's not a completely stupid idea to post an RFC for it.
The idea is to add support the registration of custom factories which
are responsible for instantiating certain classes.Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactoriesI suggest that we first discuss the implications and usefulness of
this feature. In a second step I'd need to find some skilled
internals wizard who can implement it, because not being a C
developer myself, all I can offer is making suggestions and fine
coffee.Looking forward to hearing your comments! Robert
--
Robert Lemke
Fluent Code ArtisanWhilst I am a fan of IoC, I don't think its desirable to add language
features just to make legacy code more flexible. Surely the route to
take is to refactor the legacy code as and when the extra flexibility
is needed.Also seems like a possible whole heap of wtf?! When a seemingly
absolute statement $a = new A(); gets mangled behind the scenes.Jared
I'm totaly agree with you Jared !
I'm a fan of IoC too.A factory can provide an object by creating an instance of a class, the
choice of the class depends of some paramters. Those parameters can be
provided directly by the programmer but also by a final user. PHP can
not simply "choose" the class to instanciate by checking class's
interfaces.What Robert Lemke wants to implement is called a "Service" or a
"Container".
You register a service and call the service instead of calling a class
directly.Let me show it in an example of session registration :
// you register the service
Services::register('session', 'sessionStoredInCookie');// and call it
$session = Services::load('session');Tomorrow, if you want change the session registration mechanism, for
storing them in a database for exemple, you have just to change the
registred service and whole application has change its session
registration method :// you register the service
Services::register('session', 'sessionStoredInDatabase');This is very well treated by Fabien Potencier in this document :
http://
fabien.potencier.org/talk/20/decouple-your-code-for-reusability-php-
forum-2008?position=41 (some parts are in french)Implementing a service or container mechanism could be very simple or
very complicated. Fabien Potencier use a very complicated example in
the link above.Use a service or container mechanism (and its implementation) is a
developper choice. this could not be traced by php core.A service (or container) can create an instance of class or just return
an instance of class which is allready created.// you register the service
Services::register('databaseConnexion', new databaseConnexionFactory
('mysql', array('server', 'database', 'user', 'password')));// and call it
$db = Services::load('databaseConnexion');How PHP should treat the singleton ? getInstance() is just a
convention. Create a service mechanism directly in php implies that php
implements singleton model too.Some language have support for IoC. See newspeak:
http://gbracha.blogspot.com/2009/07/ban-on-imports-continued.html-- Mathieu Suen
That's a good idea to add support of IoC in PHP.
But i think a mechanism like spl_autoloader doesn't sounds very well.
I prefer see a mechanism like import/export, something like this :
-- file a.php --
import B
class A {
public function hello() {
$b = new B();
$b->hello();
}
}
-- file myB.php --
class myB {
public function hello() {
echo "Hello, I'm myB";
}
}
-- file otherB.php --
class myB {
public function hello() {
echo "Hello, I'm otherB";
}
}
-- file main.php --
require_once 'a.php';
require_once 'myb.php';
require_once 'otherb.php';
export myB as B;
$a = new A();
$a->hello(); // print : "Hello, I'm myB";
export otherB as B;
$a->hello(); // print : "Hello, I'm otherB";
This is like the 'use' command for class alias, at the difference that
the 'use' command works localy and it resolved at the compilation time.
--
Alban Leroux seza@paradoxal.org
This smells like metaclasses to me, just that in your RFC they are
supposed to work on a global level, not on a per class level.
Python, for example, has a magic method called __new__
, which controls
the creation of the object whenever a new class is instantiated. It
actually allows you to return a different object than the expected one.
I somehow like the proposal, but it may create havoc in some code bases.
I wouldn't really want to see new FooBar
, when it actually means a
DamnBar
.
There are also other things to take into consideration. You may want to
override this instantiation mechanism for FooBar
just in a single
class, not in all of them, which complicates the problem. You'd have to
received the scope where the instantiation is done, but even then, there
may be no way to really know which object, not class, wants to
instantiate FooBar
.
I agree IoC is necessary, but I'm not really sure this is the way to go.
... [some thinking]
At this point, in PHP, classes are global constant symbols. Allowing us
to override the instantiation mechanism would make them global variable
symbols. The below example is already possible in PHP and I believe it
already does what you're asking for (in the current RFC):
class Emailer
{}
$Emailer= 'Emailer';
class FooBar
{
public function sendEmail()
{
global $Emailer;
$emailer = new $Emailer;
}
}
Hi folks,
after discussing the idea with various PHP developers I now felt safe enough that it's not a completely stupid idea to post an RFC for it. The idea is to add support the registration of custom factories which are responsible for instantiating certain classes.
Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactoriesI suggest that we first discuss the implications and usefulness of this feature. In a second step I'd need to find some skilled internals wizard who can implement it, because not being a C developer myself, all I can offer is making suggestions and fine coffee.
Looking forward to hearing your comments!
Robert
--
Ionut G. Stan
I'm under construction | http://blog.igstan.ro/
Hi folks,
after discussing the idea with various PHP developers
I now felt safe enough that it's not a completely stupid
idea to post an RFC for it. The idea is to add support
the registration of > custom factories which are
responsible for instantiating certain classes.Here is the first draft of my RFC:
http://wiki.php.net/rfc/customfactories
Robert,
Slightly different idea, why not to generalize the way of class-load and
class-instantiation in php and make existing auto-load feature implemented
as a part of it? It should be flexible enough and allow to work with
auto-loading files and/or
factories to be called for the class instance.
Class instantiation is an important thing itself and PHP should support
certain
interface for this. So all the factories will have at least one common
interface.
Similar stuff works great in Mozilla (XPCOM) and MS' COM.
I mean IFactory and nsIFactory:
interface nsIFactory : nsISupports {
/**
* Creates an instance of a component.
*
* @param aOuter Pointer to a component that wishes to be aggregated
* in the resulting instance. This will be nsnull if no
* aggregation is requested.
* @param iid The IID of the interface being requested in
* the component which is being currently created.
* @param result [out] Pointer to the newly created instance, if
successful.
* @return NS_OK - Component successfully created and the interface
* being requested was successfully returned in result.
* NS_NOINTERFACE - Interface not accessible.
* NS_ERROR_NO_AGGREGATION - if an 'outer' object is supplied,
but the
* component is not aggregatable.
* NS_ERROR* - Method failure.
*/
void createInstance(in nsISupports aOuter, in nsIIDRef iid,
[retval, iid_is(iid)] out nsQIResult result);
/**
* LockFactory provides the client a way to keep the component
* in memory until it is finished with it. The client can call
* LockFactory(PR_TRUE) to lock the factory and LockFactory(PR_FALSE)
* to release the factory.
*
* @param lock - Must be PR_TRUE or PR_FALSE
* @return NS_OK - If the lock operation was successful.
* NS_ERROR* - Method failure.
*/
void lockFactory(in PRBool lock);
};
similar thingy can be found in COM.
In PHP terms it'd be much easier:
interface IFactory... {
/**
- @returns mixed class instance initialized with default constructor
- @except throws descendant of EFactory exception in case of errors
*/
function CreateInstance();
}
/**
- @desc nothing new in this class except its class name that can be used
for filtering exceptions in catch()
*/
class EFactory extends Exception {};
Regarding your sample, "class SystemLogger implements LoggerInterface" is
nothing more but a classic singleton. It creates
one and only one instance and always return it.
In terms of XPCOM or COM it can be created with appropriate flags used in
the factory template. See SINGLETON
attribute in mozilla sources. While the factory is a standalone instance or
static class that can only create instances or
instance of another certain class. For example LoggerFactory would create
SystemLogger instances (instance).
This is proven technology and works good for more than 10 years.
Regarding such contructs like $this->logger->log() in SomeService,
it's known that many classes are partially or wholly wrappers around one or
many instances in them.
With SomeService, one can introduce log method in it like:
class SomeService {
...
log($msg) {
$this->logger->log($msg)
}
}
and call $this->log() instead of $this->logger->log(), as it's shorter and
more readable.
But in cases when inner instance have many methods to be wrapped, such dummy
code
may waste too much space.
So I'd propropose to implement a "delegate calls to instance" feature. It
may look like below
delegate_calls($delegator, $delegatee, $interface).
For example
delegate_calls($this, $this->logger, LoggerInterface)
can be called and after that you'll call any methods defined in
LoggerInterface interface
with $this instance but in fact method in $this->logger will be called.
Such delegation would simplify sources:
$this->log('aMethod has been called.');
instead of
$this->logger->log('aMethod has been called.');
I know, __call() can be used to delegate calls too, but with this way I'd
have to intercept __call and repeat
the same method body each time I need delegation.
-jv