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]



Reply via email to