Let's get back to the basics, and answer some fundamental questions. First, what is the goal of the Avalon team? Second, how do current Avalon technologies fit in to this vision?
For me, the goal of the Avalon team is to produce a kick-A container and show just how elegant and simple component based programming can be. This is a very general statement on purpose, but in the end I think it is what we all want deep down inside.
As to the current Avalon technologies, they provide a foundation, and a set of building blocks and features that show the power of components. Before we get into the nitty gritty details, let's review some basic foundational principles.
Components ----------
Components are reusable pieces that are managed by containers. They are the building blocks of applications.
Containers ----------
Containers are the central nervous system of COP. They create components and manage their instances. They map a component implementation to a request for a component type. They also have the ability to apply new features to existing components.
IOC ---
The core pattern used to manage components. IOC provides the mechanisms to isolate components from each other as much as possible, yet still provide functional and robust components.
SOC ---
The management pattern used to separate a problem space into concern areas. It is for this reason that we have separate interfaces for our lifecycle methods. We shouldn't have to implement a method if we have no use for it. But it doesn't stop there. Separating interface from implementation helps separate the concern of problem definition from problem solution. Many concerns are discrete; they have defined boundaries that only affect a small portion of the problem space. Other concerns are cross-cutting; they affect the whole application, or at least a large part of the application. Another word for concerns are Aspects. We can apply aspects without the need for language modifying libraries like Aspect4J. CBD provides the perfect way to apply aspects to an application: through the container managing the components.
I think this pattern of SOC has been lost, but I think I have a way where we can bring it back.
-o0= The Basics of a Container =0o-
In an effort to restore *simplicity*, let's get back to what the minimum is for a container to do. The absolute minimum for a container is to instantiate and run one component. That is all that is required for something to be a container. In fact we can boil the simplist container in the world down to one very simple object:
public class Container
{
private Component m_component; public Container()
{
m_component = new Component();
}public Component getComponent(); }
That is the simplist container for the simplist component. We start adding complexity when we don't omnisciently know everything about our component. For that reason we have a collection of framework APIs so that the arbitrary component knows how to get the information it needs, and the container can initialize any arbitrary component.
We can expand this by providing a ComponentFactory which takes care of the logic necessary to set up components. The simplest implementation does not require any external information. It will use default objects for every stage. The container can swap out the component factories, and the same container will be able to work on a different kind of component. I am oversimplifying this on purpose. Remember, this is a back to basics thought.
So far, we have a core container with the ability to swap out the ComponentFactory. Now what if we had another requirement to have multiple ways of managing component instances? I dubbed this concept "lifestyle", and the term has kind of stuck. Most containers work with a known lifestyle like EJBs and Servlets, however ECM originally introduced the ability to have pooled components and transient components. The way these components are written is incompatible with assuming singleton status.
There are a number of ways to solve that problem, but for now lets just classify it as an aspect of component management. So far we have identified two aspects. There is no particular alegence to the ComponentFactory solution above, just a recognition that component initialization logic is merely one of the concerns from a component.
Another concern that is related to creating a component is populating the lifecycle artifacts. In Avalon land, the lifecycle artifacts are the Context object, the ServiceManager, the Logger, etc. The important thing to realize is that this aspect is related to component initialization. If our container is able to initialize other types of components, the set of lifecycle artifacts required will change.
Up to this point, our hypothetical container only has to maintain one component. As soon as we introduce other components into the container, we have one more aspect that needs to be managed: intercomponent dependencies. These dependencies can be managed by explicit logic, implicit logic, or some combination. For example, in ECM it is assumed that the developer knows all the components that belong in the system. In the more sophisticated containers, we can verify that assumption is indeed true or not. Also, in the more sophisticated containers we provide an additional assembly concern. Assembly is the process of customizing how the container maps objects to dependencies. The two levels of the mapping include components to component dependencies and lifecycle artifacts to artifact dependencies.
So boiling a container into its most basic concern areas, we have the ability to create and initialize a component, the ability to manage its lifestyle, establishing the lifecycle artifacts, and managing intercomponent dependencies. Everything else above these most basic concerns are features. Many time these features are necessary. Many times these features are only really important to a handful of people. Either way, it is not important. What *is* important is that a container be able to add or modify these features in a manageable way.
-o0= The Radical Stuff =0o-
In Avalon land we have three modern containers: Fortress, Merlin, and Phoenix. Each have their own strengths and weaknesses. Each has tried new and exciting approaches to different problems. The truth be told, the only way to have a one-size-fits-all container is not have one--at least in the traditional sense. Our existing containers have addressed modularity in differing ways. In the end I find that a great learning experience. We can find how things work, and how to get things to interoperate.
This RRT works for both Avalon and Avalon#. My proposal is this: start with just the basics. Make the basics interchangable. That way we can define an interface for the basics. We can define how the basics interact. We make it really simple. We don't identify the meta information ahead of time, we just start with the logic.
Once we have the basic interfaces, we start providing the implementations refactored from our existing containers. Again, these are only the basics. Once we have defined the functional basics, we look at what meta information makes sense for that aspect. The entire concern is self contained. If we want avalon components, the component initialization logic knows how to read the meta information and provide it. If we want our context objects verified, we add in the concern which also reads that meta information.
In the end, our container becomes merely a shell that holds container components. Those container components interact to manage the application components. To differing levels of success, each of our containers has this concept at heart. The trick is to complete the job. I believe we should start fresh for the core code. From there we refactor the existing containers to work with that framework. I believe we will be amazed at how quickly we can arrive at the unification. The trick is to start simple, and try to remain simple.
One approach is to declare a unique interface for each type of aspect. Another approach is to try to come up with one interface that is flexible enough to be used in any aspect. I leave it to the community to decide what the best approach should be.
As we design our system we need to provide for some hard problems such as interceptors, customizing parts of the lifecycle artifacts (i.e. one user may want context validation but not configuration validation and vice versa). We don't have to get it right to begin with, the container components can evolve as we find what works and what doesn't.
Now here is the truly radical part. If we go this way, we don't have to come up with one meta-info library that knows all about Avalon components and every facet to them. We only need a way to read arbitray metainfo from from the component and assembly information. As to assembly, we should make that concern replaceable as well. What we start with may not be what we end up with. The beauty of the solution is that the container can be free to be extended and improved while still providing that key backwards compatibility.
As of right now, we don't have one way of doing assembly. In fact, that should be OK. As long as we don't have to have a whole new container to implement an alternative way of doing assembly we can let the user decide that they want the container to use Phoenix Assembly rules with Merlin Component Management rules and Fortress Asynchronous initialization. Wouldn't that rock? It allows the evolution to move at a steady yet controlled rate so that the project neither stagnates nor changes too radically.
-o0= Community Agreement Process =0o-
As has been shown repeatedly in the past, we will come up against issues where we disagree. What I would like to propose here is a guideline to help the disagreement from escalating to the point it just did with the meta information package. The requirements of building a new container from the ground up, evolving existing functionality in can have some potential points of conflict. The Jakarta guidelines don't address this, and are insufficient when we are dealing with design issues as opposed to code issues. Design is reflected in code so there is somewhat of a grey area there. The balance is that interfaces should be considered design, and implementation should be considered code. For code (i.e. implementation) we follow Jakarta Guidelines. For design (i.e. interface) we follow the proposed guidelines:
* We put one or more proposals on the table for the same concern area. The concern area should be clearly identified.
* Once all _questions_ have been answered about the differing proposals, and the proposals are finished with any modifications due to the questions, we place it up for vote. The proposal that wins, wins. No exceptions. Remember, we can change it later if we find it a dead end.
As to general guidelines to make this a happier place, I believe it is important to lay down some general reminders. Email is notoriously impersonal, even jests can be taken in offense.
* Acknowlege and respect each others oppinions, comments, concerns. Do not dismiss them, but you can address them in a calm unconfrontational manner.
* Offense happens. When it does, simply say that a particular comment is offensive. The person who offended needs to have the decency to acknowlege the hurt and appologize for it. You can appologize for HOW you said something without appologizing for the INTENT of the message. In other words, if your objection to an interface included offensive comments, you can appologize for the offensive comments without appologizing for objecting to the interface.
* Steer clear of calling each other's oppinions, comments, concerns FUD. Whether they are or not, remember the first point.
-o0= Are We on Board? =0o-
The body of this entire RRT includes my views on the subject, but that does not mean we all agree to it. The bottom line is that as long as we have code that certain developers feel they need to protect from other developers we have no basis for cooperation. One way to address this issue is to equalize the playing field and put everyone in the same boat. Another way to address it is for us to put down our pride and learn to work with everyone here. Nothing is sacred.
As this affects the whole of Avalon, I would like to know your thoughts, comments, concerns on this subject. If we would like to adopt it as our future direction, let's do it. If there are any concerns, let's lay them on the table.
--
"They that give up essential liberty to obtain a little temporary safety
deserve neither liberty nor safety."
- Benjamin Franklin--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]
