Leo has some good points, and as usual, he likes to explain himself in code :). That's not bad, but I work with prose, so I want to see if I "got it" and also I want to try and tie in some things that Paul and I have discussed off list, as well as some things that have been going on in my head.
Leo's main point about Avalon needing to KISS is well made, and taken seriously. I agree that Avalon can be made simpler. The question is how and where to simplify. Another question is how to protect people's investments so far. We all have had a certain amount of investment in Avalon, and we don't want to throw it away.
The key to evolving a framework is to do the following:
1) Protect your current users. Jerking your users around will make you lose them. We can easily accomplish this by providing adaptors for existing components.
2) Evolve the framework--don't redesign it. Learn from what Avalon has done right, and exploit it better. Learn what other frameworks have done better, and incorporate it. Learn what we don't like about Avalon and change it.
3) Follow XP practices. We won't be able to cleanly do an A5 if we think we know better than our users. We need to do test driven design, and use case driven design. If there is no compelling reason for the code it doesn't belong there.
4) Add features incrementally. Don't try to tackle persistent components if you aren't using them yet. Do tackle component configuration when you have components that need to be customized.
5) Have an idea of what you are doing. While I agree with Paul that "Big Design Up Front" is detrimental, I also believe that you have to have a general direction or overarching concern for a system.
Now, that said, let's look at some of the points Leo made:
Java Works: Amen! So do other languages. Even if we don't make everything
perfect, we should look at how the problem was solved in other
languages so we can have a good understanding of the problem
domain.XML Works, too: Yes and no. It works for expresing complex configuration info,
it also works for representing semantic information. However,
it has been forced into applications for which it really doesn't
make sense. Caveat Emptor. KISS. Only use it where it makes
sense.Language Mixing Sucks: Amen and Amen! Unless there are ways of masking the
interaction between languages (which is what .NET is
good at) trying to embed one language in another bites.
That said, a project with multiple languages has an
increased learning curve.Decouple: Amen! Decoupling separates the contracts from the implementations.
Many projects have been screwed up because of mixing contracts with
implementations.The others I completely agree with, so let's move on. From Chapter 1 from my book (which may or may not get published BTW) has this to say on contracts:
"Contracts get their name from the legal system. A legal contract is an agreement between two parties that can be enforced by authorities. In the developer’s world, we run into informal contracts all the time. A development contract is something that must hold true or it will break the system. Anyone who has been programming for a long time has run into undocumented contracts. Undocumented contracts come from assumptions about how a piece of code works. If enough developers have the same assumption about the same piece of code, it becomes an unofficial contract.
"In component based systems, contracts are inseparable from the component’s role. We must document every contract that we intend to enforce. All contracts are official, and are quite like the legal definition of a contract. The penalty for a component that claims to implement a role, but violates its contracts is that it is no longer used. Because the role explicitly identifies all the contracts that a component implementing it must obey, we have the freedom to change the component we use without fear of breaking the system.
"Component contracts should be simple and written to be well understood. My advice for defining the contracts for a role is to limit the number of contracts so you can have more freedom in the component. Said another way, the component roles should serve one purpose, and delegate to other roles that have a separate purpose. Contracts identify the guarantees that any component implementing an interface must support.
"A contract is a constraint that all components for the same role must obey."
Pay particular attention to the second to last paragraph. I advocate KISS, but there is a balance of writing/enforcing contracts. You want *enough* rigidity so that you can reliably predict the results, but no more than that. Having the contracts so binding that there can only be one real implementation is a tragedy in my oppinion.
From Leo's winning concepts:
* IoC, COP, API/Impl separation -> nothing more to be said. We have it and it rocks.
* XP, test first -> we (hopefully) are migrating toward that route. We need to get better about that.
* asynced events, pipelining -> we have support for this, but it can be better. let's see where we need to improve. There are 101 ways of doing this, and there are tradeoffs for each one.
* attributes -> :) We have a minimum, and we have some work that needs to be done to finalize this. Let's not get religious about it, but work on a truly workable minimum and then how we can safely augment it. I think we need to standardize on the way we store and retrieve the meta info (not necessarily on an object model for the info).
* apects -> Containers take care of many aspects for its components. We can take better advantage of that. In fact, containers allow us to apply aspects in a much more predictable manner than language level aspects like AspectJ.
* scriptability -> This is not a requirement, but it helps in many problem domains. Scripts should be treated as commands in the system. Those commands are executed in response to certain events.
* pluggability -> If we can conquer this, then it will open the door for all the other things we need to be better about like aspects and scriptability.
* strong typing -> This is a language feature of Java, C#, and several other languages. You can't force strong typing on systems where there isn't strong typing to begin with. Or perhaps you are talking about something else.
Avalon 4 Doesn't Cut It:
Those that have been advocating an Avalon 5 caught this vision way back when. We recognize that we need to simplify the contracts as much as possible. We also need to strike a balance between work that the component writer has to do and work that the container has to do. IMNSHO, the container should take care of more work than the component writer. Otherwise the same issues will be present time and time again.
Smaller Is Better:
Paul has talked to me about a more Bean-like component architecture that he and other well respected folks have been working on in an XP manner. It seems to work. There are some things that are great like setXXX() methods for your components which makes the framework strongly typed--but it also makes certain aspects of container/component contracts more difficult to implement. That's not a real blocker for me though.
He has also talked to me about using constructors for write once assignment of the components. This has a twofold advantage for making the components read-only without resorting to proxies, and making it easier for the component to obtain them.
There are some challenges to that approach that need to be resolved:
1) Managing changes in the constructor 2) Managing ordering of dependencies esp. when more than one type is compatible.
These can be handled with a declarative method (i.e. attributes), and can definitely be explored.
Macro Concerns:
It seems to me that packaging and component classloader architecture are bigger issues than the fine component contracts for the time being.
Separate API/Impl:
The code snippet did not do this. The container must be in charge of this. Components should be able to stand on their own merits.
--
"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]
