[with corrections]
Stephen McConnell wrote:
Berin Loritsch wrote:
Using aliteration here...
Perhaps a Portability Problem P[r]oliferated by Particular Past Practices?
;-)
Seriously, I can tell that Stephen is trying to raise an issue that he feels
strongly about. I don't want to ignore them, but I am having problems
understanding his point.
My son was saying exactly the same thing to me yesterday - but we sorting t[h]ings out at about 4:15 in the morning!
So, this is my attempt at restating what I *think* he may be getting at.
Transient components vs Singleton components --------------------------------------------
Transient components return a different instance each time you ask for them.
Pooled or not, that is how the container treats these components. Is there
a potential issue here? Yes. In fact, it is already a known issue. It has
to do with the policy of retreiving and using the components. Let us assume
we have a Singleton component named SinglePipeline and a pair of transient
components named Input and Output.
The known issue is demonstrated by this code:
class SinglePipeline implements Pipeline, Serviceable, Disposable { private ServiceManager manager; private Input in; private Output out;
public void service(ServiceManager manager) throws ServiceException { this.manager = manager; in = (Input) manager.lookup("in"); out = (Output) manager.lookup("out"); }
public void dispose() { manager.release(in); manager.release(out); manager = null; }
public void process(Properties withParams) { out.setProperties(withParams); in.setProperties(withParams); in.setOutput(out); in.execute(); } }
As you can see, these transient components are held for the life of the
singleton pipeline. This is a known problem, and affects frameworks like
Cocoon.
OK.
Just for clarification - the above issue is related to the fact that the pipeline is making lifestyle assumptions about the se[r]vices it is using. These lifestyle assumptions are not declared in the service directive - and and as such - the pipeline is a wreck simply because it has bee supplied with services that did not match the semantic assumptions of the pipeline impleme[n]tation.
If my understanding is correct - what you are saying is that lifestyle is a property of a dependecy.
However, this is not pooled component specific.
Well clearly you have just demonstrated a case where this is an issue in a singleton abstraction. Which suggests that this is an aspect of a dependency.
Now, if the component was rewritten like this:
class SinglePipeline implements Pipeline, Serviceable { private ServiceManager manager;
public void service(ServiceManager manager) throws ServiceException { this.manager = manager; }
public void process(Properties withParams) { Input in = null; Output out = null;
try { in = (Input) manager.lookup("in"); out = (Output) manager.lookup("out");
out.setProperties(withParams); in.setProperties(withParams); in.setOutput(out); in.execute(); } finally { manager.release(in); manager.release(out); } } }
We regain a system that is used as the components were *intended*. Whether
pooled or not, the transient components are used as transient components.
There is a known disconnect that components are not aware of the implementation
details of how a particular component type is intended to be used. In fact,
in some cases it might very well depend on the implementation of the component,
and not the type of component. I have seen examples of both of these.
If I understand correctly - this is an example of a coding pra[c]tice the negates the necessity to express and assumption relating to lifestyle within a dependency. I.e. the impl[e]mentation descri[b]ed above [is] lifestyle independent.
I don't think this is what Stephen is getting at, although it might be part of
the picture.
I'm learning as we go.
Back to the Pooled Problems
---------------------------
Some of the problem I can tell has to do with the Resettable
interface. The fact that Resettable/Recyclable etc. is not part of the
Framework interface means that we can't easily switch out pooling
implementations at will. Even if we make the pooling implementation backwards
compatible (as is the case with MPool), should another pooling implementation
come along, how do we make sure that the component gets back to a usable state?
Yep - that is the issue I was driving at.
I think what you are getting at, Stephen (sorry if I sound like I am picking
on you), seems to be the predictability of pooling semantics--regardless of
implementation.
Don't worry about me - its the specification of behaviour and assumed semantics that we are picking at ..i.e. in the context "predictability of pooling semantics".
In essence, it is not so much a problem if we have a simple method that the
container calls to let the component know it has to clear out any state
information--it is that there is no official standard for it.
Yes - because it is something that needs to be understood at the formal lifecycle level. I.e. its not a lifestyle question.
The drastic conclusion that you came up with is that because there is no
absolute standard, then there can be no cross-container predictability unless
we use the same implementation details for the pooling code. To this I can
agree. However, I think we have differing solutions to the problem. The
lowest cost solution would be to add a new interface that has the release
semantics of resetting the component before it is accessed again. That would
make it part of the component/service contracts--and we can adapt any pool
implementation to satisfy it.
Would that be enough--at least in the short term?
I'm not really following the short term comment - if there is a short term solution it implies that there is a long ter[m] solution which in my understanding has not been presented. If I look at Excalibur event mpool I have some contracts which after refactoring relative to the meta package could become part of the framework lifecycle model - and as such, influ[e]n[c]es lifestyle decisions concering component recycling. If I look at the Turbine Fulcrum package there is an equivalent set of of interfaces (pools, recycling, etc.). At the same time I wondering to myself if we are simply overloading lookup with too many semantics? What if you have an A5 interface that sep[a]rated pooled and non-pooled ob[j]ect lookup? I.e. explicit understanding that transient object dependencies are not the same as singleton depende[n]cies. I don't [have] the answer just yet - but from a purist architectural point of view - something smells wrong in th[is] corner of the world.
(and it's not just my spelling)
;-)
Cheers, Steve.
--
Stephen J. McConnell mailto:[EMAIL PROTECTED]
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
