Hello matthew, i would subscribe to such a component based registry thing :-) ok its not up to me, but i think its a very good mixture between DI and simplicity and especially the Controller component would really benefit from the more flexibility. :-)
On Tue, 13 Jan 2009 16:38:48 -0500, Matthew Weier O'Phinney <matt...@zend.com> wrote: > -- Benjamin Eberlei <kont...@beberlei.de> wrote > (on Tuesday, 13 January 2009, 06:11 PM +0100): >> great post ralph! this is a step into a brighter future ;-D >> >> my two cents though. >> >> 1. having __construct(array $options); is cool from a simplicity point > but it >> hides dependencies, since in an array you couldinclude ANYTHING. Most >> components also don't require the dependencies to be set in constructor, > they >> take all sort of options and set them but don't raise an exception when > a >> depdenency xyz misses. >> >> When you have a sensible default depdenency this would make sense > though. > > It would be the job of the constructor to ensure that required options > are passed, then -- or to provide defaults (potentially through an > overloaded accessor that lazyloads a default). > >> ezcComponents uses constructor struct objects for configuration. You > would have >> an object Zend_Controller_Config which enforces some variables and is > given to >> the constructor. I like this alot, since objects always allow for more > checks >> on variables than arrays. > > However, this adds another dependency to using the objects -- you then > need a value object before you can even use the object. If we allow > either an array or a Zend_Config object, we give more flexibility in > userland code for how the options are retrieved and passed to the > constructors (they could be subtrees of an application-wide > configuration object, or a serialized JSON array stored in memcached, > etc). > >> 2. component registries are a great thing IF they are not singletonized. > They >> allow for type checking and consistency checks where the Zend_Registry > does >> not. > > If you look closely at Ralph's example, you'll notice it wasn't static. > :) He and I have discussed this a fair bit, and the idea is that > factories and other "gateway" classes would push themselves and/or the > registry down into the subcomponent objects. > >> You could always make a container go into Zend_Registry to make it > global, but >> this should be optional, and pleeease let us just forget the singleton >> antipattern. :-) >> >> If component registries are used we should make sure that all > dependencies are >> overwritable with them, for example the PluginLoader of Zend_Controller > for >> helpers is hardcoded into the front controller. The component registry > should >> include all objects that might impliciltly be set deep in the object > graph of >> the component. That would be super! >> >> 3. Implicit dependencies and work in the Constructor >> >> Dependency Injection is also about not having implicit dependencies or > much >> work in the constructor. We should evaluate all components based on > this. >> Having a "new Something()" inside an object constructor is evil, aswell > as >> doing lots of stuff that you cannot influence. > > I've been pushing the setOptions/setConfig paradigm for a while, and it > works really well with DI. Your constructor then passes the options on > to setOptions() which attempts to call setters named after the keys. The > result is that it allows you to push your dependencies in at > instantiation -- leaving the constructor needing to simply check for > required settings (if any) only. > > >> On Tuesday 13 January 2009 16:55:57 Ralph Schindler wrote: >> > Comments inline: >> > > The better solution is dependency injection, and one facet of this > is >> > > removing >> > >> > I disagree (if you are talking about DI as a container model) >> > >> > > explicit references to Registry/global items from source code. This > is a >> > >> > I agree. >> > >> > > feature the ZF has yet to include but Bradley Holt has ressurected > the >> > > idea in the form of Zend_Container ( >> > > > http://framework.zend.com/wiki/display/ZFPROP/Zend_Container+-+Bradley+Ho >> > >lt ) and I really really hope it, or an evolution of it > (Zend_Application >> > > plugin?), >> > >> > I agree >> > >> > > makes it into the library. The last time something like this was > proposed >> > > it was bogged down by ever expanding requirements and complexity - >> > >> > True, as DI Containers tend to get. >> > >> > > simpler is better. >> > >> > +1000 here :) .. Now onto the explanation. >> > >> > To sum it up, I do think we need a solution here that will fit the >> > framework, specifically our components- framework wide, as well as >> > application wide. >> > >> > But, DI Containers (to me) have always introduced a level of > indirection >> > that is extremely uncommon for PHP. There are two ideas, I would love > to >> > see explored, and both of them would be rooted in what I would call a >> > "component development convention", but only at the most forward > facing API >> > layer. >> > >> > First, the __construct($options = array()) {} convention for the most >> > forward facing component API constructor adds a level of consistency > that >> > makes each and every component look and feel similar in style. This > would >> > makes it easy to move from component to component and have a good >> > understanding of what is expected. Zend_Form does this, and to me, it > make >> > for the most flexible of components. In each case, $options can be a >> > Zend_Config object, and assoc array of configuration values which can > then >> > be pushed down into the varios setXXX() methods, or $options can be > the >> > single most well used value, (if this were a Zend_Service component, > it >> > could be the API key). >> > >> > I believe this convention is very much used in Solar and its becoming > more >> > popular in ZF as we see more components hit the library. >> > >> > Second, I propose we look at creating a Registry class that can be > extended >> > (maybe its just a glorified ArrayObject), that can be used and defined > by >> > each component. This would allow components to have a *Component > Level >> > Registry*. How would this help? Well, instead of there being a > dbAdapter >> > key in the Application space registry, Zend_Db_Registry would contain > a >> > getDefaultAdapter() method. It might also have a getAdapter($name) > method. >> > Also, now the Zend_Db component can manage is component level registry > and >> > made the best decisions on how to lazyload and expose its individual > pieces >> > to the application layer, or user layer. >> > >> > For Zend_Controller, the api might look like this: >> > >> > >> > Class Zend_Controller_Registry >> > { >> > public function getFront(); >> > public function getDispatcher(); >> > public function getRouter(); >> > public function getRequest(); >> > public function getResponse(); >> > /* .. Others .. */ >> > } >> > >> > Again, this delegate the responsibility down into the actual component > of >> > wiring dependencies, and either throwing an exception or lazy-loading > when >> > a non-explictily-set wiring is needed. >> > >> > This also alleviates the need for a god-like container to find, or be > given >> > a wiring diagram (which could become expensive for instantiation of > every >> > PHP object needed) to be able to work within all components and > between all >> > components. ALSO (if this is more of a convention > Zend_Controller_Registry >> > extends ArrayObject), this would reduce the intra-component > dependencies. >> > >> > Also, PHP is not java, so containers need to be rebuilt on each > request, >> > whereas in Java the container might need to be built once and put into >> > resident memory for all requests. >> > >> > Those are two ideas I wanted to float ever since hearing of DI. Im > sure >> > this will turn in to a blog post, since its more of a how does DI > affect >> > PHP sort of question. >> > >> > Let me know what you think. >> > >> > -ralph >> >> -- >> Benjamin Eberlei >> http://www.beberlei.de >> > > -- > Matthew Weier O'Phinney > Software Architect | matt...@zend.com > Zend Framework | http://framework.zend.com/