cocoon-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Stefano Mazzocchi <stef...@apache.org>
Subject Re: [RT] composition vs. inheritance in blocks
Date Wed, 30 Mar 2005 16:26:30 GMT
Daniel Fagerstrom wrote:

[snip]

> Can you describe how you would prefer to adress the "building a webapp 
> from several blocks" scenario that I described above.

Daniel, you are asking for two things:

  1) the existence of a super() equivalence in the block protocol
  2) the introduction of multiple inheritance of block implementations

the first is harmless and while I have never thought about needing it, I 
don't see how it could harm us, so I would not be against introducing it 
it. So, if Block A extends Block B, calling

  block:super://blah.xml

from Block A would yield the call to 'blah.xml' in Block B. Does this 
satisfy your needs?

[and no, let's not go over the super(2) to indicate the case where there 
is more than one layer of inheritance! that's FS!]

                                   - o -

As for MI, like I said before (and you carefully snipped), MI makes it 
*easier* to glue pieces together that were not designed to be reused, 
while composition, since it forces you to define a behavioral interface 
for every exposed service, will very likely slow you down (yes! this is 
true! it's a feature not a bug) but will make you think about how to 
design those services.... A by product of this is that your services are 
instantanously more reusable and the contracts between components are 
more solid, and SoC/polymorphism much more effective (the size of the 
cocoon distribution proves my point).

So, instead of multiply inherit a bunch of blocks, you have to define a 
behavioral interface for every block (which is a URI at the end, not 
such a big deal) and indicate that you "require" the use of a block that 
implements that functionality.

So, instead of what you are proposing:

  A -(extends)-> B
  A -(extends)-> C

I proposed to do:

  A -(requires)-> 1 <-(implements) B
  A -(requires)-> 2 <-(implements) C

(where letters are implementations and numbers are interfaces), and if 
you need to extend B and C to provide a slightly different 
functionality, then you would have something like

  A -(requires)-> 1 <-(implements)- B2 -(extends)-> B
  A -(requires)-> 2 <-(implements)- C2 -(extends)-> C

or fragmented in statements

  A -(requires)-> 1
  A -(requires)-> 2
  B -(implements)-> 1
  C -(implements)-> 2
  B2 -(extends)-> B
  C2 -(extends)-> C

where you could have 'default' statements that say

  A -(prefers)-> B2
  A -(prefers)-> C2

and the block manager would reason on the above graph and infer that 
it's sane and that

  A -(connects to)-> B2
  A -(connects to)-> C2

which achieves the same exact functional effect as MI, but with more 
explicit contracts.

-- 
Stefano.


Mime
View raw message