http://www.potstuck.com/2010/09/09/php-dependency-a-php-dependency-injection-framework/
well, not much more to say than that, except that this one uses Reflection rather than wiring files…
http://www.potstuck.com/2010/09/09/php-dependency-a-php-dependency-injection-framework/
well, not much more to say than that, except that this one uses Reflection rather than wiring files…
Comments should not be code and doing so is going to lead to trouble. Creative though…
I don’t know why everyone is obsessed with dependency injection containers. I have never felt the need for them in PHP. Just make a basic factory function or simple service locator. There’s no need for such complexity in PHP applications.
Hi…
Nope.
If the locator is passed into the other objects within the buggy code, then any of the dependencies could also be in error and I have to dig into the class and test both theories at the same time. With the construction separated from the buggy code everything has happened up front.
I also don’t need to mock the locator in the unit tests.
Nope. If a locator is passed into an object I have no idea what it’s dependencies are. I have to read the code. With DI I read the constructor signature of the code I’m in. That’s usually it.
This could get silly. I think you should try it.
Er…I hardly ever use Java. Guess again.
Nope. I’ve written registries and service locators galore. Never again. DI is simpler with a lot less coupling and a lot more potential for automation. It’s a lot nicer.
I feel I’m in the same position as when I was promoting unit testing and then mock objects. You have to try it.
Uh? I don’t know who are you arguing with?
yours, Marcus
Indeed, the reflected classes, methods and parameters are cached. Indeed, it’s only one type of object. But I was trying to show the difference between new Foo( $bar ) and $foo = new ReflectionClass( ‘Foo’ ); $foo = $foo->newInstanceArgs( array( $bar ) ); That’s the thing I was trying to show, nothing more, nothing less.
I was planning on doing that later, actually, as I too want to see how much slow it is in “real-life” usage. It should be interesting either way (and thanks for those links!)
True… If everything your application does in its limited lifetime is spawning objects. I don’t know how your applications work, but mine don’t take up the most time in constructing classes, but instead in doing calculations, querying the database, showing data and stuff like that. The fact that newInstanceArgs vs new $foo is twice as slow, doesn’t mean your application will be twice as slow. So, no, 30 vs 70 requests is utter non-sense, and you know it.
That I can agree on. I accept the (from my view limited) performance impact and slightly increased initial complexity to make my life easier, and to make sure I’m spending less time debugging. If you’re fixed on having optimal performance, that’s great!
There is a linear path either way. If you request the object from a locator or factory, you know what you’re getting. You still have to go elsewhere to see the dependencies - either to the factory or to the DIC “wiring”. There is no difference.
That depends quite a bit on how you set it up. In a service locator/registry/factory, you can request the object - like “getRequest()” etc. It’s no more hidden than having dependency wiring in a separate location from where you instantiate the object. Again, essentially the same thing. You’re just saying you prefer reading dependency wiring code to factory code. Either way, you have to look elsewhere to find dependencies if you run into issues.
You are assuming quite a bit about architecture here. Factories don’t have to be overridden with inheritance. There also don’t have to be multiple factories at any given time - there could only be one. Perhaps you’ve been looking at too much Java (No thanks on looking at Swing!) :). I setup my own code to use a Kernel, which is like a Service Locator/Registry/Factory all in one. It’s a single central object that can have dynamic callbacks added at runtime. If you need to add a new factory method, do it in the setup file. If you need to override one, same.
I personally don’t think inheritance is a good solution for code re-use, and it is certainly not flexible (as you have noted). I think the issue here is you have encountered factories you didn’t like that left a bad taste in your mouth. Design Patterns are generic and flexible enough that they can be combined and implemented in many different ways. Thinking strictly in design patterns almost always gets in your way. I have often found that when I come up with a creative and flexible solution to a problem, it almost never exactly fits into a single design pattern, but is instead a combination of many with a slightly different implementation. I just do what is most helpful and practical in the real word.
So what you’re saying is… Your dependency injection container is more than twice as slow. And that’s only using one type of object, so reflection is likely cached and re-used instead of reflecting on the object every time. You can’t get realistic numbers running benchmarks like this, and you know it.
A more realistic test would be 5-40 different types of objects per request, and using something like Apache Bench or [URL=“http://www.joedog.org/index/siege-home”]Siege to see how it will actually affect your ability to serve webpages to visitors. If you are intentionally selecting a programming method that you know to be at least twice as slow, that may mean you are settling for something like 30 req/s instead of 70 req/s. It’s only going to matter to you when it counts the most.
Like I said, it’s a trade-off. You choose to accept the performance penalty and increased complexity for making your life a bit easier, I do not.
Also I forgot to mention, using comments which can break the application when removed/modified feels very wrong to me!
You’re the second person to say that to me this week, so I got annoyed and decided to put it to a (naive) test. My own Dependeny Injection Container takes approximately 27.4s to create the same object a million times. PHP itself (new Foo( isset( $bar) ? $bar : new Bar( ) ) ) does it in 11.7s. Using the Zend Framework Registry class (new Foo( Zend_Registry::get( ‘bar’ ) ); took 71.5s.
Performance is not the problem: the thought that Reflection is slow is the problem, because it isn’t. 28s to create 1.000.000 objects isn’t bad. If you’re creating more than a hundred, I think you might have other problems to begin with
That said: the benefits of using a Dependency Injection Container are making my life more than just a “smidgen” easier.
Don’t think that’s new a new idea. Someone posted one here (probably a year and a half ago or more now) which did exactly that, which I used a a reference point when making my own container
edit: The previous one was better too because it used type hinting to work out what needed to be passed.
e.g. __construct(Database $db) {}
I also found a flaw in the solution: Where more than one instance of a specific object is needed, it can’t be done. What I do now is have a minimal wiring file which contains entries only for these edge cases. Everything else is worked out using reflection.
edit2: found the topic I was thinking about: http://www.sitepoint.com/forums/showthread.php?t=528808&highlight=dependency+injection
Well you could say the same about MVC, ORMs, even OOP.
For DI, “just a smidgen” depends ( ;)) on the scale of the project and how much it is utilised.
There’s always a trade-off. In compiled languages like Java, DI containers are popular because of that reason, AND the fact that there is effectively no penalty due to the JVM and/or compiled nature.
In PHP, objects need to be reflected and those dependencies have to be figured out at run time on each request, for each object loaded. Even if you get to a point where you can hand-wire all your objects to prevent reflection, as soon as someone adds something new you have the same problem again. For me, it’s a trade-off that’s not worth it - making my life just a smidgen easier is not worth the performance penalty required.
Hi…
It’s not about easier object construction, that’s just a pleasant side effect. It’s about passing all dependencies. This means you only have to deal with the code you can see.
Any problem is either with the code you are looking at (in which case mock objects will sort you out at the testing stage) or one of the dependencies misbehaving (a print statement around thereturn value will reveal this). In the former case fix it, in the latter case go to the dependency and repeat. A linear path to the problem.
If you pass in a ServiceLocator/Registry any problems you find could be just about anywhere in any object in the locator. You have to read a lot more code and the search path is more tree like.
Yes you can use a bunch of raw factories, builders, etc, but DI tool will radically reduce the numbers of them. It also means you don’t have to subclass a log chain of factories when you override something in a framework. If you want an idea of what this tedium can be like, have a play with the early versions of Swing (the Java GUI toolkit).
DI is one of those things that has to be experienced I guess.
yours, Marcus
I disagree. It makes life so much easier to delegate all object creation to factories which can just work without modification no matter if the dependencies change between objects.