Registry vs Static DB

I was wondering which would be better to use. This is considering that the only thing I want to call (for now) is the Database Connection.

Static DB - Singleton PDO connection.

class a
{
	public function __construct()
	{
		// Getting the connection for a random class,
		// This would be an obscure class not part of the flow of the system
 		// Which is hard to explain, maybe AJAX type stuff.
		$this->DB = DB::Connect();
	}	
}

Registry - Referenced non-static Singleton PDO.

class a
{
	public function __construct()
	{
		// Getting the connection for a random class,
		// This would be an obscure class not part of the flow of the system
 		// Which is hard to explain, maybe AJAX type stuff.
		// Assuming Registry was already Set
		$this->DB = Registry::Get('DB');
	}	
}

I know you can statically call the PDO but I want a DB object to handle the connection and quite a few other things.

Question about a Registry:
Do I need to return the DB object as a reference inside the registry? Because I thought all objects were passed as reference by default… So

function &connection($link)
{
  return $link;
}

Is that useless?

Hi…

It’s not actually that bad. The top level code doesn’t usually have a lot of inheritance, and the lower level code doesn’t have a lot of dependencies.

A base controller for example:


class EnterDetails extends Controller {
    function __construct($request, $session, $alerts, $customer_base, ...) {
        parent::__construct($session);
        ...
    }
}

Changing dependencies is a significant event and you want the code to shout it loud and clear. That “parent::__construct($session)” line is a small price to pay for me.

yours, Marcus

Hi…

I’ve obviously upset you, for which a thousand apologies. That certainly wasn’t my intention :(.

You are clearly highly knowledgeable and were honestly trying to help. I certainly don’t want to disuade you from doing that.

But then, how do I say that I think you are wrong in this case?

What I was trying to say (badly) was that I’ve been down the very road you are recommending and it gets ugly. In the process the whole industry missed a much better turning in the road. It’s took nearly five years to correct this (the PHP community gets it’s news five years behind that). It’s really subtle and requires the negative experiences.

I certainly missed the turning, waving as I went…:eek:

https://www.zend.com//code/codex.php?ozid=865&single=1

I mean, what was I thinking? The code’s awful as well. I’m really wincing looking at it.

Never afraid to tour my own personal lecture circuit, I did it again…:rolleyes:

http://www.phppatterns.com/docs/design/the_registry

At least this time I’m more aware of the downsides and the tone is a little more contrite. Even the code is not so bad, although the test naming is awful - “testSingleton” - arggh!

So I honestly think I’m giving bad advice.

And what about your second test? The one where the database is not there and you want to throw an exception?

This affects mainly the code that uses the Singleton. How do I start each test is a known state if a previous test has set a bunch of stuff up for me? My tests have become interdependent.

Yes.

No, you got it.

It’s very rare that a new solution to a problem in programming is superior across the board. I can’t think of any other example. In this one case only though, yes I’m saying this is the one technique to rule them all.

At least for now.

yours, Marcus

Having to call methods on an object in a specific order before it works as intended always seems wrong to me.

Off Topic:

edit: I have no idea why I included the "Hi… " when i quoted lastcraft. Looking at it now is kinda funny. Sorry :stuck_out_tongue:

Bingo - I hate methods specifically for injecting required dependencies. I prefer lastCraft’s approach where you supply the dependency for the method when it’s called. That’s given me an idea for another topic… back in a bit

Off Topic:

That mentions “Object not fully initialized after the constructor finishes (watch out for initialize methods)”

Well then what’s the best way to handle objects where I want to allow inheritance. I need specify the constructor with all arguments and call parent::__construct with all args. Seems horribly messy, especially for maintainability: What if I add a new dependency to the parent… I now need to change the class definition for all children as well.

Perhaps init() should be called externally… but then the object needs this called before other methods to make it work.

Maybe some days DI fans unleash war against global everything? I really do not understand it.

The thing is, it’s all a matter of scope isn’t it. If you’re the only coder on the project - you can do whatever you like. If it works, and you can bear the burden of your creation, write it however you want.

Thanks for the replies!

Perhaps I should just force myself to require an actual class an instantiate it, it seems in the long run this won’t be worth the trouble, ie:

class a
{
    public function __construct()
    {
        require_once('libs/DatabaseObject.php');
        $this->DB = new Database() 
    }    
} 

As for the DB connection, it would be a non-static singleton (or just allow once instance of construct), sorry I’m not good with the lingo… I had read some more of one of my books and it seems to suggest Registry should be used very sparingly and not in your main application flow when possible.

We do not claim anything against DI. It’s you who reduces programmer’s craft to single technique.

I don’t that think was his intent. He gave several good reasons why to avoid statics. Statics, by virtue of the name alone, implies, limited, strict static coding techniques.

Dynamic programming techniques allow for easier refactoring, testing and other best practices, not no developer can dispute, IMO.

Don’t take it personally, take it as advice, learn from others mistakes, you don’t live long enough to make them all yourself. :slight_smile:

Cheers,
Alex

A singleton is virtually untestable

For most cases:

if ( get_class( DB::Connect() ) == 'my_db_class')
   echo 'Test passed';

they’re both static which makes them global in scope
Well, I repeat myself here, but we have global variables, global constants, global builtin statements and functions - that’s all OK, but global objects NOT. Maybe some days DI fans unleash war against global everything? I really do not understand it.

you are giving bad advice
We do not claim anything against DI. It’s you who reduces programmer’s craft to single technique.

Hi…

Back in 2004:
http://www.c2.com/cgi-bin/wiki?SingletonsAreEvil

More recently:
http://misko.hevery.com/code-reviewers-guide/

My personal experience over the last dozen years has mirrored the development of these patterns.

I started with the Gang of Four book when it was the only patterns book published. I wrote some singletons. I then rewrote a big bunch of code in taking them out again.

Armed with unit testing and enterprise patterns next time around, I went for the registry. Unit tests were fine, but people didn’t like working with the code. It was spooky, with things happening from a distance. People find Quantum Mechanics hard for the same reason. Debugging an integration test failure was a complete pain. I had to factor them out again.

Service Locator was the next effort. Not so bad. Testing was a bit labourious (mocks returning mocks), but you could guarantee the objects would be created properly. You still have a large footprint to examine when reading the code though. Once you pass the Locator into something, it has access to every major object in the system. You have no choice but to read the code very carefully. If something holds a reference to the locator, then print_r() produces a gallon of output. People explore code with print statements, so disabling them has a cost.

These patterns turned out to be dead ends. Dependency injection turns out to be easier and cleaner in just about every way. Mocks are passed straight in and only affect the local object. The code footprint is just the class itself, plus anything you pass in (which you can easily fake for testing/debugging). Not only that, I was writing less code too.

If your app is small, just pass things in from above with a few factories here and there. You are doing dependency injection without needing a special tool to do it. If you are a framework author or your app is large (20K lines plus) then a DI container will be very useful. It doesn’t matter which one you choose, they are so decoupled you can swap them around.

To those posters saying Singleton is OK or Registry is OK, have you tried dependency injection in a real project? I rather suspect you haven’t. Sorry, but I honestly think you are giving bad advice.

yours, Marcus

Registry vs Static DB - much of a muchness, they’re both static which makes them global in scope. Of the two, registry is the more useful. As lastcraft said though, it’s better to pass dependencies in the constructor, or to the specific method that requires a connection.
Alternatively, you could work with a Dependency Injection container/framework

As with everything, you will have those against Singleton classes. I for one am not against it, so I would recommend the first option.

And yes, as of PHP5 all objects assigned to a variable are passed by reference.

JREAM: If you do not plan to write new Zend Framework or some CRM, both static solutions are suitable. Registry is a better one.

Hi…

Neither :).


class A {
    function __construct($connection) { ... }
    function doStuff() { ... }
}

…or better…


class A {
    function __construct() { ... }
    function doStuff($connection) { ... }
}

Both Singletons and Registries are problematic. A singleton is virtually untestable. A registry has issues when you try to track down a bug - any part of the code could have messed with your registry.

yours, Marcus