On 15/02/2015 20:20, Patrick Schaaf wrote:


Am 15.02.2015 21:05 schrieb "Rowan Collins" <rowan.coll...@gmail.com <mailto:rowan.coll...@gmail.com>>:
>
> This sounds to me like you should just be using the Singleton pattern,

Of course this is singleton under the hood.

> // Now wherever in the code you want the default instance, just use this:
> $value = MyRedis::singleton()->get($key);

You can surely see how this is more readable / easier to write:

$value = MyRedir::get($key);


Actually, no, I find that harder to read accurately - there is no clue there that there is actually a singleton under the hood, and that this is actually an instance method in disguise.

For writing, it saves, in this case, 13 characters; change the method name to inst(), and that difference goes down to 8 characters.

And if you use it lots of times in succession, you wouldn't even need to call the accessor every time:

$redis = MyRedis::inst();
$foo = $redis->get('foo');
$bar = $redis->get('bar');
// etc

In that scenario, you've had to write one extra line at the top of the method, and the rest of the lines are probably shorter (if the variable name is more than one character shorter than the class name). Plus, you have the bonus of being able to use an injected connection later.

> The nice thing about an explicit Singleton is you can migrate to Dependency Injection (call "$redis = MyRedis::singleton()" and start passing the instance around,

I _can_ do that with my redis class, where I need it, by calling a method MyRedis::link() which just returns $this. But the places where I need that are rare.


You may be able to do it with your current implementation, but how do you propose to do it with an invisible singleton property implicitly created by __constructStatic?

> ... or to a cleverer factory / service locator (store more than one instance in different static variables or a keyed array, to connect to different stores for different purposes).

This i do with subclasses, where the subclass define suitable static protected properties that guide the connect logic (which sits in the baseclass). I have a global redis, a local redis (local to the host the code runs on), a volatile redis (global, but does not make prersistent dumps), and so on. Calling code ready red_global::this(), red_volatile::that(), and so on. You don't get it better readable (and greppable) as that.


OK, but you need a new subclass every time, not just a new method, or new parameter; that limits your options. For instance, you can't dynamically create instances based on configuration of a reusable library, which could be as simple as adding an optional parameter to a standard Singleton:

class MyRedis {
private static $instances;
public static function inst($type='default') {
global $config;
if ( ! array_key_exists(self::$instances, $type) ) {
self::$instances[$type] = new self(...$config['redis_options'][$type]);
}
return self::$instances[$type];
}
}


Any function that already uses the "$redis = MyRedis::inst();" pattern can then quickly be changed to "$redis = MyRedis::inst('volatile');" and continue to work fine.


> Making static calls implicitly access a singleton seems like it would make code harder to read, and harder to extend,

I don't understand. It's the best to read to me.


OK, we'll call that one a matter of opinion.

And the best to extend - I just make another subclass.


"Extend" was perhaps not the word I should have chosen; I was thinking of "extending the use of the class beyond the current coding pattern". By implementing one specific use case as a magic method, you make it harder to do anything other than that one use case; or, you end up creating a whole set of magic methods and features, which are then no easier than just implementing the whole thing by hand.


I deliberately didn't go into details of the arguments against the Singleton pattern in general in my last e-mail, because I was comparing your "magic" code to a normal Singleton. However, those criticisms are out there, and adding a feature to the language specifically in order to support Singletons, in a very limited way, will be considered by some as encouraging bad practice.

Regards,

--
Rowan Collins
[IMSoP]


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

Reply via email to