|
I don't get it. How would you do it?
Any chance you could describe it in more concrete terms? Like how would the DefaultComponentAdapter use a factory? For what? We had sort of the notion of a pluggable object that instantiated the objects (don't remember the name), but it didn't work. There's more logic associated to doing that than just creating an instance of a class. That's why we ended up with the adapter instead. Feature-envy, various parts of the container moved towards the factory, and the factory stopped being just a factory. The ComponentAdapterFactory is there for one reason only, to allow a PicoContainer to select a component-adapter to use when the user does not specify one. It's a completely different set of logic to doing that, for example the NanningComponentAdapterFactory introspects the component to see whether it's an aspect, a component that can get aspects applied to it, or a POJO (without intf/impl-separation). That's all different component adapters. There's no way I can put that logic somewhere else. I don't get the notion of a ComponentFactory. Isn't that a developer? How can someone other than a developer create a component? Jon wrote: "I don't get it. How would you do it? Any chance you could describe it in more concrete terms?"
Sure. How about some code? Take a look here: http://cvs.sourceforge.net/viewcvs.py/jicarilla/jicarilla-sandbox/platform/container/ here are some sample adapters: http://cvs.sourceforge.net/viewcvs.py/jicarilla/jicarilla-sandbox/platform/container/ here is a "type-3" component factory: here's a testcase that shows it works: Jon also wrote: "The ComponentAdapterFactory is there for one reason only, to allow a PicoContainer to select a component-adapter to use when the user does not specify one. It's a completely different set of logic to doing that, for example the NanningComponentAdapterFactory introspects the component to see whether it's an aspect, a component that can get aspects applied to it, or a POJO (without intf/impl-separation). That's all different component adapters. There's no way I can put that logic somewhere else. " Why not? A ComponentAdapter selection policy should be a "policy-style" object, not a "factory-style" object. The key point is to decouple your policies from the "new" keyword (to me, "factory" is about calling the "new" keyword and doing any initialization). With the nanning example, in my chosen decomposition, I would actually much rather apply the policy you desribe at container population time (since the policy that should be applied is already known at that stage). Something like AspectSupportingContainerBuilder.add(componentKey, componentClass): where you obviously will have a set of builders that reuses more code Jon also wrote: "I don't get the notion of a ComponentFactory. Isn't that a developer? How can someone other than a developer create a component?" I don't get your question! Re: the factory pattern. A factory creates instances of things. A component factory creates instances of components. I am sure there are also other possible decompositions that remove the parallel hierarchies which are probably less radical; I just haven't thought of any just yet. I wrote: "With the nanning example, in my chosen decomposition, I would actually much rather apply the policy you desribe at container population time"
Put another way, remove a lot of policy decisions from the container and encapsulate it in a helper object. You will then probably have a proliferation of different "builders" that apply different policies. So unless you add another layer of abstraction (something like policy objects), you will indeed still have sort-of parallel class hierarchies (one for each policy). But some things have been decoupled, so they will be smaller. Put yet another way, we've replaced inheritance with composition. Got it! We simply use different naming:
Pico Leo Simons But in fact we have a very similar solution! Still don't really like the term ComponentFactory though, it sounds like something that creates components (not instances of components). It's like calling something a ClassFactory, it's something that creates classes, right? So, simply put, there are no factories that creates instances of components in Pico, there are only adapters. For that reason, I don't think we should fix this issue. Maybe we could rename ComponentAdapterFactory to ComponentAdapterSelectionPolicy though, it's a bit awkward though.
Jon wrote: "We simply use different naming <snip> But in fact we have a very similar solution!".
I (still) don't think so. Implementations of ComponentAdapterFactory are tied to (specific, hard-coded) implementations of ComponentAdapter. Also, current implementations of Container are tied to specific implementations of a single ComponentAdapterFactory. Renaming them to "ComponentFactorySelectionPolicy" or anything else does not change that fact. Here's the terminology mapping as it applies to the code links I sent: Pico Me There is overlap between "ComponentAdapterFactory" and "Selector", but the latter has a much smaller responsibility. I'll "speak pico" from now on Take a look at this code: public ComponentAdapter createComponentAdapter(Object componentKey, Class componentImplementation, Parameter[] parameters) I'm saying that should always be written as container.registerAdapter( or better yet container.registerAdapter( The difference is relatively small from a user perspective but rather big from an implementation perspective (or from a power user perspective). This is because as a power user I cannot get away with simply writing a custom ComponentAdapter; I need to write a ComponentAdapterFactory as well. Furthermore, it is difficult to mix and match multiple ComponentAdapterFactories (it requires adding scoped/hierarchical containers). Truly decoupling ComponentAdapterFactory from ComponentAdapter and removing some of its current responsibilities (removing them from PicoContainer and references alltogether, in fact) is the only way I've thought of so far that changes this. "simply put, there are no factories that creates instances of components in Pico, there are only adapters." that is a Good Thing. But there's factories that create instances of adapters, and pico assumes that there are. I'm not saying adapters must neccessarily use factories; I'm saying PicoContainer (implementations) shouldn't use them either. I hope I'm making at least some kind of sense to you. Maybe Thomas explains it better @ http://lists.codehaus.org/pipermail/picocontainer-dev/2003-November/001626.html I understand.
The reason why we keep around ComponentAdapterFactories for a number of component-adapters is because the casual user should not have to worry about ComponentAdapters. In fact we initially only considered ComponentAdapter to be an implementation detail. What you suggest is to remove all registerComponentImplementation We already have a registerComponentAdapter(ComponentAdapter). It would be possible to remove all other methods, but I think for the non-casual user they make the API easier to use. Maybe we should just keep a small number of ComponentAdapterFactories around and let all power-users use registerComponentAdapter. That ComponentAdapter knows what key it has is probably one of the main differences with ComponentFactory and ComponentAdapter, the ComponentAdapter actually keeps it's state around. That the container maps it just a performance detail, an index. Jon wrote: "I understand".
good! And your decision is to keep things as-is to support the more common use cases better by default, right? Okay. Makes sense. Annoying for me, but makes sense Yeah, but it's not my decision only.
I get your point, although it's much to close to a release to do such a massive overhaul. I will try to take a serious look at the other issue though, the Adapter -> Registry thing: Is this closeable?
I think Leo's use-case can be achieved with MutablePicoContainer.registerComponent( ComponentAdapter ). As for addditional design ideas, at this point in time in Pico's life I'm not sure if its a pragmatic decision. That's the reason for the 2.0 schedule. Here we collect any ideas, that we should consider for the next incarnation.
I don't think Jon will do anything with it
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
factory creates adapter
to
factory uses adapter
The combo I like best atm is
adapter uses factory
where a factory is just that, a factory, and the adapter handles everything but the 'new' (and with non-type-3 IoC, the init and dispose). Furthermore, the container need not care or know about factories...
container uses adapter
...is enough.
In my pet container I went further and introduced many-to-many selection policy, where an adapter is associated with a selector inside the container:
Container-<<uses>>----
0..m--->SelectorSelector-
<<locates>>1------>AdapterAdapter-
<<uses>>----1..n--->FactoryThis is essentially a more generic form of a hashmap. In JDK-1.5 terms, the less generic hashmap variant is:
container<key,adapter>
Adapter has-a Factory
In Ruby terms, the selector list functions as a rich switch/case statement, and the selector is the implementation of the '===' operator.
In pseudocode (fragments):
Container.get(arg):
for each selector
if selector.select(arg)
return adapters.get(selector).get()
return null
SingleUseAdapter.get():
return factory.newInstance()
SingletonAdapter.get():
lazyInit()
return instance
Factory.newInstance():
return new Something
Much cleaner. IoC.