Singleton vs Registry

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
thecowboy
Forum Newbie
Posts: 3
Joined: Wed Nov 02, 2005 10:38 am
Location: Canada

Singleton vs Registry

Post by thecowboy »

I am building a framework, and I am trying to decide which route to take.

In the past I have set up objects that are reused often, like a database class for instance, as a singleton. That way it is only instantiated once, and is only actually instantiated if it needs to be used. However, I have also been experimenting with building factories to return the object depending on a setting in a config file. So, this means extra processing every time the database is instantiated.

This now lends me to think that a registry class might be a better alternative, instead of having all these singletons. The object would always be instantiated, but at least the processing of the factory would only take place the one time.

Another though. Wouldn't the registry class be easier to keep track of, especially with debugging?

I'm really interested to hear your input. I am just learning about this all alone in the dark.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Re: Singleton vs Registry

Post by Christopher »

thecowboy wrote:This now lends me to think that a registry class might be a better alternative, instead of having all these singletons. The object would always be instantiated, but at least the processing of the factory would only take place the one time.

Another though. Wouldn't the registry class be easier to keep track of, especially with debugging?
Yes, yes, yes ... Registry! You have learned the hard was some of the problems of the Singleton. There are a very few places where Singleton makes sense, but you should really know that you want/need it.

A Registry allows you to invert dependencies and inject object into your classes with a standard interface. It is testable and mockable.
(#10850)
thecowboy
Forum Newbie
Posts: 3
Joined: Wed Nov 02, 2005 10:38 am
Location: Canada

Post by thecowboy »

Well thanks for the validation. At least I knew enough to question it.

It does make sense for the registry to be a singleton though, now doesn't it?

I suppose this post should have been more accurately titled Singletons vs Registry...
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

The Registry doesn't need to be a Singleton. If you are going to access it statically throughout your application then it can be a Singleton but then you have the problems of using a static. I prefer to have a Front Controller pass the Registry object to the Action controllers. I just pass it through so it is a true object. I know others like to use statics ... that preference is up to you.
(#10850)
User avatar
feyd
Neighborhood Spidermoddy
Posts: 31559
Joined: Mon Mar 29, 2004 3:24 pm
Location: Bothell, Washington, USA

Post by feyd »

I say avoid statics at all costs. Statics are a lazy way of passing the information, just as ob_start() is a lazy way of getting rid of (hiding, actually) "headers already sent errors."
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

Having the Registry as a singleton is very common, though it's not the best of practices. I could use two or more Registry instances in an application since it often counts as "Global" data and there's little point handing a Registry with a set of, say configuration objects, to a family of classes which only use a collection of Line objects. Having too many objects spread across application areas where they are never intended to be used isn't always a good idea.

Notably, a Registry should just be the same one (or two) instances always. This is often the Singleton motivation, but you can do the same by watching your startup logic (only create the one Registry) and then using type hinting to ensure other classes are passed a Registry instance correctly. Passing as parameter also avoids littering your source code with the classname of the Registry which can cause lots of editing down the line for reuse.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Exactly. This is one confusion about the Singleton. Usually when you only want one copy of and object -- you just only create one. That's the norm.

With a Front Controller and Registry it becomes pretty easy to not use Singletons because you put objects into the Registry before dispatch and then use them. It is a structural solution. You are creating a structure where you don't need a Singleton ... which is one of the goals.
(#10850)
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

Would it be feasible (and wise) to then take that theory a further step and not use a registry, either?
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

You could - in the Zend Framework you technically do not require a Registry, since the Front Controller can store a list of named objects to be passed to the Dispatcher and Action Controllers. This is sort of a hidden structure though - it's possible because the Action Controller has no defined Registry dependency and the Controller is easily subclassed so you can assign the parameter objects to private fields (one of the advantages of having an Application specific Action Controller subclass).

In most cases, having a Registry is not a problem. Once it follows a predictable interface it can be passed around like any parameter value. I suppose the danger is simple overuse. A Registry is commonly accessible from lots of places. If you're not careful it can break the separation between application layers - for example if you stick both a Session object and a User object into a Registry, and then pass it to the View (where User data is needed), it's possible a template author could misuse sessions. That's not too far fetched considering web designers and developers may not be from the same team or even company...
User avatar
Jenk
DevNet Master
Posts: 3587
Joined: Mon Sep 19, 2005 6:24 am
Location: London

Post by Jenk »

That was my thoughts.

I was also curious in what the difference between:

Code: Select all

$data = new DBObject();
$registry->add($data);
$someObject = new SomeOtherObject($registry);
and just plain old

Code: Select all

$someObject = new SomeOtherObject($data);
I can understand using the registry as a container for many objects, should there be a dependency on all those objects, maybe.

Thus far I've not really needed a registry, nor singleton, as I haven't found a justifiable use for either over just passing the required dependencies between objects.

Perhaps if the chain of command gets long enough, and let's say for example, the 5th tier needs an object that is not needed by the 2nd, 3rd, nor 4th tier - but those tiers also have dependencies not required elsewhere, a registry would be good to pass around.

I think I just answered my own question..
User avatar
Maugrim_The_Reaper
DevNet Master
Posts: 2704
Joined: Tue Nov 02, 2004 5:43 am
Location: Ireland

Post by Maugrim_The_Reaper »

I can understand using the registry as a container for many objects, should there be a dependency on all those objects, maybe.
Both examples are equally valid - both offer a means of injecting objects into new objects. The Registry is more of a container though, and it ensures that the objects it holds are variable - no strict control over what must or must not be added. In a way it's a Parameter Object, a common refactoring to combat the long parameter list code smell. Not the exact same, but it bears a resemblance.
I can understand using the registry as a container for many objects, should there be a dependency on all those objects, maybe.
A Registry doesn't know or care about what objects (as if can't also hold scalars ;)) it contains. It's just a dumb store other objects use. The only piece of coupling between Registry and the user Objects should be the interface, and likely a retrieval key name. That's all. If the user switches on completely new objects under an identical key, so long as they follow the same interface the other application code won't notice the difference. The registry isn't a requirement - it's just a simple and neat way of simplifying how objects interact with and rely on their dependencies. It's part of a wider subject - Dependency Injection.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Maugrim_The_Reaper wrote:You could - in the Zend Framework you technically do not require a Registry, since the Front Controller can store a list of named objects to be passed to the Dispatcher and Action Controllers. This is sort of a hidden structure though - it's possible because the Action Controller has no defined Registry dependency and the Controller is easily subclassed so you can assign the parameter objects to private fields (one of the advantages of having an Application specific Action Controller subclass).
Yes ... ZF has become a bit of a mess I think, in that they have sacrificed purity for features too early in the process. I think keeping it simpler through 1.0 would be a better choice. Several parallel system have crept into the codebase e.g. static Registry, injected Registry object, injected "named" object, etc. But they are pleasing everyone! ;)
Maugrim_The_Reaper wrote:In most cases, having a Registry is not a problem. Once it follows a predictable interface it can be passed around like any parameter value. I suppose the danger is simple overuse. A Registry is commonly accessible from lots of places. If you're not careful it can break the separation between application layers - for example if you stick both a Session object and a User object into a Registry, and then pass it to the View (where User data is needed), it's possible a template author could misuse sessions. That's not too far fetched considering web designers and developers may not be from the same team or even company...
It is my opinion that having to pass the registry reduces its global nature and forces the programmer to choose where they want to expose that interface/functionality. It the long run I believe that will produce more modular and testable code than being able to access the Registry from anywhere.
(#10850)
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post by Christopher »

Jenk wrote:Thus far I've not really needed a registry, nor singleton, as I haven't found a justifiable use for either over just passing the required dependencies between objects.

Perhaps if the chain of command gets long enough, and let's say for example, the 5th tier needs an object that is not needed by the 2nd, 3rd, nor 4th tier - but those tiers also have dependencies not required elsewhere, a registry would be good to pass around.
In some ways I think it is more an artifact of certain architectures -- specially controller architectures. If you find that all your "actions" need request, response, config, session, outer view, etc. objects then you gravitate toward a solution to hold all of them and make them available to your "actions."
(#10850)
Post Reply