You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cocoon.apache.org by Stefano Mazzocchi <st...@apache.org> on 2005/03/29 18:22:35 UTC

[RT] composition vs. inheritance in blocks

Daniel Fagerstrom wrote:

> But if we step up from the technical details, the main reason that I 
> want multiple inheritance is that I want to make it easy to build 
> webapps by extending and partly overiding a couple of orthogonal blocks. 
> When you build your webapp block it might extend e.g. a Forrest block 
> for documentation structure and skinning, a Lenya block for CMS 
> functionality a user handling block for user adminstration etc. If you 
> use extension you get a default behaviour from the beginning and then 
> you can a step at the time overide the resources you want to modify.
> 
> If you use a block instead of extending it, it is much more complicated 
> to modify its behaviour. Take a look at Forrest, e.g. To make it 
> extendible you have to use all kinds of global variables to simulate 
> polymorphism. You must explicitly tell where it should search for 
> different resources in your Forrest conf. As I have said before, I have 
> practical experience of building webapps based on sitemap polymorphism 
> and multiple inheritance, and it is much more convenient than having 
> Forrest like conigurations for every block you want to extend.
> 
> <snip/>
> 
>>>> ------------------------------------------------------------------------------ 
>>>>
>>>> Improvement #3: block inheritance
>>>>
>>>> The third step is to allow blocks to extends other blocks.
>>>>
>>>> The idea is to be able to wrap a block with another one, creating an 
>>>> 'overloading' mechanism similar to the one used by OOP inheritance 
>>>> where methods are 'fall back' to the extended class if the extending 
>>>> class doesn't implement them.
>>>>
>>>> Let us supposed we have the following block (very simple):
>>>>
>>>> block "A" implements "skin"
>>>>
>>>>          /stylesheets/changes2document.xslt
>>>>          /stylesheets/faq2document.xslt
>>>>          /stylesheets/document2html.xslt
>>>>          /resources/logo.gif
>>>>
>>>> and let us suppose that we want to change the look and feel of that 
>>>> block. The first two stylesheets provide simply a way to adapt from 
>>>> more specific markup to the Document DTD. So, my block would need to 
>>>> change only the last two resources 'document2html.xslt' and 'logo.gif'.
>>>>
>>>> The best solution is to allow my block to explicitly "extend" that 
>>>> block and inherits the resources that it doesn't contain.
>>>>
>>>> block "B" extends block "A"
>>>>
>>>>          /stylesheets/document2html.xslt
>>>>          /resources/logo.gif
>>>>
>>>> but then block B still is considered implementing behavior "skin" 
>>>> because the rest is inherited.
>>>>
>>>> This mainly:
>>>>
>>>>     * reduces block development and maintanance costs because 
>>>> changes and bugfixes are directly inherited by all the extending 
>>>> blocks, thus allowing better SoC between the two groups mainaining 
>>>> the different blocks
>>>>
>>>>     * easy customization: blocks can be adapted for personal 
>>>> specific needs simply with a wrapper around and without the need to 
>>>> repackaging.
>>>
>>>
>>>
>>>
>>> Ok, allready discussed that above. I think we need to be more 
>>> explicit about what behaviour we want. If we just write:
>>>
>>> <map:transform src="stylesheets/document2html.xslt"/>
>>>
>>> that means normally the same as:
>>>
>>> <map:transform src="context:/stylesheets/document2html.xslt"/>
>>>
>>> and I don't think it is a good idea for isolation between block to be 
>>> able to overide what is in the current context, only things that are 
>>> exposed through the sitemap should IMO be overidable:
>>>
>>> <map:transform src="block:polymorph:/stylesheets/document2html.xslt"/>.
>>
>>
>>
>> I'm not sure if Stefano and you mean the same here. IIUC in Stefano's 
>> example
>> you have e.g. blockA and blockB. blockA implements the behaviour skin and
>> extends blockB:
>>
>>
>> <block id="http://cocoon.apache.org/blocks/A/1.0.0">
>>  <extends>
>>   <block id="http://cocoon.apache.org/interface/B/1.0.0"/>
>>  </extends>
>>  <implements>
>>    <interface id="http://cocoon.apache.org/interface/skin/1.0"/>
>>  </implements>
>> </block>
>>
>> A sitemap snippet of blockA:
>>
>> <map:match pattern="stylesheets/document2html.xslt">
>>   <map:read src="{0}"/>
>> </map:match>
>>
>> A sitemap snippet of blockB:
>>
>> <map:match pattern="stylesheets/changes2.html.xslt">
>>   <map:read src="{0}"/>
>> </map:match>
>> <map:match pattern="stylesheets/document2html.xslt">
>>   <map:read src="{0}"/>
>> </map:match>
>>
>>
>> Another block, e.g. blockC now uses blockA for its styling:
>>
>> <block id="http://cocoon.apache.org/blocks/C/1.0.0">
>>  <requirements>
>>   <requires block="http://cocoon.apache.org/interface/skin/1.0"
>>    default="http://cocoon.apache.org/blocks/A/1.0.0"
>>    name="skin"/>
>>  </requirements>
>> </block>
>>
>> Here a sitemap snippet of blockC:
>>
>> <map:match pattern="myPipeline1">
>>   <map:generate src="bla"/>
>>   <map:transform src="blocks:skin:/stylesheets/document2html.xslt"/>
>>   <map:serialize/>
>> </map:match>
>> <map:match pattern="myPipeline2">
>>   <map:generate src="bla"/>
>>   <map:transform src="blocks:skin:/stylesheets/changes2html.xslt"/>
>>   <map:serialize/>
>> </map:match>
>>
>> myPipeline1 gets the stylesheet from blockA and myPipeline2 from 
>> blockB (no
>> stylesheet available in blockA --> fallback to super block blockB)
>>
>> Does this make sense for you?
> 
> 
> It does.
> 
>> How does block:polymorph apply in this usecase?
> 
> 
> In your example block A extends block B, then in block B we can have a 
> sitemap rule like:
> 
> <map:match pattern="**.html">
>  <map:generate src="{1}.xml"/>
>  <map:transform src="block:polymorph:/stylesheets/document2html.xslt"/>
>  <map:serialize/>
> </map:match>
> 
> The block:polymorphism makes that stylesheets/document2html.xslt is 
> taken from A rather than B. Say that you use that stylesheet in several 
> rules, then you change multiple behaviours by overriding it.
> 
> 
>>>> --------------------------------------------------------------------------------- 
>>>>
>>>>
>>>> I'm not sure about multiple-block inheritance. For me it's some kind 
>>>> of an anti-pattern but maybe I'm too Java-minded.
>>>
>>>
>>> Multiple inheritance is not an antipattern in itself. The idea that 
>>> it should be is IMO mainly marketing BS from Sun to make the stupid 
>>> idea of single implementation inheritance seem like a feature.
>>>
>>> But there are a number of antipattern that was popular in OO maybe 
>>> 10-20 years ago that was based on multiple inheritance. But that is a 
>>> different thing. People tended to model the world with classes 
>>> instead of interfaces, and used deep an multiple inheritance that got 
>>> a lot of garbage from all the to full featured base classes. Also as 
>>> the extension relation in Java (and many other OO languages) is much 
>>> "harder" than using through interface, extension was considered less 
>>> flexible.
>>>
>>> But as discussed above we don't need extension to be as hardcoded as 
>>> in OO languages. And also implementation inheritance is a rather 
>>> natural and efficient way to put things together.
>>
>>
>> I think that modelling applications using interfaces and implementing 
>> them using
>> delegation is better than extension ...
> 
> 
> If you want to convince me I'm afraid that you have to tell why you 
> think it as well ;)
> 
> Using extension as it happen to be implemented in C++ and Java can be an 
> anti pattern under certain circumstances. But saying that something is 
> an antipattern without giving a context is close to meaningsless. For 
> blocks extension give us polymorphism and if we want to extend and 
> override several different concern areas in our webapp, we need multiple 
> inheritance.
> 
> If we instead using interfaces they are for the moment just an URI an 
> maybe some documentation. And for the delegation, it means that you have 
> to explicitly code the usage pattern for every block service.
> 
>> The question for blocks now is what
>> multi-block inheritance really buys us.
> 
> 
> Extend and override from multiple blocks based on polymorphism.
> 
>> As I said above I think we should go
>> through all 3 block services (pipelines, components, flows) and describe
>> scenarios and compare pros and cons of multi-block inheritance 
>> compared to single-block inheritance.
> 
> 
> The pros with multi-block inheritance is that your block can be vertical 
> frameworks with default behaviour that you can modify by overiding 
> certain pipeline rules, components and flow functions. The cons is that 
> we have to spend some thinking to get the design right and to get the 
> behaviour intuitive enough.
> 
> Single block inheritance is possibly good in the way that it is easy to 
> see where you get things from and it is bad in that you have to do a lot 
> of coding if you want to use several vertical frameworks that takes care 
> of different concern areas in your webapp.
> 
> Frankly I can't see much advantages in single implementation inheritance 
> at all. If delegation always is better we should only have interface 
> inheritance and not even single implementation inheritance. And if 
> implementation inheritance is good, and for webapps I'm quite certain 
> that it is, it seem like a very arbitrary limitation to just allow for 
> inheriting implementation for one concern area.

I don't like multiple inheritance and this is not just because I learned 
OOP thru java, but because every single time I wish I had multiple 
implementation inheritance in java I found a way to go around the 
problem with single implementation inheritance that was more elegant.

I would go a little further and say that I believe inheritance is useful 
only when used as a 'cascading' mechanism, in any other sense is 
harmful: composition should be used instead.

Why so?

It's extremely hard to design for inheritance, a lot easier to design 
for composition.

And performing composition thru multiple-inheritance is a really 
terrible way to do it. Why? because you need to go very deep in 
describing what behaviors get exposed and what are protected, otherwise 
things get messy very fast.

Also, multiple-inheritance stops further composition: you seem to 
suggest that a block that inherit multiply is a 'leaf block', one that 
is your own application and that will not be used by others.

Well, one of the reasons for block design was to sparkle the creation of 
reusable application components without people to think much about them: 
multiple-inheritance yields horizontal behavior changes to the inherited 
components, which means that if I have block A inherit block B and then 
block C that wants to use A but was already using B, but A modified B's 
behavior a little with the inheritance, you have a problem!

I am strongly against multiple implementation inheritance for blocks, 
because what you want to do, if you care about reusability, is really 
multiple composition and that is achieved with being allowed to 
implement multiple behavioral interfaces.

If you *don't* care for reusability, then it's true that multiple 
implementation inheritnace can serve as a cheaper form of composition.

But if I had to pick between improving block reusability or ease of 
composition, I would go with the first, hoping that tools/syntax-sugar 
would help the second (as it happened with Java).

-- 
Stefano.


Re: [RT] composition vs. inheritance in blocks

Posted by Peter Hunsberger <pe...@gmail.com>.
On Tue, 29 Mar 2005 19:36:33 -0500, Stefano Mazzocchi
<st...@apache.org> wrote:
> Peter Hunsberger wrote:
> 
> >>I would go a little further and say that I believe inheritance is useful
> >>only when used as a 'cascading' mechanism, in any other sense is
> >>harmful: composition should be used instead.
> >>
> >>Why so?
> >>
> >>It's extremely hard to design for inheritance, a lot easier to design
> >>for composition.
> >
> >
> > That's FUD: a graph is a graph is a graph.
> 
> BS. All graphs are graphs, but the 'properties' of graphs very a lot
> between them and there is a pretty good literature about how different
> 'local properties' in graph growth yield global properties.

Most of the significant differences are best described as the result
of default node exposure vs. default node hiding.  Composition can
only default to hiding, inheritance can do either.  As such, simply
saying that composition is better than inheritance is FUD, it's how
you traverse the graph that matters and what matters for Cocoon blocks
is that a graph is a graph is a graph.

A good traversal mechanism is going to solve the issues at hand much
better than trying to figure out whether that traversal mechanism
shares more properties with the concepts of inheritance or
composition.

xPath comes to mind...

> > The only question is how to expose or hide child nodes.
> 
> Yep, this is *exactly* the local property I'm talking about above, that
> yields very different dependencies graphs.
> 
> > With composition there are no child
> > nodes until you add them.
> 
> Yep.
> 
> > With inheritance the visibility depends on
> > the language and the implementor.
> 
> Absolutely. And look at what happens with our classes: we call something
> public, just because we want another package to have access to it, and
> this is automatically exposed to somebody that later on wants to extend
> it, even if we did not meant it to be public for that use!!
> 
> Sure, we could keep adding 'visibility' stati to sitemap URLs (we
> already have two: internal and external) but what is the gain?

Composition doesn't solve this problem. If you need public access to a
composed method the problem starts all over again. The problem with
Java is how you traverse the nodes (using public/private/etc.), not
inheritance.

> 
> >>And performing composition thru multiple-inheritance is a really
> >>terrible way to do it. Why? because you need to go very deep in
> >>describing what behaviors get exposed and what are protected, otherwise
> >>things get messy very fast.
> >
> > Also FUD, again it depends on the language and the implementor.
> 
> Again, BS. MI would force us to deal with visibility metadata and back
> compatibility would force us to default to 'external', meaning that only
> those 'aware' of what they are doing will keep things internal unless
> really required to open it up, and the 'public' java identifier problem
> will happen all over again.

No that's not BS: properly used MI doesn't _force_ you to do anything
more than composition. It allows it, but doesn't force it. MI provides
a superset of capabilities WRT composition.  One can construct exactly
the same graphs using a constrained MI as with composition, the
inverse is not true (for normalized structures).
 
> >>Also, multiple-inheritance stops further composition: you seem to
> >>suggest that a block that inherit multiply is a 'leaf block', one that
> >>is your own application and that will not be used by others.
> >>
> >>Well, one of the reasons for block design was to sparkle the creation of
> >>reusable application components without people to think much about them:
> >>multiple-inheritance yields horizontal behavior changes to the inherited
> >>components, which means that if I have block A inherit block B and then
> >>block C that wants to use A but was already using B, but A modified B's
> >>behavior a little with the inheritance, you have a problem!
> >
> >
> > Only if you design things to allow the problem in the first place.  If
> > I'm using both blocks to start with I can specify A.foo() or B.foo()
> > and pick or choose which version I want.  If I start out using only B
> > and later add in A and find out I have a name space collision on foo()
> > then I have an issue.
> >
> > That's where the real problem lies with Cocoon blocks: unless the
> > references are resolved at startup then you have the _potential_ for
> > obscure run time problems as blocks get resolved dynamically.  Since
> > you may not want to do startup resolution on the entire graph, I think
> > the way for Cocoon to support multiple inheritance is for the default
> > behaviour to be to hide all inherited capabilities and require
> > explicit exposure or to always require complete paths to the function.
> 
> Exactly, and this behavior is back incompatible.

There's nothing to be back incompatible with....   Given that the
resultant property exposure can be exactly the same as with
composition you're not making any sense.

> > IOW, in this example , the only way to see the A version of foo()
> > would be an explicit reference to A.foo(), otherwise the reference
> > would fall back to B.
> >
> >
> >>I am strongly against multiple implementation inheritance for blocks,
> >>because what you want to do, if you care about reusability, is really
> >>multiple composition and that is achieved with being allowed to
> >>implement multiple behavioral interfaces.
> >
> >
> > Given that this is more-or-less completely new territory, the terms
> > inheritance and composition seem to be getting in the way.  The real
> > issue is how does the block language expose features from each block.
> > You're describing the language as implementing "multiple behavioral
> > interfaces"; from my backgrounds POV the easiest way to do that is
> > multiple inheritance.
> 
> I completely agree that it's the easiest way. My avalon experience shows
> me that composition yields more separate and much easier reusable
> components.

That suggests to me that avalon didn't have good ways of working with
MI, nothing more...

> It's very true this is unexplored terryrory, but my gut feeling tells me
> this is the case for webapp components as well. And, as I said, I will
> stick to this until proven wrong.

Here's the issue, properly done:

- composition yields a bunch of disjoint graphs and relies on a
grammar to move from one graph to another, and another grammar to move
from one node to another.

- MI builds a single normalized graph and uses a single grammar to
move from one node to another.  A separate grammar is required to
build the normalized graph from disjoint components.

IOW; where do you want to pay the price for the second grammar? At the
time you smash the blocks together, or at the time you want to use the
functions in a block?  Do you smash the blocks together more often
than you use functions across the blocks or vice versa?

Frankly, I don't know the answer to that one.

We do know that Cocoon has mechanisms for aggregation already
existing: smashing a bunch of block descriptors together in a pipeline
is trivial.  Using XSLT  to extract the results is likely somewhat
tricky work.  However, once you've got the results, an in memory DOM
like structure traversed via xpath for feature extraction is straight
forward programming.

> 
> >>If you *don't* care for reusability, then it's true that multiple
> >>implementation inheritnace can serve as a cheaper form of composition.
> >>
> >>But if I had to pick between improving block reusability or ease of
> >>composition, I would go with the first, hoping that tools/syntax-sugar
> >>would help the second (as it happened with Java).
> >
> > Well, that's almost all that it is about in this case: pure syntax.
> > If you think about what's going to have to happen under the covers the
> > end result is the same either way: you need a language to describe
> > which features are visible from one block to another.  If there's a
> > term that is an abstraction for both inheritance and composition then
> > that's what you reallly want...
> 
> that's hiding the problem under the carpet.
> 
> Polymorphic Composition is not the same as multiple inheritance even if
> they might be used to achieve the same results.
> 
> The real issue is another one and you both seem to be missing it
> entirely: multiple inheritance is easier to use, because doesn't force
> the block providers to define (and think about!) the contract between
> you and the services you require to achieve your task.

Only if you let it (default feature exposure)...

> 
> This is both its advantage and its ultimate weakness: the system is way
> more fragile because the contracts between the two block sare 'implitic'.
> 
> So, when you do
> 
>           +-(inherits from)-> block B
>          /
>  block A
>          \
>           +-(inherits from)-> block C
> 
> what you are really stating is
> 
>           +-(requires)-> service 1 <-(implements)- block B
>          /
>  block A
>          \
>           +-(requires)-> service 2 <-(implements)- block C
> 
> in java interfaces at least have method signatures that can be checked
> at compile time, Cocoon blocks won't have anything like that (the first
> that mentions BPEL will be shot!) because it's simply too hard (and
> cumbersome and useless in a local environment) to describe the behavior
> of a (potentially stateful!) service.

Unless you're going to write the language (BPEL or otherwise), how are
you going to get any better contracts with composition? You might have
jumped straight to your second diagram, but so what?  Unless you've
written the "requires" and "implements" contracts you haven't achieved
anything.  If you have written those contracts then they are the nodes
of your graphs and you're back to the issues I give above: how do you
want to smash the nodes of the graph together and how do you want to
traverse them?

> In such a 'weakly typed' environment, allowing people to get away with
> even "defining" what is the service (interface) that a block implements
> in order to allow service composition is suicidal.
> 
> I don't want it to be easy to 'reporpuse' existing blocks (not designed
> to be extended or used as services!!), I want it to be *HARD*.

What about blocks designed to be used as services?  Do you want _two_
different mechanisms for dealing with blocks?  Surely not?

> I want it to be dead easy to write 'leaf blocks', those that you mount
> to the public and you expose as your own stuff, but as for writing
> blocks that are meant to be reused, this is another story and this
> requires you to go to the process of managing that contract between what
> you implement and what you exhibit.
> 
> And you get polymorphism for free if you do that, but polymorphism is
> not the main advantage of this: interfaces, just like in java, make
> programs more reusable and solid because they create 'awareness' of what
> is the contract between your code and the user's.
> 
> If we lose that, we are doomed to have a million blocks, and people that
> keep cutting and pasting between them to achieve what they want and
> avoid depending on somebody elses because the contracts change too fast.
> 
> Sure, unlike java, our dependencies are versioned, so some of that
> problem goes away, but the awareness of contract management is what I
> want and MI kills all that.

Oh, good grief, that's simply not true (and I'm pretty sure you know
it).  Sure you can screw up contract management with MI.  You can also
screw up contracts with composition. You can also make contract
management easier with MI than with composition.

Instead of arguing MI vs. composition figure out what it really means
to do contract discovery and validation: if it's something you need to
do multiple times then you want a normalized graph.  If it's something
you rarely need to do then save the resources required to do
normalization and use disjoint graphs instead.

 -- 
Peter Hunsberger

Re: [RT] composition vs. inheritance in blocks

Posted by Stefano Mazzocchi <st...@apache.org>.
Peter Hunsberger wrote:

>>I would go a little further and say that I believe inheritance is useful
>>only when used as a 'cascading' mechanism, in any other sense is
>>harmful: composition should be used instead.
>>
>>Why so?
>>
>>It's extremely hard to design for inheritance, a lot easier to design
>>for composition.
> 
> 
> That's FUD: a graph is a graph is a graph.  

BS. All graphs are graphs, but the 'properties' of graphs very a lot 
between them and there is a pretty good literature about how different 
'local properties' in graph growth yield global properties.

> The only question is how to expose or hide child nodes. 

Yep, this is *exactly* the local property I'm talking about above, that 
yields very different dependencies graphs.

> With composition there are no child
> nodes until you add them.

Yep.

> With inheritance the visibility depends on
> the language and the implementor.

Absolutely. And look at what happens with our classes: we call something 
public, just because we want another package to have access to it, and 
this is automatically exposed to somebody that later on wants to extend 
it, even if we did not meant it to be public for that use!!

Sure, we could keep adding 'visibility' stati to sitemap URLs (we 
already have two: internal and external) but what is the gain?

>>And performing composition thru multiple-inheritance is a really
>>terrible way to do it. Why? because you need to go very deep in
>>describing what behaviors get exposed and what are protected, otherwise
>>things get messy very fast.
> 
> Also FUD, again it depends on the language and the implementor.

Again, BS. MI would force us to deal with visibility metadata and back 
compatibility would force us to default to 'external', meaning that only 
those 'aware' of what they are doing will keep things internal unless 
really required to open it up, and the 'public' java identifier problem 
will happen all over again.

>>Also, multiple-inheritance stops further composition: you seem to
>>suggest that a block that inherit multiply is a 'leaf block', one that
>>is your own application and that will not be used by others.
>>
>>Well, one of the reasons for block design was to sparkle the creation of
>>reusable application components without people to think much about them:
>>multiple-inheritance yields horizontal behavior changes to the inherited
>>components, which means that if I have block A inherit block B and then
>>block C that wants to use A but was already using B, but A modified B's
>>behavior a little with the inheritance, you have a problem!
> 
> 
> Only if you design things to allow the problem in the first place.  If
> I'm using both blocks to start with I can specify A.foo() or B.foo()
> and pick or choose which version I want.  If I start out using only B
> and later add in A and find out I have a name space collision on foo()
> then I have an issue.
> 
> That's where the real problem lies with Cocoon blocks: unless the
> references are resolved at startup then you have the _potential_ for
> obscure run time problems as blocks get resolved dynamically.  Since
> you may not want to do startup resolution on the entire graph, I think
> the way for Cocoon to support multiple inheritance is for the default
> behaviour to be to hide all inherited capabilities and require
> explicit exposure or to always require complete paths to the function.

Exactly, and this behavior is back incompatible.

> IOW, in this example , the only way to see the A version of foo()
> would be an explicit reference to A.foo(), otherwise the reference
> would fall back to B.
> 
> 
>>I am strongly against multiple implementation inheritance for blocks,
>>because what you want to do, if you care about reusability, is really
>>multiple composition and that is achieved with being allowed to
>>implement multiple behavioral interfaces.
> 
> 
> Given that this is more-or-less completely new territory, the terms
> inheritance and composition seem to be getting in the way.  The real
> issue is how does the block language expose features from each block. 
> You're describing the language as implementing "multiple behavioral
> interfaces"; from my backgrounds POV the easiest way to do that is
> multiple inheritance.

I completely agree that it's the easiest way. My avalon experience shows 
me that composition yields more separate and much easier reusable 
components.

It's very true this is unexplored terryrory, but my gut feeling tells me 
this is the case for webapp components as well. And, as I said, I will 
stick to this until proven wrong.

>>If you *don't* care for reusability, then it's true that multiple
>>implementation inheritnace can serve as a cheaper form of composition.
>>
>>But if I had to pick between improving block reusability or ease of
>>composition, I would go with the first, hoping that tools/syntax-sugar
>>would help the second (as it happened with Java).
> 
> Well, that's almost all that it is about in this case: pure syntax. 
> If you think about what's going to have to happen under the covers the
> end result is the same either way: you need a language to describe
> which features are visible from one block to another.  If there's a
> term that is an abstraction for both inheritance and composition then
> that's what you reallly want...

that's hiding the problem under the carpet.

Polymorphic Composition is not the same as multiple inheritance even if 
they might be used to achieve the same results.

The real issue is another one and you both seem to be missing it 
entirely: multiple inheritance is easier to use, because doesn't force 
the block providers to define (and think about!) the contract between 
you and the services you require to achieve your task.

This is both its advantage and its ultimate weakness: the system is way 
more fragile because the contracts between the two block sare 'implitic'.

So, when you do

           +-(inherits from)-> block B
          /
  block A
          \
           +-(inherits from)-> block C


what you are really stating is



           +-(requires)-> service 1 <-(implements)- block B
          /
  block A
          \
           +-(requires)-> service 2 <-(implements)- block C


in java interfaces at least have method signatures that can be checked 
at compile time, Cocoon blocks won't have anything like that (the first 
that mentions BPEL will be shot!) because it's simply too hard (and 
cumbersome and useless in a local environment) to describe the behavior 
of a (potentially stateful!) service.

In such a 'weakly typed' environment, allowing people to get away with 
even "defining" what is the service (interface) that a block implements 
in order to allow service composition is suicidal.

I don't want it to be easy to 'reporpuse' existing blocks (not designed 
to be extended or used as services!!), I want it to be *HARD*.

I want it to be dead easy to write 'leaf blocks', those that you mount 
to the public and you expose as your own stuff, but as for writing 
blocks that are meant to be reused, this is another story and this 
requires you to go to the process of managing that contract between what 
you implement and what you exhibit.

And you get polymorphism for free if you do that, but polymorphism is 
not the main advantage of this: interfaces, just like in java, make 
programs more reusable and solid because they create 'awareness' of what 
is the contract between your code and the user's.

If we lose that, we are doomed to have a million blocks, and people that 
keep cutting and pasting between them to achieve what they want and 
avoid depending on somebody elses because the contracts change too fast.

Sure, unlike java, our dependencies are versioned, so some of that 
problem goes away, but the awareness of contract management is what I 
want and MI kills all that.

-- 
Stefano.


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Peter Hunsberger wrote:
> On Tue, 29 Mar 2005 11:22:35 -0500, Stefano Mazzocchi
> <st...@apache.org> wrote:
<snip/>
> That's where the real problem lies with Cocoon blocks: unless the
> references are resolved at startup then you have the _potential_ for
> obscure run time problems as blocks get resolved dynamically.  Since
> you may not want to do startup resolution on the entire graph, I think
> the way for Cocoon to support multiple inheritance is for the default
> behaviour to be to hide all inherited capabilities and require
> explicit exposure or to always require complete paths to the function.

Exactly, we could have internal and external sections of the component 
declaration in sitemap in the same way as we allready has internal and 
external pipelines. For pipelines I suggested earlier that inhertiance 
is done through a special map:mount, in that way one is explicit about 
search order and where in the uri space the blocks sitemap is mounted. 
Also I proposed that we have a special protocol for polymorphic access 
for avoiding supprises.

We could have similar constructions for component inheritance. I.e. all 
or individual components from an extended block can be added to the 
component section in an extending block, if there are several components 
with the same name in the components section, the order is significant. 
One have to explicitly ask for poymorphic behaviour for component lookup.

<snip/>

>>I am strongly against multiple implementation inheritance for blocks,
>>because what you want to do, if you care about reusability, is really
>>multiple composition and that is achieved with being allowed to
>>implement multiple behavioral interfaces.
> 
> Given that this is more-or-less completely new territory, the terms
> inheritance and composition seem to be getting in the way.

Agree, what we need to discuss is what access patterns we want to 
support between two blocks for different service types (pipelines, 
components, flow?). I guess we all agree about that a "use" access 
pattern with possibility for having internal services is needed. IMO we 
also need a polymorpic "extend" access pattern for supporting the 
"extend and overide default behaviour" style of webapp composition.

> The real
> issue is how does the block language expose features from each block.

As described above IMO this could be done on a more detailed level with 
mounts in the sitemap for exposing pipeline services and though the 
component section for exposing components.

Thinking further about it I'm quite sceptic about declaring "implements" 
and "extends" at the block level, it should be enough to declare what 
blocks it is dependent on. The exact nature of the dependence can better 
be described in the sitemap.

Of course I think that it would be cool to be able to say that a block 
depends on a number of interafaces and to be able to supply it with any 
other set of blocks that implements the interfaces. But as long as no 
one have made any concrete proposals about how to declare the behaviours 
that a certain interface contains, I wonder if it not is asking for 
trouble and all kinds of runtime errors by having "interfaces" without 
any possibillities to check the contracts.

<snip/>

/Daniel

Re: [RT] composition vs. inheritance in blocks

Posted by Peter Hunsberger <pe...@gmail.com>.
On Tue, 29 Mar 2005 11:22:35 -0500, Stefano Mazzocchi
<st...@apache.org> wrote:

<snip/>
> 
> I don't like multiple inheritance and this is not just because I learned
> OOP thru java, but because every single time I wish I had multiple
> implementation inheritance in java I found a way to go around the
> problem with single implementation inheritance that was more elegant.

I learned most of my OO with Smalltalk, Java has always seemed like a
big step backwards by comparison...

> I would go a little further and say that I believe inheritance is useful
> only when used as a 'cascading' mechanism, in any other sense is
> harmful: composition should be used instead.
> 
> Why so?
> 
> It's extremely hard to design for inheritance, a lot easier to design
> for composition.

That's FUD: a graph is a graph is a graph.  The only question is how
to expose or hide child nodes.  With composition there are no child
nodes until you add them.  With inheritance the visibility depends on
the language and the implementor.

> And performing composition thru multiple-inheritance is a really
> terrible way to do it. Why? because you need to go very deep in
> describing what behaviors get exposed and what are protected, otherwise
> things get messy very fast.

Also FUD, again it depends on the language and the implementor.

> Also, multiple-inheritance stops further composition: you seem to
> suggest that a block that inherit multiply is a 'leaf block', one that
> is your own application and that will not be used by others.
> 
> Well, one of the reasons for block design was to sparkle the creation of
> reusable application components without people to think much about them:
> multiple-inheritance yields horizontal behavior changes to the inherited
> components, which means that if I have block A inherit block B and then
> block C that wants to use A but was already using B, but A modified B's
> behavior a little with the inheritance, you have a problem!

Only if you design things to allow the problem in the first place.  If
I'm using both blocks to start with I can specify A.foo() or B.foo()
and pick or choose which version I want.  If I start out using only B
and later add in A and find out I have a name space collision on foo()
then I have an issue.

That's where the real problem lies with Cocoon blocks: unless the
references are resolved at startup then you have the _potential_ for
obscure run time problems as blocks get resolved dynamically.  Since
you may not want to do startup resolution on the entire graph, I think
the way for Cocoon to support multiple inheritance is for the default
behaviour to be to hide all inherited capabilities and require
explicit exposure or to always require complete paths to the function.

IOW, in this example , the only way to see the A version of foo()
would be an explicit reference to A.foo(), otherwise the reference
would fall back to B.

> I am strongly against multiple implementation inheritance for blocks,
> because what you want to do, if you care about reusability, is really
> multiple composition and that is achieved with being allowed to
> implement multiple behavioral interfaces.

Given that this is more-or-less completely new territory, the terms
inheritance and composition seem to be getting in the way.  The real
issue is how does the block language expose features from each block. 
You're describing the language as implementing "multiple behavioral
interfaces"; from my backgrounds POV the easiest way to do that is
multiple inheritance.

> If you *don't* care for reusability, then it's true that multiple
> implementation inheritnace can serve as a cheaper form of composition.
> 
> But if I had to pick between improving block reusability or ease of
> composition, I would go with the first, hoping that tools/syntax-sugar
> would help the second (as it happened with Java).

Well, that's almost all that it is about in this case: pure syntax. 
If you think about what's going to have to happen under the covers the
end result is the same either way: you need a language to describe
which features are visible from one block to another.  If there's a
term that is an abstraction for both inheritance and composition then
that's what you reallly want...

-- 
Peter Hunsberger

Re: [RT] composition vs. inheritance in blocks

Posted by Stefano Mazzocchi <st...@apache.org>.
Daniel Fagerstrom wrote:

damn, hit sent too early.

>> If you *don't* care for reusability, then it's true that multiple 
>> implementation inheritnace can serve as a cheaper form of composition.
> 
> For the majority of Cocoon users I would assume that blocks that are 
> possible to extend and override is easier to reuse (considered that they 
> have a good design of course), than just a lump of components and 
> stylesheets.

what the hell are you talking about? the problem on the table is 
multiple inheritance, not how granular the services the blocks offer are.

There is *NOTHING* that indicates that if you had MI or not the blocks 
will be more or less granular.

>> But if I had to pick between improving block reusability or ease of 
>> composition, I would go with the first, hoping that tools/syntax-sugar 
>> would help the second (as it happened with Java).
> 
> It's not either or. It's not exactly rocket science to build a mechanism 
> for mutiple inheritance so we can have booth.

> We just need to discuss what we want to achieve and how to achive it to 
> get it right.

I consider multiple inheritance for blocks FS: YAGNI!

Show me *one* example where single inheritance and multiple interface 
composition can't echieve what you want to achieve and I'll change my 
mind, but until then I'm stongly -1 on MI for blocks.

-- 
Stefano.


Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Peter Hunsberger <pe...@gmail.com>.
On Apr 4, 2005 11:16 AM, Daniel Fagerstrom <da...@nada.kth.se> wrote:
> Peter Hunsberger wrote:
> 
> >On Apr 4, 2005 10:26 AM, Daniel Fagerstrom <da...@nada.kth.se> wrote:
> >
> >
> >>Pier Fumagalli wrote:
> >>
> >>
> >>
> >>>On 31 Mar 2005, at 01:26, Stefano Mazzocchi wrote:
> >>>
> >>>
> >
> ><snip/>
> >
> >
> >
> >>As all URI discussions tend to provoke strong feelings for Stefano, it's
> >>best to say directly that this question is not important enough for me
> >>to fight about ;)
> >>
> >>But anyway, whether we go for an opaque custom protocol or base the
> >>block protocol on hierachial URIs we need to get into the specifics for
> >>the block URI scheme to be able to implement it.
> >>
> >>WDYT?
> >>
> >>
> >
> >He, he...  The more I look at this the more I wonder if maybe it
> >really isn't crazy to allow blocks to specify a resolver intercept
> >scheme.  Just lift the code directly out of mod-rewrite/mod-redirect
> >and let a block tell Cocoon what URI's have special concerns:
> >
> ><resolver>match spec</resolver>
> >
> >then you can go either way...
> >
> >
> I'm not following you, we already has source factories, so we can make
> our resolver as special as we want to. The question was rather if we
> should make them less special by using java.net.URI. Or do you have
> something else in mind?

Basically, the idea is to have a way for a block to say to treat a
given set of URI's in a special manner by performing a remapping on
them.  That way the incoming  request can be generic and transformed
into something block specific _before_ it hits the source factory. 
Eg, being able to say that

  http://site.com/foo/bar.css

ends up as:

   block:/foo/bar.css

where as:

    ../bar.css

gets passed through to Cocoon untouched, or vice versa, depending on
the needs of the block and the block user.  Perhaps this might be
better expressed as a "remap" directive than a "resolve" directive...

-- 
Peter Hunsberger

Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Peter Hunsberger wrote:

>On Apr 4, 2005 10:26 AM, Daniel Fagerstrom <da...@nada.kth.se> wrote:
>  
>
>>Pier Fumagalli wrote:
>>
>>    
>>
>>>On 31 Mar 2005, at 01:26, Stefano Mazzocchi wrote:
>>>      
>>>
>
><snip/>
>
>  
>
>>As all URI discussions tend to provoke strong feelings for Stefano, it's
>>best to say directly that this question is not important enough for me
>>to fight about ;)
>>
>>But anyway, whether we go for an opaque custom protocol or base the
>>block protocol on hierachial URIs we need to get into the specifics for
>>the block URI scheme to be able to implement it.
>>
>>WDYT?
>>    
>>
>
>He, he...  The more I look at this the more I wonder if maybe it
>really isn't crazy to allow blocks to specify a resolver intercept
>scheme.  Just lift the code directly out of mod-rewrite/mod-redirect
>and let a block tell Cocoon what URI's have special concerns:
>
><resolver>match spec</resolver>
>
>then you can go either way...
>  
>
I'm not following you, we already has source factories, so we can make 
our resolver as special as we want to. The question was rather if we 
should make them less special by using java.net.URI. Or do you have 
something else in mind?

/Daniel


Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Peter Hunsberger <pe...@gmail.com>.
On Apr 4, 2005 10:26 AM, Daniel Fagerstrom <da...@nada.kth.se> wrote:
> Pier Fumagalli wrote:
> 
> > On 31 Mar 2005, at 01:26, Stefano Mazzocchi wrote:

<snip/>

> 
> As all URI discussions tend to provoke strong feelings for Stefano, it's
> best to say directly that this question is not important enough for me
> to fight about ;)
> 
> But anyway, whether we go for an opaque custom protocol or base the
> block protocol on hierachial URIs we need to get into the specifics for
> the block URI scheme to be able to implement it.
> 
> WDYT?

He, he...  The more I look at this the more I wonder if maybe it
really isn't crazy to allow blocks to specify a resolver intercept
scheme.  Just lift the code directly out of mod-rewrite/mod-redirect
and let a block tell Cocoon what URI's have special concerns:

<resolver>match spec</resolver>

then you can go either way...

-- 
Peter Hunsberger

Re: Multiple block instances

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Reinhard Poetz wrote:

> Daniel Fagerstrom wrote:
>
>>>> Another case is if we follow the method of handling the profile 
>>>> info for a portal block that Reinhard proposed. If we want to use 
>>>> two portals under the same Cocoon the portal block will be deployed 
>>>> in two instances with different implementations of the profile 
>>>> contract. Also here is the question is how we differ between the 
>>>> two instances.
>>>
>>>
>>>
>>> Let's assume that you want to deploy two custom blocks that are 
>>> based on the portal block. Doing so leds to two different blocks 
>>> (--> different block IDs) which both extend the same block. Both 
>>> blocks can use the same profile block to be customized or each gets 
>>> its own - depends on your requirements.
>>
>>
>>
>> If we compare the situation with concepts from Java, my view was:
>>
>> Java: You download a class with unique combination of name and 
>> namespace.
>> Blocks: You download a block with a unique URI.
>>
>> Java: You call the constuctor of the class possibly with parameters 
>> and get an object with an unique object id.
>> Blocks: You deploy the block and get a block instance with a unique 
>> (in your Cocoon) block instance id. During deployment you give it 
>> parameter values and connect it to other block instances.
>>
>>                                     --- o0o ---
>>
>> I guess that in your view there is no istantiation, you subclass and 
>> have everything "static" instead.
>>
>> Both views will solve the same problem but in different ways. With 
>> your view we might want to have tool support for automatic 
>> subclassing ;)
>
>
> It should be as simple as writing a new block.xml and make a .cob out 
> of it. btw, I heard of some project called Lepido .... ;-)
>
> After reading your mail I thought a bit about block instances but IMO 
> they make things more difficult: where to put the 'constructor 
> parameters', URI resolving and maybe more stuff.

In my view there is nearly no extra difficulty. The BlockManager 
represents an instance and the deployment parameters and connections are 
the constructor parameters. The only differnce is that a identifier is 
generated at deploy time so that several BlockManagers can represent the 
same Block but with different parameter and connection values.

> Maybe we really need them but this will be clearified after we set up 
> some usecases using a working prototype.

Sure, it will only affect the identifier in the wiring and some 
fuctionality in the deployer. For the communication between the 
BlockManager and the BlocksManager it shouldn't matter. So its no big 
deal to change it when we see that we need it ;)

/Daniel


Re: Multiple block instances

Posted by Reinhard Poetz <re...@apache.org>.
Daniel Fagerstrom wrote:

>>> Another case is if we follow the method of handling the profile info 
>>> for a portal block that Reinhard proposed. If we want to use two 
>>> portals under the same Cocoon the portal block will be deployed in 
>>> two instances with different implementations of the profile contract. 
>>> Also here is the question is how we differ between the two instances.
>>
>>
>> Let's assume that you want to deploy two custom blocks that are based 
>> on the portal block. Doing so leds to two different blocks (--> 
>> different block IDs) which both extend the same block. Both blocks can 
>> use the same profile block to be customized or each gets its own - 
>> depends on your requirements.
> 
> 
> If we compare the situation with concepts from Java, my view was:
> 
> Java: You download a class with unique combination of name and namespace.
> Blocks: You download a block with a unique URI.
> 
> Java: You call the constuctor of the class possibly with parameters and 
> get an object with an unique object id.
> Blocks: You deploy the block and get a block instance with a unique (in 
> your Cocoon) block instance id. During deployment you give it parameter 
> values and connect it to other block instances.
> 
>                                     --- o0o ---
> 
> I guess that in your view there is no istantiation, you subclass and 
> have everything "static" instead.
> 
> Both views will solve the same problem but in different ways. With your 
> view we might want to have tool support for automatic subclassing ;)


It should be as simple as writing a new block.xml and make a .cob out of it. 
btw, I heard of some project called Lepido .... ;-)

After reading your mail I thought a bit about block instances but IMO they make 
things more difficult: where to put the 'constructor parameters', URI resolving 
and maybe more stuff. Maybe we really need them but this will be clearified 
after we set up some usecases using a working prototype.

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: Multiple block instances

Posted by Ralph Goers <Ra...@dslextreme.com>.
Daniel Fagerstrom wrote:

> If we compare the situation with concepts from Java, my view was:
>
> Java: You download a class with unique combination of name and namespace.
> Blocks: You download a block with a unique URI.
>
> Java: You call the constuctor of the class possibly with parameters 
> and get an object with an unique object id.
> Blocks: You deploy the block and get a block instance with a unique 
> (in your Cocoon) block instance id. During deployment you give it 
> parameter values and connect it to other block instances.

This depends on whether the Java class is a singleton, in which case the 
constructor is called only when the class is instantiated the first 
time.  The same could be true for blocks as well, if that is desirable.  
It probably would be more manaageable if the first release required that 
blocks be singletons and then expand that later if needed.  Isn't that 
basically the way servlets work?

>
>
>                                     --- o0o ---
>
> I guess that in your view there is no istantiation, you subclass and 
> have everything "static" instead.

Being a singleton doesn't mean that you can't have some initialization.

>
> Both views will solve the same problem but in different ways. With 
> your view we might want to have tool support for automatic subclassing ;)
>
> /Daniel
>


Re: Multiple block instances

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Reinhard Poetz wrote:

> Daniel Fagerstrom wrote:
>
>> Consider the following case: One of my applications use a repository 
>> block, and this repository block has a db connection with name and 
>> password as deplyment parameters. If another application need to use 
>> the same repository block, but connected to another db it will have 
>> other deployment parameters. In this case we will have two deployed 
>> instances of the same block with different deployment parameters. How 
>> do we differ between them.
>
>
> If you need different behaviour of one block you will have to extend 
> it (so it gets another unique ID) and only change the properties in 
> block.xml.

ok.

> (Although I think that this isn't a good example because it's not a 
> consuming block's concern to set the database connection IMO).

Didn't suggest that. What I described above was supposed to happen at 
deploy time. The two applications only know that they talk with a block 
that fullfills the repository contract.

>> Another case is if we follow the method of handling the profile info 
>> for a portal block that Reinhard proposed. If we want to use two 
>> portals under the same Cocoon the portal block will be deployed in 
>> two instances with different implementations of the profile contract. 
>> Also here is the question is how we differ between the two instances.
>
> Let's assume that you want to deploy two custom blocks that are based 
> on the portal block. Doing so leds to two different blocks (--> 
> different block IDs) which both extend the same block. Both blocks can 
> use the same profile block to be customized or each gets its own - 
> depends on your requirements.

If we compare the situation with concepts from Java, my view was:

Java: You download a class with unique combination of name and namespace.
Blocks: You download a block with a unique URI.

Java: You call the constuctor of the class possibly with parameters and 
get an object with an unique object id.
Blocks: You deploy the block and get a block instance with a unique (in 
your Cocoon) block instance id. During deployment you give it parameter 
values and connect it to other block instances.

                                     --- o0o ---

I guess that in your view there is no istantiation, you subclass and 
have everything "static" instead.

Both views will solve the same problem but in different ways. With your 
view we might want to have tool support for automatic subclassing ;)

/Daniel


Multiple block instances

Posted by Reinhard Poetz <re...@apache.org>.
Daniel Fagerstrom wrote:

> Consider the following case: One of my applications use a repository 
> block, and this repository block has a db connection with name and 
> password as deplyment parameters. If another application need to use the 
> same repository block, but connected to another db it will have other 
> deployment parameters. In this case we will have two deployed instances 
> of the same block with different deployment parameters. How do we differ 
> between them.

If you need different behaviour of one block you will have to extend it (so it 
gets another unique ID) and only change the properties in block.xml.
(Although I think that this isn't a good example because it's not a consuming 
block's concern to set the database connection IMO).

> 
> Another case is if we follow the method of handling the profile info for 
> a portal block that Reinhard proposed. If we want to use two portals 
> under the same Cocoon the portal block will be deployed in two instances 
> with different implementations of the profile contract. Also here is the 
> question is how we differ between the two instances.


Let's assume that you want to deploy two custom blocks that are based on the 
portal block. Doing so leds to two different blocks (--> different block IDs) 
which both extend the same block. Both blocks can use the same profile block to 
be customized or each gets its own - depends on your requirements.

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] The block protocol

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Stefano Mazzocchi wrote:

> Daniel Fagerstrom wrote:
>
>> Stefano Mazzocchi wrote:
>>
>>> I disagree. You have a world-wide unique identifier (the URI) and a 
>>> local name in a well isolated context,  and a wiring table to glue 
>>> these together (using the URIs) that's all you need.
>>
>>
>> Consider the following case: One of my applications use a repository 
>> block, and this repository block has a db connection with name and 
>> password as deplyment parameters. If another application need to use 
>> the same repository block, but connected to another db it will have 
>> other deployment parameters. In this case we will have two deployed 
>> instances of the same block with different deployment parameters. How 
>> do we differ between them.
>
>
> Context.
>
> Here is your problem:
>
>  [ Block A -(requires)-> Block C ] -(named)-> 'database'
>  [ Block B -(requires)-> Block C ] -(named)-> 'database'
>
> this is the 'structure' of the dependency, not your actual instance.
>
> When you install Block A, the block deployer (thanks Reinhard for 
> correcting me) will look for Block C (let's not dicuss the 'how' of 
> this now).
>
> The block will be fetched, unpacked, configured and wired. At this 
> point, Block C will become known (to A!) as "database" and from the 
> block A, you can call "block:database:/" and that *instance* of block 
> C will respond.
>
> Note that since java classloading is already namespaced, you *DO NOT* 
> need to provide a block hint for the classloading: if Block C provides 
> a class called
>
>  org.myhost.myapp.myblock.Database
>
> you flowscript in block A can call
>
>  cocoon.getComponent("org.myhost.myapp.myblock.Database")
>
> and obtain that *instance*, configured as you wanted at installation 
> time (here, you will be asked for username/password/jdbc-url etc.).
>
> Now, later on, you install Block B, which requires an instance of 
> Block C. You already have one installed, so the block deployer will 
> ask you if you want to reuse that instance or another one.
>
> at this point, if you want to use another instance (keep the code, but 
> change the behavior thru different configurations!), the block manager 
> (and its internal classloader and sitemap mounter) will make sure that 
> if you call block:database:/ from block B, you end up in *another* 
> instance, with different configurations and different parameters.
>
Yes, sounds good.

/Daniel


Re: [RT] The block protocol

Posted by Stefano Mazzocchi <st...@apache.org>.
Daniel Fagerstrom wrote:
> Stefano Mazzocchi wrote:
>
>> I disagree. You have a world-wide unique identifier (the URI) and a 
>> local name in a well isolated context,  and a wiring table to glue 
>> these together (using the URIs) that's all you need.
> 
> Consider the following case: One of my applications use a repository 
> block, and this repository block has a db connection with name and 
> password as deplyment parameters. If another application need to use the 
> same repository block, but connected to another db it will have other 
> deployment parameters. In this case we will have two deployed instances 
> of the same block with different deployment parameters. How do we differ 
> between them.

Context.

Here is your problem:

  [ Block A -(requires)-> Block C ] -(named)-> 'database'
  [ Block B -(requires)-> Block C ] -(named)-> 'database'

this is the 'structure' of the dependency, not your actual instance.

When you install Block A, the block deployer (thanks Reinhard for 
correcting me) will look for Block C (let's not dicuss the 'how' of this 
now).

The block will be fetched, unpacked, configured and wired. At this 
point, Block C will become known (to A!) as "database" and from the 
block A, you can call "block:database:/" and that *instance* of block C 
will respond.

Note that since java classloading is already namespaced, you *DO NOT* 
need to provide a block hint for the classloading: if Block C provides a 
class called

  org.myhost.myapp.myblock.Database

you flowscript in block A can call

  cocoon.getComponent("org.myhost.myapp.myblock.Database")

and obtain that *instance*, configured as you wanted at installation 
time (here, you will be asked for username/password/jdbc-url etc.).

Now, later on, you install Block B, which requires an instance of Block 
C. You already have one installed, so the block deployer will ask you if 
you want to reuse that instance or another one.

at this point, if you want to use another instance (keep the code, but 
change the behavior thru different configurations!), the block manager 
(and its internal classloader and sitemap mounter) will make sure that 
if you call block:database:/ from block B, you end up in *another* 
instance, with different configurations and different parameters.

-- 
Stefano.


Re: [RT] The block protocol

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Stefano Mazzocchi wrote:

> Daniel Fagerstrom wrote:

<snip/>

>>>> in the connection section, where 
>>>> "http://mycompany.com/skins/corporate/34.3.345" uniquely identifies 
>>>> the specific skin implementation that has been choosen at deploy time.
>>>>
>>>> <comment>
>>>> Is the URI unique enough? What if I want several variants of the 
>>>> skin that has different deployment parameters and implementations 
>>>> of theire connections.
>>>
>>> IIRC, URI is generated, at that time uniqueness is guaranteed by 
>>> BlocksManager (who created the URI).
>>
>>   From http://wiki.apache.org/cocoon/BlockIdentification, I get the 
>> impression that URI is "universal" rather than locally generated at 
>> deploy time. I agree that a unique identifier created at deploy time 
>> by the BlocksManager is needed.
>
> I disagree. You have a world-wide unique identifier (the URI) and a 
> local name in a well isolated context,  and a wiring table to glue 
> these together (using the URIs) that's all you need.

Consider the following case: One of my applications use a repository 
block, and this repository block has a db connection with name and 
password as deplyment parameters. If another application need to use the 
same repository block, but connected to another db it will have other 
deployment parameters. In this case we will have two deployed instances 
of the same block with different deployment parameters. How do we differ 
between them.

Another case is if we follow the method of handling the profile info for 
a portal block that Reinhard proposed. If we want to use two portals 
under the same Cocoon the portal block will be deployed in two instances 
with different implementations of the profile contract. Also here is the 
question is how we differ between the two instances.

>>>> </comment>
>>>>
>>>> Interesting enough, IIUC, blocks are only accessible through the 
>>>> block protocol from other blocks,
>>>
>>> No; IMHO they are all available through BlocksManager.
>>
> Well, no. The BlockManager has block 'scopes' and should allow a block 
> to resolve only the blocks that it explicitly depended upon and for 
> which it has a name for. The rest is just like it wasn't there... and 
> this is required to avoid polymorphism without unwanted collisions.
>
>> They are, but AFAICS they have no common short name that could be 
>> used outside blocks, and it is the short name that is used by the 
>> block protocol.
>
> Exactly.
>
>> This could be solved by considering the main sitemap being part of a 
>> block as well and have a (possibly optional) block descriptor for it. 
>> Then the blocks would have a short name from the main sitemap as well.
>
> YAGNI: if you need a block, declare that you need it and associate a 
> name with it. Otherwise, you don't need it, you don't have access to it.
>
With declaring it, do you mean that we have a block deployment 
descriptor that is connected to the main sitemap?

/Daniel


Re: [RT] The block protocol

Posted by Stefano Mazzocchi <st...@apache.org>.
Daniel Fagerstrom wrote:

>> You probably meant here "BlocksManager"
> 
> 
> No I meant BlockManager. In my discussion I assumed that a BlockManager 
> is responsible for the information within a block element in the wiring 
> (http://wiki.apache.org/cocoon/BlocksWiring) and that the BlocksManager 
> "correspond" to the blocks element. So from this the BlocksManager only 
> know the URI that identifies the block. The mapping from a short name to 
> the URI
> 
>  skin -> http://mycompany.com/skins/corporate/34.3.345
> 
> is only known localy whithin a BlockManager. The situation is AFAIU 
> analoguos with the relation between a namespace URI and a namespace 
> prefix. Where the URI is a universal identifier and the prefix works as 
> a identifier within the document. In the same way the blocks URI is a 
> universal identifier of the block while the short name only identifies 
> it whithin a certain block and the wiring for the block is like a 
> namespace declaration. Different blocks can access the same block with 
> different short names.

This is correct.

> I think this design is necessary for achieving scalability. If the short 
> name was assumed to be unique, we would get name clashes between 
> external blocks developers.

Absolutely: URI gets prefixed and are used only in the local wiring 
context, they lose meaning if detached from the block that uses them.

Also because the "using" block is responsible for this mapping:

  [ http://host/myBlock/3.4.34 -(requires)-> http://blah/skin/2.3 ]
      --(calls it)--> "skin"

so, block:skin: used inside http://host/myBlock/3.4.34 will point to 
whatever http://blah/skin/2.3 implementation you decided to wire it to, 
but block:skin: used somewhere might route somewhere else.

So, "skin" has no absolute meaning, just local and it's still a solid 
contract because it's defined by the requiring block, which is the only 
one using and in-control-of that name.

>>> resolves it by looking up "skin" in the wiring info for the block 
>>> (http://wiki.apache.org/cocoon/BlocksWiring) and find the mapping:
>>>
>>>   skin -> http://mycompany.com/skins/corporate/34.3.345
>>
>>
>>
>> Beside mapping, BlocksManager can fetch an instance of the referenced 
>> Block, i.e. its BlockManager. Not sure if URI by itself is needed at all.
> 
> 
> The BlockManagers could be wired to get direct access to each other 
> during start up. In that case we don't need a global identifier during 
> execution. I prefered to make all communication between the blocks 
> proxied by the BlocksManager in the interest of isolation. But it is 
> more of an implementation detail. Isolation can be achieved in other ways.

You don't need global block identifiers other than their URIs (which are 
meant to be 'globally' unique, not just locally).

>>> in the connection section, where 
>>> "http://mycompany.com/skins/corporate/34.3.345" uniquely identifies 
>>> the specific skin implementation that has been choosen at deploy time.
>>>
>>> <comment>
>>> Is the URI unique enough? What if I want several variants of the skin 
>>> that has different deployment parameters and implementations of 
>>> theire connections.
>>
>>
>>
>> IIRC, URI is generated, at that time uniqueness is guaranteed by 
>> BlocksManager (who created the URI).
> 
> 
>  From http://wiki.apache.org/cocoon/BlockIdentification, I get the 
> impression that URI is "universal" rather than locally generated at 
> deploy time. I agree that a unique identifier created at deploy time by 
> the BlocksManager is needed.

I disagree. You have a world-wide unique identifier (the URI) and a 
local name in a well isolated context,  and a wiring table to glue these 
together (using the URIs) that's all you need.

>>> </comment>
>>>
>>> Interesting enough, IIUC, blocks are only accessible through the 
>>> block protocol from other blocks,
>>
>>
>> No; IMHO they are all available through BlocksManager.

Well, no. The BlockManager has block 'scopes' and should allow a block 
to resolve only the blocks that it explicitly depended upon and for 
which it has a name for. The rest is just like it wasn't there... and 
this is required to avoid polymorphism without unwanted collisions.

> They are, but AFAICS they have no common short name that could be used 
> outside blocks, and it is the short name that is used by the block 
> protocol.

Exactly.

> This could be solved by considering the main sitemap being part of a 
> block as well and have a (possibly optional) block descriptor for it. 
> Then the blocks would have a short name from the main sitemap as well.

YAGNI: if you need a block, declare that you need it and associate a 
name with it. Otherwise, you don't need it, you don't have access to it.

-- 
Stefano.


Re: [RT] The block protocol

Posted by Vadim Gritsenko <va...@reverycodes.com>.
Daniel Fagerstrom wrote:
> Vadim Gritsenko wrote:
> 
>> Daniel Fagerstrom wrote:
>>
>>> Inter block access
>>> ------------------
>>>
>>> An URI to another block "skin" e.g. looks like:
>>>
>>>   block:skin:/foo/bar
>>>
>>> the BlockManager
>>
>>
>> You probably meant here "BlocksManager"
> 
> 
> No I meant BlockManager. In my discussion I assumed that a BlockManager 
> is responsible for the information within a block element in the wiring 
> (http://wiki.apache.org/cocoon/BlocksWiring) and that the BlocksManager 
> "correspond" to the blocks element. So from this the BlocksManager only 
> know the URI that identifies the block. The mapping from a short name to 
> the URI
> 
>  skin -> http://mycompany.com/skins/corporate/34.3.345
> 
> is only known localy whithin a BlockManager.

Yes, you are right. See my prev email about portal / profile block: portal knows 
which profile it wants (URI), and BlocksManager can resolve block instance using 
URI.


> The situation is AFAIU 
> analoguos with the relation between a namespace URI and a namespace 
> prefix. Where the URI is a universal identifier and the prefix works as 
> a identifier within the document. In the same way the blocks URI is a 
> universal identifier of the block while the short name only identifies 
> it whithin a certain block and the wiring for the block is like a 
> namespace declaration. Different blocks can access the same block with 
> different short names.

Yep


>>> resolves it by looking up "skin" in the wiring info for the block 
>>> (http://wiki.apache.org/cocoon/BlocksWiring) and find the mapping:
>>>
>>>   skin -> http://mycompany.com/skins/corporate/34.3.345

Now we are on the same page. So BlockManager (or something else on its behalf - 
like Wiring) looks up URI by the short name.


> The BlockManagers could be wired to get direct access to each other 
> during start up. In that case we don't need a global identifier during 
> execution. I prefered to make all communication between the blocks 
> proxied by the BlocksManager in the interest of isolation.

Yes, once URI known, BlockManager should ask for other block instance from 
BlocksManager (which might be as simple as this.manager.lookup()).


>>> in the connection section, where 
>>> "http://mycompany.com/skins/corporate/34.3.345" uniquely identifies 
>>> the specific skin implementation that has been choosen at deploy time.
>>>
>>> <comment>
>>> Is the URI unique enough? What if I want several variants of the skin 
>>> that has different deployment parameters and implementations of 
>>> theire connections.
>>
>>
>> IIRC, URI is generated, at that time uniqueness is guaranteed by 
>> BlocksManager (who created the URI).
> 
> 
> From http://wiki.apache.org/cocoon/BlockIdentification, I get the 
> impression that URI is "universal" rather than locally generated at 
> deploy time.

Yes, my recall was wrong :-)


>>> </comment>
>>>
>>> Interesting enough, IIUC, blocks are only accessible through the 
>>> block protocol from other blocks,
>>
>>
>> No; IMHO they are all available through BlocksManager.
> 
> 
> They are, but AFAICS they have no common short name that could be used 
> outside blocks, and it is the short name that is used by the block 
> protocol.

Which is resolved to URI which can be used to get a block from BlocksManager as 
described above.


> This could be solved by considering the main sitemap being part of a 
> block as well and have a (possibly optional) block descriptor for it. 
> Then the blocks would have a short name from the main sitemap as well.

I thought about it... If there is a root block, then there will be *no* root 
sitemap. As I see it, either you deploy root block (new behaviour), or you have 
root sitemap (old one) which then can mount blocks as needed.


Vadim


Re: [RT] The block protocol

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Vadim Gritsenko wrote:

> Daniel Fagerstrom wrote:
>
>>                             --- o0o ---
>
>
> </lurk>
> Just some sidenotes...
>
>> The main involved components are the BlocksManager that in turn has 
>> access to one BlockManager for each block.
>
>
> (From [1] BlockManager is the ServiceManager of the block)

Yes it is. We need to discuss the details about component managment in 
blocks also. My mail was only about the block protocol aspect of the 
architecture.

>> Block local access
>> ------------------
>>
>> Each BlockManager has its own SourceResolver and especially it can 
>> have its own implementation of the block protocol which is registred 
>> with the scheme "block:".
>>
>> An absolute URI relative to the root sitemap of the block looks like:
>>
>>   block:/foo/bar
>>
>> and is a hierarchical URI. It is invoked by first trying "foo/bar" in 
>> the current block's root sitemap and if that fails 
>> "block:super:/foo/bar" is invoked.
>
>
> You don't need that. As mentioned in [1], local BlockManager has 
> access to the parent BlockManager, so local BlockSource instance will 
> lookup parent BlockSource and delegate to it. (Or may be this is just 
> another way of saying the same? Hm.)

I think we mean the same.

>> More about "block:super:" later. To make this work I would assume 
>> that error handling must work a little bit different in blocks so 
>> that a sitemap can fail without emmiting any error messages immediatly.
>
> That's the only behaviour available in 2.1.6 and below.

Ok.

>> In the case when a block A has invoked an URI in its super block B, 
>> to achieve polymorphism, all block protocoll resolution in B must be 
>> done by first asking A's block resolver before trying its own.
>
>
> So it means local SourceResolver (or it's settings) should be 
> preserved for the duration of polymorphic source processing.

Yes.

>> A relative URI in a sub sitemap "/foo" from the block's root sitemap,
>>
>>   block:./bar
>>
>> (an opaque URI) is resolved to
>>
>>   block:/foo/bar
>>
>> using the same method as Pier used for the cocoon protocol in his Wiki.
>>
>> Inter block access
>> ------------------
>>
>> An URI to another block "skin" e.g. looks like:
>>
>>   block:skin:/foo/bar
>>
>> the BlockManager
>
> You probably meant here "BlocksManager"

No I meant BlockManager. In my discussion I assumed that a BlockManager 
is responsible for the information within a block element in the wiring 
(http://wiki.apache.org/cocoon/BlocksWiring) and that the BlocksManager 
"correspond" to the blocks element. So from this the BlocksManager only 
know the URI that identifies the block. The mapping from a short name to 
the URI

  skin -> http://mycompany.com/skins/corporate/34.3.345

is only known localy whithin a BlockManager. The situation is AFAIU 
analoguos with the relation between a namespace URI and a namespace 
prefix. Where the URI is a universal identifier and the prefix works as 
a identifier within the document. In the same way the blocks URI is a 
universal identifier of the block while the short name only identifies 
it whithin a certain block and the wiring for the block is like a 
namespace declaration. Different blocks can access the same block with 
different short names.

I think this design is necessary for achieving scalability. If the short 
name was assumed to be unique, we would get name clashes between 
external blocks developers.

>> resolves it by looking up "skin" in the wiring info for the block 
>> (http://wiki.apache.org/cocoon/BlocksWiring) and find the mapping:
>>
>>   skin -> http://mycompany.com/skins/corporate/34.3.345
>
>
> Beside mapping, BlocksManager can fetch an instance of the referenced 
> Block, i.e. its BlockManager. Not sure if URI by itself is needed at all.

The BlockManagers could be wired to get direct access to each other 
during start up. In that case we don't need a global identifier during 
execution. I prefered to make all communication between the blocks 
proxied by the BlocksManager in the interest of isolation. But it is 
more of an implementation detail. Isolation can be achieved in other ways.

>> in the connection section, where 
>> "http://mycompany.com/skins/corporate/34.3.345" uniquely identifies 
>> the specific skin implementation that has been choosen at deploy time.
>>
>> <comment>
>> Is the URI unique enough? What if I want several variants of the skin 
>> that has different deployment parameters and implementations of 
>> theire connections.
>
>
> IIRC, URI is generated, at that time uniqueness is guaranteed by 
> BlocksManager (who created the URI).

 From http://wiki.apache.org/cocoon/BlockIdentification, I get the 
impression that URI is "universal" rather than locally generated at 
deploy time. I agree that a unique identifier created at deploy time by 
the BlocksManager is needed.

>> </comment>
>>
>> Interesting enough, IIUC, blocks are only accessible through the 
>> block protocol from other blocks,
>
> No; IMHO they are all available through BlocksManager.

They are, but AFAICS they have no common short name that could be used 
outside blocks, and it is the short name that is used by the block protocol.

This could be solved by considering the main sitemap being part of a 
block as well and have a (possibly optional) block descriptor for it. 
Then the blocks would have a short name from the main sitemap as well.

>> as the short name, "skin" e.g., only exists in the block wiring info. 
>> Are we going to consider the main sitemap part of a block as well to 
>> be able to access blocks from it?
>
> (I did not get this question).

Is it clearer from my explanations above.

>> Next the block manager asks the blocks manager for the URI,
>
> Nope. No need - it can simply ask for BlockManager.
>
>> this could be done through a "blocks:" protocol that is connected to 
>> the blocks manager. The uri "block:skin:/foo/bar" could be resolved 
>> to e.g.:
>>
>>   blocks:{http://mycompany.com/skins/corporate/34.3.345}:/foo/bar
>>
>> Besides that it looks awfull I would doubt that it even is synatactic 
>> correct as an opaque URI. I only wrote it down to provoke you to find 
>> something better ;)
>
> IMHO, it (BlockManager) does not need URI of another block, at all. So 
> no need for writing awful URIs :-P

See above.

>> Next the blocks manager looks up the block manager identified by 
>> "http://mycompany.com/skins/corporate/34.3.345" and send the URI:
>>
>>   block:/foo/bar
>>
>> to it, which will be resolved by the skin blocks internal 
>> implementation of the block protocol.
>
> Yep.
>
>>   block:super:/foo/bar
>>
>> is resolved in the same way as an ordinary external block URI. To 
>> make this possible the role of being a super block must be 
>> identifiable among the connections in the wiring info. Maybe by 
>> reserving the name "super" for this case.
>>
>> WDYT?
>>
>> /Daniel
>
> Vadim
> <lurk>
>
> [1] http://wiki.apache.org/cocoon/22BlockImplementation

/Daniel


Re: [RT] The block protocol

Posted by Vadim Gritsenko <va...@reverycodes.com>.
Daniel Fagerstrom wrote:
>                             --- o0o ---

</lurk>
Just some sidenotes...

> The main involved components are the BlocksManager that in turn has 
> access to one BlockManager for each block.

(From [1] BlockManager is the ServiceManager of the block)


> Block local access
> ------------------
> 
> Each BlockManager has its own SourceResolver and especially it can have 
> its own implementation of the block protocol which is registred with the 
> scheme "block:".
> 
> An absolute URI relative to the root sitemap of the block looks like:
> 
>   block:/foo/bar
> 
> and is a hierarchical URI. It is invoked by first trying "foo/bar" in 
> the current block's root sitemap and if that fails 
> "block:super:/foo/bar" is invoked.

You don't need that. As mentioned in [1], local BlockManager has access to the 
parent BlockManager, so local BlockSource instance will lookup parent 
BlockSource and delegate to it. (Or may be this is just another way of saying 
the same? Hm.)


> More about "block:super:" later. To 
> make this work I would assume that error handling must work a little bit 
> different in blocks so that a sitemap can fail without emmiting any 
> error messages immediatly.

That's the only behaviour available in 2.1.6 and below.


> In the case when a block A has invoked an URI in its super block B, to 
> achieve polymorphism, all block protocoll resolution in B must be done 
> by first asking A's block resolver before trying its own.

So it means local SourceResolver (or it's settings) should be preserved for the 
duration of polymorphic source processing.


> A relative URI in a sub sitemap "/foo" from the block's root sitemap,
> 
>   block:./bar
> 
> (an opaque URI) is resolved to
> 
>   block:/foo/bar
> 
> using the same method as Pier used for the cocoon protocol in his Wiki.
> 
> Inter block access
> ------------------
> 
> An URI to another block "skin" e.g. looks like:
> 
>   block:skin:/foo/bar
> 
> the BlockManager

You probably meant here "BlocksManager"


> resolves it by looking up "skin" in the wiring info for 
> the block (http://wiki.apache.org/cocoon/BlocksWiring) and find the 
> mapping:
> 
>   skin -> http://mycompany.com/skins/corporate/34.3.345

Beside mapping, BlocksManager can fetch an instance of the referenced Block, 
i.e. its BlockManager. Not sure if URI by itself is needed at all.


> in the connection section, where 
> "http://mycompany.com/skins/corporate/34.3.345" uniquely identifies the 
> specific skin implementation that has been choosen at deploy time.
> 
> <comment>
> Is the URI unique enough? What if I want several variants of the skin 
> that has different deployment parameters and implementations of theire 
> connections.

IIRC, URI is generated, at that time uniqueness is guaranteed by BlocksManager 
(who created the URI).


> </comment>
> 
> Interesting enough, IIUC, blocks are only accessible through the block 
> protocol from other blocks,

No; IMHO they are all available through BlocksManager.


> as the short name, "skin" e.g., only exists 
> in the block wiring info. Are we going to consider the main sitemap part 
> of a block as well to be able to access blocks from it?

(I did not get this question).


> Next the block manager asks the blocks manager for the URI,

Nope. No need - it can simply ask for BlockManager.


> this could 
> be done through a "blocks:" protocol that is connected to the blocks 
> manager. The uri "block:skin:/foo/bar" could be resolved to e.g.:
> 
>   blocks:{http://mycompany.com/skins/corporate/34.3.345}:/foo/bar
> 
> Besides that it looks awfull I would doubt that it even is synatactic 
> correct as an opaque URI. I only wrote it down to provoke you to find 
> something better ;)

IMHO, it (BlockManager) does not need URI of another block, at all. So no need 
for writing awful URIs :-P


> Next the blocks manager looks up the block manager identified by 
> "http://mycompany.com/skins/corporate/34.3.345" and send the URI:
> 
>   block:/foo/bar
> 
> to it, which will be resolved by the skin blocks internal implementation 
> of the block protocol.

Yep.


>   block:super:/foo/bar
> 
> is resolved in the same way as an ordinary external block URI. To make 
> this possible the role of being a super block must be identifiable among 
> the connections in the wiring info. Maybe by reserving the name "super" 
> for this case.
> 
> WDYT?
> 
> /Daniel

Vadim
<lurk>

[1] http://wiki.apache.org/cocoon/22BlockImplementation

Re: [RT] The block protocol

Posted by Stefano Mazzocchi <st...@apache.org>.
Reinhard Poetz wrote:
> Vadim Gritsenko wrote:
> 
>> Reinhard Poetz wrote:
>>
>>> Ralph Goers wrote:
>>>
>>>> Daniel Fagerstrom wrote:
>>>>
>>>> Portal block
>>>> ------------
>>>> - requires "MyProfile" that implements "profile"
>>
>>
>>
>> Correction:
>>
>>   - Requires implementation of "profile" interface.
>>     "profile" is implemented by "MyProfile1",
>>     "MyProfile2", ..., "MyProfileN".
>>
>>
>>>> <profiles>
>>>>  <copletbasedata-load
>>>>   uri="blocks:profile:/load-global-profile?profile=copletbasedata"/>
>>>>  <copletdata-global-load
>>>>   uri="blocks:profile:/load-global-profile?profile=copletdata"/>
>>>>   ..
>>>> </profiles>
>>>>
>>>> The problem with this example is that is not how the portal works, 
>>>> nor would I ever want the portal to require that a block with a 
>>>> specific name be present as this prohibits two portal 
>>>> implementations from being present in the same webapp. 
>>>
>>>
>>>
>>>
>>> That's not true. You can deploy as many portal applications as real 
>>> blocks as you want.
>>
>>
>>
>> Yes
>>
>>
>>> And, if you don't like dependencies (references, extensions) just 
>>> don't use them.
>>
>>
>>
>> And No. If portal block requires implementation of profile block, 
>> during its deployment time you will pick up an implementation you like 
>> for each instance of portal block.
> 
> 
> ... stand corrected
> 
> and you have always the chance that you can do it the same way as it is 
> done now: simply copy everything that you need into your own application.
> 
> If people really want this, the portal block could have a "base" version 
> that only contains the components (e.g. the PortalGenerator) and a 
> "default" version that extends the base version and requires a "profile" 
> block.
> 
> Then people who like blocks and that functionality is spreat over 
> several blocks extend the "default" version and people who don't want to 
> change the way how they work with Cocoon, use the "base" block that only 
> contains components.

There are two concerns here, not totally unrelated, but enough so:

  1) what features should the block system have

  2) what is the best way to use those features in order to achieve what 
I need

We have a pretty good understanding of 1) (and meets *all* the 
requirements that I came across so far!) but have no idea on best 
practices for 2)

I would strongly suggest we avoid discussing #2 before we even implement 
#1 to test it out.

Obviously, the two cannot be completely isolated, because #1 influences 
#2 and problems in #2 should influence back #1, so the cycle will be 
iterative, but for now, let's focus on what we understand of #1 and move 
on until we have a better understanding of the problems on #2.

-- 
Stefano.


Re: [RT] The block protocol

Posted by Reinhard Poetz <re...@apache.org>.
Vadim Gritsenko wrote:
> Reinhard Poetz wrote:
> 
>> Ralph Goers wrote:
>>
>>> Daniel Fagerstrom wrote:
>>>
>>> Portal block
>>> ------------
>>> - requires "MyProfile" that implements "profile"
> 
> 
> Correction:
> 
>   - Requires implementation of "profile" interface.
>     "profile" is implemented by "MyProfile1",
>     "MyProfile2", ..., "MyProfileN".
> 
> 
>>> <profiles>
>>>  <copletbasedata-load
>>>   uri="blocks:profile:/load-global-profile?profile=copletbasedata"/>
>>>  <copletdata-global-load
>>>   uri="blocks:profile:/load-global-profile?profile=copletdata"/>
>>>   ..
>>> </profiles>
>>>
>>> The problem with this example is that is not how the portal works, 
>>> nor would I ever want the portal to require that a block with a 
>>> specific name be present as this prohibits two portal implementations 
>>> from being present in the same webapp. 
>>
>>
>>
>> That's not true. You can deploy as many portal applications as real 
>> blocks as you want.
> 
> 
> Yes
> 
> 
>> And, if you don't like dependencies (references, extensions) just 
>> don't use them.
> 
> 
> And No. If portal block requires implementation of profile block, during 
> its deployment time you will pick up an implementation you like for each 
> instance of portal block.

... stand corrected

and you have always the chance that you can do it the same way as it is done 
now: simply copy everything that you need into your own application.

If people really want this, the portal block could have a "base" version that 
only contains the components (e.g. the PortalGenerator) and a "default" version 
that extends the base version and requires a "profile" block.

Then people who like blocks and that functionality is spreat over several blocks 
extend the "default" version and people who don't want to change the way how 
they work with Cocoon, use the "base" block that only contains components.

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] The block protocol

Posted by Vadim Gritsenko <va...@reverycodes.com>.
Reinhard Poetz wrote:
> Ralph Goers wrote:
> 
>> Daniel Fagerstrom wrote:
>>
>> Portal block
>> ------------
>> - requires "MyProfile" that implements "profile"

Correction:

   - Requires implementation of "profile" interface.
     "profile" is implemented by "MyProfile1",
     "MyProfile2", ..., "MyProfileN".


>> <profiles>
>>  <copletbasedata-load
>>   uri="blocks:profile:/load-global-profile?profile=copletbasedata"/>
>>  <copletdata-global-load
>>   uri="blocks:profile:/load-global-profile?profile=copletdata"/>
>>   ..
>> </profiles>
>>
>> The problem with this example is that is not how the portal works, nor 
>> would I ever want the portal to require that a block with a specific 
>> name be present as this prohibits two portal implementations from 
>> being present in the same webapp. 
> 
> 
> That's not true. You can deploy as many portal applications as real 
> blocks as you want.

Yes


> And, if you don't like dependencies (references, 
> extensions) just don't use them.

And No. If portal block requires implementation of profile block, during its 
deployment time you will pick up an implementation you like for each instance of 
portal block.

Vadim

Re: [RT] The block protocol

Posted by Reinhard Poetz <re...@apache.org>.
Ralph Goers wrote:
> Daniel Fagerstrom wrote:
> 
>> is resolved in the same way as an ordinary external block URI. To make 
>> this possible the role of being a super block must be identifiable 
>> among the connections in the wiring info. Maybe by reserving the name 
>> "super" for this case.
>>
>> WDYT?
>>
>> /Daniel
> 
> 
> A few  thoughts here (that aren't necessarily directed at you):
> 1. I may have missed some points in this discussion. When the email gets 
> to be  long or quotes previous nested emails in their entirety I tend to 
> just move on and ignore the post.  So, as a rule I would recommend 
> keeping posts as short and sweet as possible.  If you'll notice, there 
> have only been a few participants in these discussions. Maybe its just 
> me, but I wonder if others aren't jumping in with their thoughts for the 
> same reason.

I have the same feeling - but discussing based on examples is difficult, 
especially if the examples are very long ...

> 2. I've noticed a few discussions that are mainly between you and 
> Reinhard with other folks posting occaisionally. Although you two may 
> come to agreement on some ideas, given item 1 I wonder if it actually is 
> the concensus of the community. 

No, I don't think that everybody who hasn't contributed to the discussion is in 
agreement with Daniel, Stefano and me. It will be much easier when the first 
prototype is available.

> Maybe I'm wrong though, and maybe most 
> of the commtters just aren't interested.

I don't understand this. If somebody isn't interested, he shouldn't have a 
problem with the discussion. It's a bigger problem that if people *were* 
interested and don't like the long mails that they would have to say important 
things but they don't want to invest that much time in following the discussions.

As said in my reply to Betrand's mail, I will try to revise the original design 
proposal by Stefano (as far as I can see there are only some minor things that 
have changed or were extended + I will also add relevant links to mails)


> 3. I've had a real problem with the previous "blocks" discussion and how 
> it used the Portal as an example.  I'm not sure that it is actually 
> understood what needs to happen with the portal to make it into a "real 
> block".  The issue with the portal is that the framework (what would be 
> the portal block)  requires quite a few definitions, both in components 
> and in the sitemap. These definitions must be provided by the portal 
> implementation. If the portal implementation must provide the 
> definitions then there really is no need for a block protocol as there 
> is nothing in the portal block to invoke, other than the sitemap 
> components provided by it. In message 
> http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=111245388030013&w=2, 
> Reinhard said "The block "portal" only contains pipelines calls which 
> the block "profile" provides in its sitemap
> 
> Portal block
> ------------
> - requires "MyProfile" that implements "profile"
> 
> <profiles>
>  <copletbasedata-load
>   uri="blocks:profile:/load-global-profile?profile=copletbasedata"/>
>  <copletdata-global-load
>   uri="blocks:profile:/load-global-profile?profile=copletdata"/>
>   ..
> </profiles>
> 
> The problem with this example is that is not how the portal works, nor 
> would I ever want the portal to require that a block with a specific 
> name be present as this prohibits two portal implementations from being 
> present in the same webapp. 

That's not true. You can deploy as many portal applications as real blocks as 
you want. And, if you don't like dependencies (references, extensions) just 
don't use them. The example above was for the sake of showing that things *can* 
be separated if people like it. E.g. you could deploy 5 portal applications all 
using the same skin block.

In fact, these definitions must be in the
> application, not the portal block.

as said above, it's your choice. If you want to do things in the future as you 
have always done, put your application into a single block and only minor things 
will change for you (you have to provide a block.xml file, that's it).

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] The block protocol

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Ralph Goers wrote:

> Daniel Fagerstrom wrote:
>
>> is resolved in the same way as an ordinary external block URI. To 
>> make this possible the role of being a super block must be 
>> identifiable among the connections in the wiring info. Maybe by 
>> reserving the name "super" for this case.
>>
>> WDYT?
>>
>> /Daniel
>
>
> A few  thoughts here (that aren't necessarily directed at you):
> 1. I may have missed some points in this discussion. When the email 
> gets to be  long or quotes previous nested emails in their entirety I 
> tend to just move on and ignore the post.  So, as a rule I would 
> recommend keeping posts as short and sweet as possible.

While I agree in general, It is quite hard to achieve. At some point we 
need to get from discussing about the general requirements and the broad 
vision about things, and get into designing the gory details. And at 
that point we need to use examples (which takes place) to assure that 
our proposed solutions actually work and that we talking about the same 
things. It is also necessary to discuss some edge cases that most users 
hopefully don't need to understand, but which would bite them if we 
didin't take care about them in the design.

>   If you'll notice, there have only been a few participants in these 
> discussions. Maybe its just me, but I wonder if others aren't jumping 
> in with their thoughts for the same reason.

I have certainly noticed that there are few participant in the 
discussion. I think an important reason is that the discussed subject 
(blocks) is rather difficult and takes quite some while to learn enough 
about to be able to participate in detailed design discussions.

For my own part I found blocks attractive and important from the very 
beginning, when Stefano presented them maybe three years ago. But it 
took me long time before I started to participate in the discussions as 
the focus on the blocks work in the beginning was about things that I 
didn't know much about. People believed that it was necessary to switch 
component manager before we could start to actually implement blocks. 
And I didn't know much about componment managers back then.

Anyway, if you (or others) think that we are dicussing something that 
you would like to participate in but is lost in all the details, just 
ask us about some background or for a summary of the issues. As long as 
you don't comment it is hard to know if anyone reads. And the allready 
long mails would be endless if we by default started with a summary of 
the whole thread.

> 2. I've noticed a few discussions that are mainly between you and 
> Reinhard with other folks posting occaisionally. Although you two may 
> come to agreement on some ideas, given item 1 I wonder if it actually 
> is the concensus of the community.

I'm certain that people will start to have opinions when we start to 
have an implementation. Until then lazy concensus is enough.

<snip>stuff that Reinhard commented</snip>

/Daniel


Re: [RT] The block protocol

Posted by Bertrand Delacretaz <bd...@apache.org>.
Le 5 avr. 05, à 09:10, Reinhard Poetz a écrit :
> ...I will revise http://wiki.apache.org/cocoon/Blocks (this weekend or 
> next week)

Thanks - wiki pages also make good "discussion checkpoints", and might 
allow more people to give feedback on the design.

-Bertrand

--
   Bertrand Delacretaz
   independent consultant, Lausanne, Switzerland
   http://www.codeconsult.ch


Re: [RT] The block protocol

Posted by Reinhard Poetz <re...@apache.org>.
Bertrand Delacretaz wrote:
> Le 5 avr. 05, à 04:42, Ralph Goers a écrit :
> 
>> ...When the email gets to be  long or quotes previous nested emails in 
>> their entirety I tend to just move on and ignore the post...
> 
> 
> FWIW, it is exactly my case: not enough time to follow these loooong 
> emails. The mailing-list discussion mode makes it very hard to work on 
> such (important I'm afraid) design issues collectively.
> 
> Not that I have a solution, just wanted to reinforce what Ralph is 
> saying. Or maybe one suggestion: if the people involved in these 
> discussions could post [SUMMARY] messages as a kind of checkpoint along 
> the way from time to time, it might help more people get involved based 
> on what's been agreed in the discussion so far.

as said the discussions were very long and maybe Daniel, Stefano and I were the 
only ones who were able to follow it.

I will revise http://wiki.apache.org/cocoon/Blocks (this weekend or next week)

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] The block protocol

Posted by Bertrand Delacretaz <bd...@apache.org>.
Le 5 avr. 05, à 04:42, Ralph Goers a écrit :
> ...When the email gets to be  long or quotes previous nested emails in 
> their entirety I tend to just move on and ignore the post...

FWIW, it is exactly my case: not enough time to follow these loooong 
emails. The mailing-list discussion mode makes it very hard to work on 
such (important I'm afraid) design issues collectively.

Not that I have a solution, just wanted to reinforce what Ralph is 
saying. Or maybe one suggestion: if the people involved in these 
discussions could post [SUMMARY] messages as a kind of checkpoint along 
the way from time to time, it might help more people get involved based 
on what's been agreed in the discussion so far.

-Bertrand

Re: [RT] The block protocol

Posted by Ralph Goers <Ra...@dslextreme.com>.
Daniel Fagerstrom wrote:

> is resolved in the same way as an ordinary external block URI. To make 
> this possible the role of being a super block must be identifiable 
> among the connections in the wiring info. Maybe by reserving the name 
> "super" for this case.
>
> WDYT?
>
> /Daniel

A few  thoughts here (that aren't necessarily directed at you):
1. I may have missed some points in this discussion. When the email gets 
to be  long or quotes previous nested emails in their entirety I tend to 
just move on and ignore the post.  So, as a rule I would recommend 
keeping posts as short and sweet as possible.  If you'll notice, there 
have only been a few participants in these discussions. Maybe its just 
me, but I wonder if others aren't jumping in with their thoughts for the 
same reason.
2. I've noticed a few discussions that are mainly between you and 
Reinhard with other folks posting occaisionally. Although you two may 
come to agreement on some ideas, given item 1 I wonder if it actually is 
the concensus of the community. Maybe I'm wrong though, and maybe most 
of the commtters just aren't interested.
3. I've had a real problem with the previous "blocks" discussion and how 
it used the Portal as an example.  I'm not sure that it is actually 
understood what needs to happen with the portal to make it into a "real 
block".  The issue with the portal is that the framework (what would be 
the portal block)  requires quite a few definitions, both in components 
and in the sitemap. These definitions must be provided by the portal 
implementation. If the portal implementation must provide the 
definitions then there really is no need for a block protocol as there 
is nothing in the portal block to invoke, other than the sitemap 
components provided by it. In message 
http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=111245388030013&w=2, 
Reinhard said "The block "portal" only contains pipelines calls which 
the block "profile" provides in its sitemap

Portal block
------------
- requires "MyProfile" that implements "profile"

<profiles>
  <copletbasedata-load
   uri="blocks:profile:/load-global-profile?profile=copletbasedata"/>
  <copletdata-global-load
   uri="blocks:profile:/load-global-profile?profile=copletdata"/>
   ..
</profiles>

The problem with this example is that is not how the portal works, nor 
would I ever want the portal to require that a block with a specific 
name be present as this prohibits two portal implementations from being 
present in the same webapp. In fact, these definitions must be in the 
application, not the portal block.

Ralph


[RT] The block protocol (was: RFC-2396)

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Daniel Fagerstrom wrote:
> Pier Fumagalli wrote:
>> On 4 Apr 2005, at 16:26, Daniel Fagerstrom wrote:
>>> Pier Fumagalli wrote:
>>>> On 31 Mar 2005, at 01:26, Stefano Mazzocchi wrote:
>>>>>
>>>>>  block:super://blah.xml
>>>>
>>>> A very simple remark, I don't want to criticise...
>>>>
>>>> I'm already slightly "upset" about the "cocoon://" protocol, as it 
>>>> does not follow the URI RFC properly, I'd like to address the 
>>>> problem as early as possible...
>>>>
>>>> http://www.ietf.org/rfc/rfc2396.txt
>>>>
>>>> I wrote a small "rant" while on the plane, just to explain my 
>>>> reasoning, with a couple of code examples, as it's (I don't think) 
>>>> mailing-list material, I've stored it on my WIKI...
>>>>
>>>> http://www.betaversion.org/~pier/wiki/display/pier/Cocoon+and+URIs

<snip/>

>> Exactly... That's why I'm thinking that the URI should be this:
>>
>> block:portal:/foo
>>
>> block is an opaque URI, whose scheme specific part _is_ a valid URI by 
>> itself.
>>
>> portal:/foo is a valid URI, but if (for example) you think about other 
>> cases, this URI could be
>>
>> block:xmlrpc://www.myrpcserver.dom/entry/point
>>
>> block: opaque URI
>> xmlrpc: valid URI whose scheme specific part (whether it's opaque, 
>> absolute, relative, blah) is only known by the "xmlrpc" handler...
>>
>> block:portal:/foo
>>
>> What's "/foo"? Only the portal block knows it...

<snip/>

I have thougth a litle bit more about the block URI and the architecture 
around it so I do a new trial.

                             --- o0o ---

The main involved components are the BlocksManager that in turn has 
access to one BlockManager for each block.

Block local access
------------------

Each BlockManager has its own SourceResolver and especially it can have 
its own implementation of the block protocol which is registred with the 
scheme "block:".

An absolute URI relative to the root sitemap of the block looks like:

   block:/foo/bar

and is a hierarchical URI. It is invoked by first trying "foo/bar" in 
the current block's root sitemap and if that fails 
"block:super:/foo/bar" is invoked. More about "block:super:" later. To 
make this work I would assume that error handling must work a little bit 
different in blocks so that a sitemap can fail without emmiting any 
error messages immediatly.

In the case when a block A has invoked an URI in its super block B, to 
achieve polymorphism, all block protocoll resolution in B must be done 
by first asking A's block resolver before trying its own.

A relative URI in a sub sitemap "/foo" from the block's root sitemap,

   block:./bar

(an opaque URI) is resolved to

   block:/foo/bar

using the same method as Pier used for the cocoon protocol in his Wiki.

Inter block access
------------------

An URI to another block "skin" e.g. looks like:

   block:skin:/foo/bar

the BlockManager resolves it by looking up "skin" in the wiring info for 
the block (http://wiki.apache.org/cocoon/BlocksWiring) and find the mapping:

   skin -> http://mycompany.com/skins/corporate/34.3.345

in the connection section, where 
"http://mycompany.com/skins/corporate/34.3.345" uniquely identifies the 
specific skin implementation that has been choosen at deploy time.

<comment>
Is the URI unique enough? What if I want several variants of the skin 
that has different deployment parameters and implementations of theire 
connections.
</comment>

Interesting enough, IIUC, blocks are only accessible through the block 
protocol from other blocks, as the short name, "skin" e.g., only exists 
in the block wiring info. Are we going to consider the main sitemap part 
of a block as well to be able to access blocks from it?

Next the block manager asks the blocks manager for the URI, this could 
be done through a "blocks:" protocol that is connected to the blocks 
manager. The uri "block:skin:/foo/bar" could be resolved to e.g.:

   blocks:{http://mycompany.com/skins/corporate/34.3.345}:/foo/bar

Besides that it looks awfull I would doubt that it even is synatactic 
correct as an opaque URI. I only wrote it down to provoke you to find 
something better ;)

Next the blocks manager looks up the block manager identified by 
"http://mycompany.com/skins/corporate/34.3.345" and send the URI:

   block:/foo/bar

to it, which will be resolved by the skin blocks internal implementation 
of the block protocol.

   block:super:/foo/bar

is resolved in the same way as an ordinary external block URI. To make 
this possible the role of being a super block must be identifiable among 
the connections in the wiring info. Maybe by reserving the name "super" 
for this case.

WDYT?

/Daniel

Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Pier Fumagalli wrote:

>
> On 4 Apr 2005, at 16:26, Daniel Fagerstrom wrote:
>
>> Pier Fumagalli wrote:
>>
>>> On 31 Mar 2005, at 01:26, Stefano Mazzocchi wrote:
>>>
>>>>
>>>>  block:super://blah.xml
>>>
>>>
>>>
>>> A very simple remark, I don't want to criticise...
>>>
>>> I'm already slightly "upset" about the "cocoon://" protocol, as it 
>>> does not follow the URI RFC properly, I'd like to address the 
>>> problem as early as possible...
>>>
>>> http://www.ietf.org/rfc/rfc2396.txt
>>
>>
>>>
>>> I wrote a small "rant" while on the plane, just to explain my 
>>> reasoning, with a couple of code examples, as it's (I don't think) 
>>> mailing-list material, I've stored it on my WIKI...
>>>
>>> http://www.betaversion.org/~pier/wiki/display/pier/Cocoon+and+URIs
>>>
>>> Anyhow, feel free to discuss it here...
>>
>>
>> I read your rant and agree with it, it seem benefical to take 
>> advantage of java.net.URI. I'm not completely happy with letting 
>> relative sitemap paths be opaque and absolute be hierarchical, but I 
>> don't see any better alternatives.
>
>
> The thing is that the scheme specific part of the opaque URI, is 
> actually a relative URI which can be resolved against an absolute one...
>
> URI relative_uri = 
> absolute_uri.resolve(opaque_uri.getSchemeSpecificPart());
>
> As simple as that...
>
>>
>> Concerning:
>>
>>  block:super://blah.xml
>>
>> it is AFAICS a correct opaque URI. But we could make better use of 
>> java.net.URI if we considered a hierarchial URI scheme for blocks 
>> instead. From this perspective the scheme that Reinhard suggested 
>> makes sense
>>
>>  block://portal/foo
>>
>> for refering to the absoute path "/foo" within the portal block,
>>
>>  block:/foo
>>
>> for refering to the absolute path "/foo" within the current block and
>>
>>  block:./bar
>>
>> for refering to the relative path "bar" relative to the current 
>> (sub)sitemap within the current block and
>>
>>  block:super:/foo
>>
>> for refering to the absolute path "foo" whithin the super block of 
>> the current and possibly
>>
>>  block:super:./bar
>>
>> for refering to the relative path "bar" relative to the current 
>> (sub)sitemap within the super block of the current.
>>
>> The last three URIs are opaque and could be resolved to absolute 
>> hierarchical URIs with a similar algorithm as you proposed for 
>> "cocoon:./" resolution.
>>
>> Maybe using "//portal" as an authority is stretching the 
>> intepretation to far.
>
>
> Exactly... That's why I'm thinking that the URI should be this:
>
> block:portal:/foo
>
> block is an opaque URI, whose scheme specific part _is_ a valid URI by 
> itself.
>
> portal:/foo is a valid URI, but if (for example) you think about other 
> cases, this URI could be
>
> block:xmlrpc://www.myrpcserver.dom/entry/point
>
> block: opaque URI
> xmlrpc: valid URI whose scheme specific part (whether it's opaque, 
> absolute, relative, blah) is only known by the "xmlrpc" handler...
>
> block:portal:/foo
>
> What's "/foo"? Only the portal block knows it...

Ok, that makes sense. The specific blocks handler resolve the scheme 
specific part. If we follow this path the blocks descriptor 
(http://wiki.apache.org/cocoon/BlocksCob) must be extended with a 
declaration about what source resolver to use.

It would still be good to have a default resolver for all blocks that 
doesn't have specific needs, so that we get some coherence for our 
blocks. And there we could use hierarchical URIs like those you propsed 
in your wiki for the cocoon: protocol.

Question is how i.e. the portal block refers to its own pipes. If you 
take a look at http://wiki.apache.org/cocoon/BlocksCob a block doesn't 
have a short name for it self that can be used as scheme, it only 
declares such names for the blocks it requires, so portal: doesn't make 
any sense within the portal block. So within the specific block we could 
maybe use:

  block:/foo, block:./bar, block:super:/foo, block:super:./bar

whith the same intepretation as I suggested above (for the default 
resolver).

This could be done in the way that each block define its own resolver 
and bind it to the scheme block:, then when  a block, portal e.g. use an 
URI to another block, the block manager (for portal) will get an URI like:

  block:skin:/foo

it will then find the block manager for the skin block and ask it to resolve

  block:/foo

Which will use the resolver from the skin block.

/Daniel


Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Stefano Mazzocchi <st...@apache.org>.
Pier Fumagalli wrote:

> The only problem I have with "block:super://blah.xml" is that "//" in an 
> URI indicates the start of the authority part, and this is defined as 
> "user@host:port", and no matter how you see it, "block:...anything..." 
> _is_ a URI, and thus should follow its spec...
> 
>     Pier
> 
>>
>>                                              --- o0o ---
>>
>> As all URI discussions tend to provoke strong feelings for Stefano, 
>> it's best to say directly that this question is not important enough 
>> for me to fight about ;)

Despite dry humor, I have no problems deprecating the use of // in the 
cocoon: and block: URI scheme.

-- 
Stefano.


Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Pier Fumagalli <pi...@betaversion.org>.
On 4 Apr 2005, at 16:26, Daniel Fagerstrom wrote:

> Pier Fumagalli wrote:
>
>> On 31 Mar 2005, at 01:26, Stefano Mazzocchi wrote:
>>
>>>
>>>  block:super://blah.xml
>>
>>
>> A very simple remark, I don't want to criticise...
>>
>> I'm already slightly "upset" about the "cocoon://" protocol, as it 
>> does not follow the URI RFC properly, I'd like to address the problem 
>> as early as possible...
>>
>> http://www.ietf.org/rfc/rfc2396.txt
>
>>
>> I wrote a small "rant" while on the plane, just to explain my 
>> reasoning, with a couple of code examples, as it's (I don't think) 
>> mailing-list material, I've stored it on my WIKI...
>>
>> http://www.betaversion.org/~pier/wiki/display/pier/Cocoon+and+URIs
>>
>> Anyhow, feel free to discuss it here...
>
> I read your rant and agree with it, it seem benefical to take 
> advantage of java.net.URI. I'm not completely happy with letting 
> relative sitemap paths be opaque and absolute be hierarchical, but I 
> don't see any better alternatives.

The thing is that the scheme specific part of the opaque URI, is 
actually a relative URI which can be resolved against an absolute 
one...

URI relative_uri = 
absolute_uri.resolve(opaque_uri.getSchemeSpecificPart());

As simple as that...

>
> Concerning:
>
>  block:super://blah.xml
>
> it is AFAICS a correct opaque URI. But we could make better use of 
> java.net.URI if we considered a hierarchial URI scheme for blocks 
> instead. From this perspective the scheme that Reinhard suggested 
> makes sense
>
>  block://portal/foo
>
> for refering to the absoute path "/foo" within the portal block,
>
>  block:/foo
>
> for refering to the absolute path "/foo" within the current block and
>
>  block:./bar
>
> for refering to the relative path "bar" relative to the current 
> (sub)sitemap within the current block and
>
>  block:super:/foo
>
> for refering to the absolute path "foo" whithin the super block of the 
> current and possibly
>
>  block:super:./bar
>
> for refering to the relative path "bar" relative to the current 
> (sub)sitemap within the super block of the current.
>
> The last three URIs are opaque and could be resolved to absolute 
> hierarchical URIs with a similar algorithm as you proposed for 
> "cocoon:./" resolution.
>
> Maybe using "//portal" as an authority is stretching the intepretation 
> to far.

Exactly... That's why I'm thinking that the URI should be this:

block:portal:/foo

block is an opaque URI, whose scheme specific part _is_ a valid URI by 
itself.

portal:/foo is a valid URI, but if (for example) you think about other 
cases, this URI could be

block:xmlrpc://www.myrpcserver.dom/entry/point

block: opaque URI
xmlrpc: valid URI whose scheme specific part (whether it's opaque, 
absolute, relative, blah) is only known by the "xmlrpc" handler...

block:portal:/foo

What's "/foo"? Only the portal block knows it...

> Using an URIs like the ones above has the advantage that we can reuse 
> most of the definition of hierarchial URIs and the functionality in 
> java.net.URI, if we instead go for the opaque style exemplified by 
> "block:super://blah.xml" we have to define the URI parsing ourselves 
> instead.

The only problem I have with "block:super://blah.xml" is that "//" in 
an URI indicates the start of the authority part, and this is defined 
as "user@host:port", and no matter how you see it, 
"block:...anything..." _is_ a URI, and thus should follow its spec...

	Pier

>
>                                              --- o0o ---
>
> As all URI discussions tend to provoke strong feelings for Stefano, 
> it's best to say directly that this question is not important enough 
> for me to fight about ;)
>
> But anyway, whether we go for an opaque custom protocol or base the 
> block protocol on hierachial URIs we need to get into the specifics 
> for the block URI scheme to be able to implement it.
>
> WDYT?
>
> /Daniel
>
>

Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Pier Fumagalli wrote:

> On 31 Mar 2005, at 01:26, Stefano Mazzocchi wrote:
>
>>
>>  block:super://blah.xml
>
>
> A very simple remark, I don't want to criticise...
>
> I'm already slightly "upset" about the "cocoon://" protocol, as it 
> does not follow the URI RFC properly, I'd like to address the problem 
> as early as possible...
>
> http://www.ietf.org/rfc/rfc2396.txt

>
> I wrote a small "rant" while on the plane, just to explain my 
> reasoning, with a couple of code examples, as it's (I don't think) 
> mailing-list material, I've stored it on my WIKI...
>
> http://www.betaversion.org/~pier/wiki/display/pier/Cocoon+and+URIs
>
> Anyhow, feel free to discuss it here...

I read your rant and agree with it, it seem benefical to take advantage 
of java.net.URI. I'm not completely happy with letting relative sitemap 
paths be opaque and absolute be hierarchical, but I don't see any better 
alternatives.

Concerning:

  block:super://blah.xml

it is AFAICS a correct opaque URI. But we could make better use of 
java.net.URI if we considered a hierarchial URI scheme for blocks 
instead. From this perspective the scheme that Reinhard suggested makes 
sense

  block://portal/foo

for refering to the absoute path "/foo" within the portal block,

  block:/foo

for refering to the absolute path "/foo" within the current block and

  block:./bar

for refering to the relative path "bar" relative to the current 
(sub)sitemap within the current block and

  block:super:/foo

for refering to the absolute path "foo" whithin the super block of the 
current and possibly

  block:super:./bar

for refering to the relative path "bar" relative to the current 
(sub)sitemap within the super block of the current.

The last three URIs are opaque and could be resolved to absolute 
hierarchical URIs with a similar algorithm as you proposed for 
"cocoon:./" resolution.

Maybe using "//portal" as an authority is stretching the intepretation 
to far.

Using an URIs like the ones above has the advantage that we can reuse 
most of the definition of hierarchial URIs and the functionality in 
java.net.URI, if we instead go for the opaque style exemplified by 
"block:super://blah.xml" we have to define the URI parsing ourselves 
instead.

                                              --- o0o ---

As all URI discussions tend to provoke strong feelings for Stefano, it's 
best to say directly that this question is not important enough for me 
to fight about ;)

But anyway, whether we go for an opaque custom protocol or base the 
block protocol on hierachial URIs we need to get into the specifics for 
the block URI scheme to be able to implement it.

WDYT?

/Daniel


Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Stefano Mazzocchi <st...@apache.org>.
Daniel Fagerstrom wrote:
> Colin Paul Adams wrote:
> 
>>>>>>> "Pier" == Pier Fumagalli <pi...@betaversion.org> writes:
>>>>>>>           
>>
>>
>>    Pier> I'm already slightly "upset" about the "cocoon://" protocol,
>>    Pier> as it does not follow the URI RFC properly, I'd like to
>>    Pier> address the problem as early as possible...
>>
>>    Pier> http://www.ietf.org/rfc/rfc2396.txt
>>
>> I don't know if this is relevant to the discussion, but are you aware
>> that this RFC has been obsoleted by RFC 3986?
>>  
>>
> It has some relevance to the discussion as it seem (chap 3.) to allow a 
> hierarchical URI at the form:
> 
>  cocoon:foo/bar
> 
> where "foo/bar" is called a root less path. But I don't find any 
> explanation about what it is supposed to mean.

that's the point of a general URI syntax: the meaning is not defined. 
It's just XML for strings really. The semantics are not defined there.

-- 
Stefano.


Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Colin Paul Adams wrote:
>>>>>>"Daniel" == Daniel Fagerstrom <da...@nada.kth.se> writes:
> 
> 
>     Daniel>   cocoon:foo/bar
> 
>     Daniel> where "foo/bar" is called a root less path. But I don't
>     Daniel> find any explanation about what it is supposed to mean.
> 
> Well, it could mean anything the protocol inventor intended.
> Not all URI schemes are hierarchical in nature. This does not mean
> they cannot use the / character.

Thing is that foo/bar in the example above actually is supposed to be a 
hierarchy consisting of the segments foo and bar according to rfc3986. 
But after having checked it closer, the comment in the end of chapter 5 
seem to mean that is shouldn't be used and only is part of the spec to 
cover a loophole in rfc1630 the predecessor of rfc2396. So we shouldn't 
use it anyway.

/Daniel


Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Colin Paul Adams <co...@colina.demon.co.uk>.
>>>>> "Daniel" == Daniel Fagerstrom <da...@nada.kth.se> writes:

    Daniel>   cocoon:foo/bar

    Daniel> where "foo/bar" is called a root less path. But I don't
    Daniel> find any explanation about what it is supposed to mean.

Well, it could mean anything the protocol inventor intended.
Not all URI schemes are hierarchical in nature. This does not mean
they cannot use the / character.
-- 
Colin Paul Adams
Preston Lancashire

Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Colin Paul Adams wrote:

>>>>>>"Pier" == Pier Fumagalli <pi...@betaversion.org> writes:
>>>>>>            
>>>>>>
>
>    Pier> I'm already slightly "upset" about the "cocoon://" protocol,
>    Pier> as it does not follow the URI RFC properly, I'd like to
>    Pier> address the problem as early as possible...
>
>    Pier> http://www.ietf.org/rfc/rfc2396.txt
>
>I don't know if this is relevant to the discussion, but are you aware
>that this RFC has been obsoleted by RFC 3986?
>  
>
It has some relevance to the discussion as it seem (chap 3.) to allow a 
hierarchical URI at the form:

  cocoon:foo/bar

where "foo/bar" is called a root less path. But I don't find any 
explanation about what it is supposed to mean.

/Daniel


Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Pier Fumagalli <pi...@betaversion.org>.
On 4 Apr 2005, at 18:09, Colin Paul Adams wrote:

>>>>>> "Pier" == Pier Fumagalli <pi...@betaversion.org> writes:
>
>     Pier> I'm already slightly "upset" about the "cocoon://" protocol,
>     Pier> as it does not follow the URI RFC properly, I'd like to
>     Pier> address the problem as early as possible...
>
>     Pier> http://www.ietf.org/rfc/rfc2396.txt
>
> I don't know if this is relevant to the discussion, but are you aware
> that this RFC has been obsoleted by RFC 3986?

Ups, didn't pick up that one... Thanks... AFAICS the main changes 
concern IPv6, anyhow... The overall concept remains the same.

	Pier


Re: RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Colin Paul Adams <co...@colina.demon.co.uk>.
>>>>> "Pier" == Pier Fumagalli <pi...@betaversion.org> writes:

    Pier> I'm already slightly "upset" about the "cocoon://" protocol,
    Pier> as it does not follow the URI RFC properly, I'd like to
    Pier> address the problem as early as possible...

    Pier> http://www.ietf.org/rfc/rfc2396.txt

I don't know if this is relevant to the discussion, but are you aware
that this RFC has been obsoleted by RFC 3986?
-- 
Colin Paul Adams
Preston Lancashire

RFC-2396 (Was: Re: [RT] composition vs. inheritance in blocks)

Posted by Pier Fumagalli <pi...@betaversion.org>.
On 31 Mar 2005, at 01:26, Stefano Mazzocchi wrote:
>
>  block:super://blah.xml

A very simple remark, I don't want to criticise...

I'm already slightly "upset" about the "cocoon://" protocol, as it does 
not follow the URI RFC properly, I'd like to address the problem as 
early as possible...

http://www.ietf.org/rfc/rfc2396.txt

I wrote a small "rant" while on the plane, just to explain my 
reasoning, with a couple of code examples, as it's (I don't think) 
mailing-list material, I've stored it on my WIKI...

http://www.betaversion.org/~pier/wiki/display/pier/Cocoon+and+URIs

Anyhow, feel free to discuss it here...

	Pier


Re: [RT] composition vs. inheritance in blocks

Posted by Peter Hunsberger <pe...@gmail.com>.
On Apr 4, 2005 8:49 AM, Daniel Fagerstrom <da...@nada.kth.se> wrote:

<snip/>

> This means IMO that we have to spend time discussing things even if it
> in the short time horizont and for ones own goals whould have seemed
> more productive to just commit some code.

Ultimately, with an Open Source community it is going to be the code
that counts.  However, that shouldn't stop any discussion before or
after the fact.  There's a thousand different view points out there
and just bringing them to light may trigger ideas that no one would
have considered otherwise...

-- 
Peter Hunsberger

Re: [RT] composition vs. inheritance in blocks

Posted by Peter Hunsberger <pe...@gmail.com>.
On Thu, 31 Mar 2005 18:03:40 +0200, Reinhard Poetz <re...@apache.org> wrote:
> Peter Hunsberger wrote:
> > On Thu, 31 Mar 2005 17:42:38 +0200, Reinhard Poetz <re...@apache.org> wrote:
> >
> >>Peter Hunsberger wrote:
> >>
> >>
> >>>One comment: I'd hope that you don't literally copy the
> >>>"portal-page.xsl" and modify it?  Instead you should be creating a new
> >>>XSL, including "portal-page.xsl" in it and just modifying the
> >>>templates that you  wish to override...
> >>
> >>yes, <xsl:import href="blocks://portal-skin/portal-page.xsl"/> should do it.
> >
> >
> > Personally, I'd use <xsl:include href="..."/> most of the time, but
> > either way, it's interesting to note that the Cocoon resolver has to
> > get involved in resolving the reference, which means the resultant XSL
> > isn't portable....
> 
> true, but what's the alternative?

You need to allow the referencing block to add an indication that the
the block resolver is to be used to resolve certain URL's. Eg:

<block ...
<extends>http://cocoon.apache.org/blocks/portal-skin/1.0.0
<resolve>//portal-skin</resolve>
</extends>

then any reference starting with the given path would use the block
resolver to resolve to the given block.  That could probably work with
relative URL's also, but the whole idea makes me a little nervous:
you'd get cases where people want to use regex or something to do the
matches or add filters to make exceptions and you'd end up reinventing
mod-redirect or some such thing.


-- 
Peter Hunsberger

Re: [RT] composition vs. inheritance in blocks

Posted by Reinhard Poetz <re...@apache.org>.
Peter Hunsberger wrote:
> On Thu, 31 Mar 2005 17:42:38 +0200, Reinhard Poetz <re...@apache.org> wrote:
> 
>>Peter Hunsberger wrote:
>>
>>
>>>One comment: I'd hope that you don't literally copy the
>>>"portal-page.xsl" and modify it?  Instead you should be creating a new
>>>XSL, including "portal-page.xsl" in it and just modifying the
>>>templates that you  wish to override...
>>
>>yes, <xsl:import href="blocks://portal-skin/portal-page.xsl"/> should do it.
> 
> 
> Personally, I'd use <xsl:include href="..."/> most of the time, but
> either way, it's interesting to note that the Cocoon resolver has to
> get involved in resolving the reference, which means the resultant XSL
> isn't portable....

true, but what's the alternative?

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] composition vs. inheritance in blocks

Posted by Peter Hunsberger <pe...@gmail.com>.
On Thu, 31 Mar 2005 17:42:38 +0200, Reinhard Poetz <re...@apache.org> wrote:
> Peter Hunsberger wrote:
> 
> > One comment: I'd hope that you don't literally copy the
> > "portal-page.xsl" and modify it?  Instead you should be creating a new
> > XSL, including "portal-page.xsl" in it and just modifying the
> > templates that you  wish to override...
> 
> yes, <xsl:import href="blocks://portal-skin/portal-page.xsl"/> should do it.

Personally, I'd use <xsl:include href="..."/> most of the time, but
either way, it's interesting to note that the Cocoon resolver has to
get involved in resolving the reference, which means the resultant XSL
isn't portable....

-- 
Peter Hunsberger

Re: [RT] composition vs. inheritance in blocks

Posted by Reinhard Poetz <re...@apache.org>.
Peter Hunsberger wrote:

> One comment: I'd hope that you don't literally copy the
> "portal-page.xsl" and modify it?  Instead you should be creating a new
> XSL, including "portal-page.xsl" in it and just modifying the
> templates that you  wish to override...

yes, <xsl:import href="blocks://portal-skin/portal-page.xsl"/> should do it.

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] composition vs. inheritance in blocks

Posted by Peter Hunsberger <pe...@gmail.com>.
On Thu, 31 Mar 2005 11:51:53 +0200, Daniel Fagerstrom
<da...@nada.kth.se> wrote:

<snip/>

> Now I'm aware that the portal samples use the construction you show
> above, but it doesn't achieve exactly the same thing as the construction
> I propose. If you want to use a slightly modified skin, I would assume
> that you start by copying the +30 files from skins/commons and then
> point "global-variables/skin" to the new location and start to modify
> whatever you wanted to modify.
> 
> With my solution you just copy the file, in this case "portal-page.xsl"
> that you actually want to modify and write an overriding sitemap rule to
> use it. After having used thing like the global variable trick for a
> number of years in various applications, we had a tremendous amonount of
> different generations of esentially the same files and numerous copies
> of slightly modified sitemap snippets. Hardly supprising it was a
> maintainance nightmare. After having start to use the pattern that I
> propose we have seen a drastic decrease in the number of files in our
> new applications.

One comment: I'd hope that you don't literally copy the
"portal-page.xsl" and modify it?  Instead you should be creating a new
XSL, including "portal-page.xsl" in it and just modifying the
templates that you  wish to override...

I point this out because XSLT implements an interesting version of MI
with include.  It completely exposes the entire inheritance tree and
gives you very limited ways to navigate the tree.  None-the-less
people use it all the time.

In the 70 plus XSLT we have in our app roughly half of them do an
include, sometimes using 4 levels inheritance.  None of them use an
import and an "apply-imports" which would be the XSLT equivalent of
composition.

There are a couple of ways in which XSLT (1.0) could provide better
tools for manging the inheritance tree.  In particular, on include you
should be able to specify the default priority of the included
templates and a base-priority that would be added to any existing
priorities.  You still wouldn't get complete navigation through the
tree, I can see ways of doing that also, but that's another topic
(unless people want to use an XSLT like model for block inheritance.)

<snip/>

-- 
Peter Hunsberger

Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Reinhard Poetz wrote:

> Daniel Fagerstrom wrote:
>
>> I have given some examples of how a user could use some adapted form 
>> of MI to build applications based on a number of blocks, so I'm 
>> interested in your view about how to build blocks based applications.
>
>
> I can't add much to what Stefano already has said:
>
> "You install "Linotype2", is a real block and it requires "Linotype 
> Skin", "JCR Repository", "RDF TripleStore". The block manager goes to 
> the block library on cocoon.apache.org and finds a list of possible 
> blocks that implement those interfaces and that are known to be 
> compatible with the version of the block you are now installing."
>
>
> Except that not the BlocksManager but the BlockDeployer will install 
> blocks, that's the vision:
>
>  - reusability
>    --> skin can be used by more than one block)
>    --> develop functionality *once* and reuse it in many applications
>  - versioning
>  - development will become much easier because you can wire locally
>    available development blocks
>    e.g. I want to use the latest cForms block in *my* project I simply
>    point in the wiring.xml of *my* project to this block. There are
>    no difficult deployment cycles!
>
>
> And quoting Stefano a second time: "what is the best way to use those 
> features in order to achieve what I need". I don't know what will be 
> the best way to use all those features. When we have a working 
> prototype we will learn a lot and best practices will evolve.
>
Ok, so lets get to a working prototype. Still if we don't spend some 
thought on relevant use cases that comes up, the working prototype might 
be less relevant than it could be.

/Daniel


Re: [RT] composition vs. inheritance in blocks

Posted by Reinhard Poetz <re...@apache.org>.
Daniel Fagerstrom wrote:

> I have given some examples of how a user could use some adapted form of 
> MI to build applications based on a number of blocks, so I'm interested 
> in your view about how to build blocks based applications.

I can't add much to what Stefano already has said:

"You install "Linotype2", is a real block and it requires "Linotype Skin", "JCR 
Repository", "RDF TripleStore". The block manager goes to the block library on 
cocoon.apache.org and finds a list of possible blocks that implement those 
interfaces and that are known to be compatible with the version of the block you 
are now installing."


Except that not the BlocksManager but the BlockDeployer will install blocks, 
that's the vision:

  - reusability
    --> skin can be used by more than one block)
    --> develop functionality *once* and reuse it in many applications
  - versioning
  - development will become much easier because you can wire locally
    available development blocks
    e.g. I want to use the latest cForms block in *my* project I simply
    point in the wiring.xml of *my* project to this block. There are
    no difficult deployment cycles!


And quoting Stefano a second time: "what is the best way to use those features 
in order to achieve what I need". I don't know what will be the best way to use 
all those features. When we have a working prototype we will learn a lot and 
best practices will evolve.

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Reinhard Poetz wrote:
> Daniel Fagerstrom wrote:
>> Reinhard Poetz wrote:

>>> I think I got the idea. Personally, I would solve this by 
>>> composition; the profiling is just another reference of the block. Of 
>>> course, as Stefano said, blocks have to be designed for this. If the 
>>> application block hasn't factored out the profile aspect, then you 
>>> can't replace implementation A by implementation B:
>>>
>>> --------------------------------------------------------------------------- 
>>>
>>> "Application block" (to be reused in many projects)
>>> --------------------------------------------------------------------------- 
>>>
>>> <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>>>  id="http://mycompany.com/blocks/application-block/1.0.0">
>>>   <name>Application block</name>
>>>   <requirements>
>>>     <requires interface="http://mycompany.com/interfaces/skin/1.0"
>>>       name="skin"
>>>       default="http://mycompany.com/blocks/myskin/1.0.0"/>
>>>     <requires 
>>> interface="http://cocoon.apache.org/interfaces/profile/1.0"
>>>       name="profile"
>>>       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
>>>     <requires interface="http://cocoon.apache.org/interfaces/portal/1.0"
>>>       name="portal"
>>>       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
>>>   </requirements>
>>> </block>
>>
>>
>>
>> It would work, but to achieve what I did in a few sitemap lines 
>> (above) you have to create and deploy a special MyProfile block, and 
>> as I just wanted to override a few things in my customized profile I 
>> have to extend the original profile from the Portal block in some way. 
>> In the sitemap in MyProfile you have to write  a copy of the profiles 
>> section in the Portal block:
>>
>> MyProfile sitemap
>> -----------------
>>
>> ...
>> <profiles>
>> <copletbasedata-load 
>> uri="blocks:/profile/load-global-profile?profile=copletbasedata"/>
>> <copletdata-global-load 
>> uri="blocks:/profile/load-global-profile?profile=copletdata"/>
>> <copletdata-role-load 
>> uri="blocks:/profile/load-role-profile?profile=copletdata"/>
>> <copletdata-user-load 
>> uri="blocks:/profile/load-user-profile?profile=copletdata"/>
>> <copletinstancedata-global-load 
>> uri="blocks:/profile/load-global-profile?profile=copletinstancedata"/>
>> <copletinstancedata-role-load 
>> uri="blocks:/profile/load-role-profile?profile=copletinstancedata"/>
>> <copletinstancedata-user-load 
>> uri="blocks:/profile/load-user-profile?profile=copletinstancedata"/>
>> <copletinstancedata-user-save 
>> uri="blocks:/profile/save-user-profile?profile=copletinstancedata"/>
>> <layout-global-load 
>> uri="blocks:/profile/load-global-profile?profile=layout"/>
>> <layout-role-load 
>> uri="blocks:/profile/load-role-profile?profile=layout"/>
>> <layout-user-load 
>> uri="blocks:/profile/load-user-profile?profile=layout"/>
>> <layout-user-save 
>> uri="blocks:/profile/save-user-profile?profile=layout"/>
>> </profiles>
>> ...
>> <pipeline>
>>  <match pattern="profile/load-user-profile">
>>   ...
>> </match>
>>
>> Here the blocks protocol is supposed to first look in the own sitemap 
>> (and find "load-user-profile") before it asks the super block. As you 
>> can see you need a copy of the profiles section of the sitemap booth 
>> in Portal and in MyProfile. 
> 
> 
> No, you don't. The block "portal" only contains pipelines calls which 
> the block "profile" provides in its sitemap:
> 
> Portal block
> ------------
> - requires "MyProfile" that implements "profile"
> 
> <profiles>
>  <copletbasedata-load
>   uri="blocks:profile:/load-global-profile?profile=copletbasedata"/>
>  <copletdata-global-load
>   uri="blocks:profile:/load-global-profile?profile=copletdata"/>
>   ..
> </profiles>
> 
> (After reading Stefano's mail I found a mistake in my examples: The 
> block name is a sub-protocol and not part of the path.)
> 
> You can have one block that provides default pipelines, let's call it 
> "profile-default":
> 
> "profile-default"
> -----------------
> - implements "profile"
> 
> <map:match pattern="load-global-profile">
>  ...
> </map:match>
> 
> 
> If you need special behaviour in your _custom_ profile block, you extend 
> the "profile-default" block and override _only_ those parts that you 
> want to see changed. In your custom portal block ("MyPortal") you change 
> the requirement from "profile-default" to "MyProfile" and you're done.
> 
> "MyProfile"
> -----------
> - extends "profile-default"
> 
> 
>> And you define and deploy small blocks for each aspect you want to 
>> override in the original block. The behaviour of an actual application 
>> will be spread out in all these small extended blocks. I found it 
>> clumsy, complicated and burocratic compared to the simple sitemap 
>> based extension mechanism I used in my example.
> 
> 
> IIUC your point is that how your application works is spread over to 
> many blocks. Maybe you're right but I don't think so, at least the 
> examples we talked about here are overly complex using

?

Ok, accepting that we get a number of small blocks, I still think that 
you miss things in your example by not using polymorphism.

Whithout knowing much about the portal, it seem to me that it would more 
natural to let the Profile interface be about an actual profile rather 
than about a number of pipelines that you could use for building a 
profile. A DefaultProfile implementation could (and probably should) 
have a number of pipelines that makes default configuration content 
avaliable and overidable and that are used for building the profile. But 
if we want to actually build easy reusable components the interface 
should not be that fat and specific.

If the DefaultProfile is built this way, really polymorphic (single) 
inheritance will reduce the amount of copying, compared to pure composition.

>>> What I do like is <mount uri-prefix="" src="blocks://portal"/> which 
>>> makes it explicit what a block exports. I'm not sure about why this 
>>> has to be a "two way contract".
>>
>>
>>
>> It must be a two way contract, as "extend and overide" is a two way 
>> contract. If you have it one way you end up having to copy everything 
>> that is an agregate of functionality as in the profile example above.
> 
> 
> Yes, if something isn't designed for reusability, then you have to copy 
> it. If you design for reusablity, you don't have to copy services.

Aggregated services requires real polymorphism, if you don't want to 
copy the sitemap rule or code that does the actual composition.

<snip/>

> I think we should stop the discussion at this point for now (I don't 
> think that anybody can follow it anymore). IIUC everything you proposed 
> can be added in a backwards-compatible way to the existing proposal. But 
> I'm confident we don't need it ;-)

Yes, we obviously not getting anywher, so lets move on and let us design 
really polymorphic blocks with sigle inheritance.

>> Also, I'm intersted in your view about how to actually use the blocks 
>> in an application.

> I can think of many scenarios where blocks make sense. We already talked 
> abut them in this discussion (skinning, profiles, easy deployment, easy 
> development, ...). Does this answer your question or is it too general.

I wouldn't have parcipated in this discussion if I didn't found blocks 
usefull ;)

My question is a serious and IMO important one. If a user is going to 
build an own portal for his/her company and is going to base this on the 
portal block, how will he/she do this. What will the main sitemap look 
like, the deployment configuration etc. In the same way that we needed 
to write example block.xml and block sitemaps, to get better 
understanding of blocks, I think we need to take a look on a "real" 
usage of a block, to get the design as usable as possible.

I have given some examples of how a user could use some adapted form of 
MI to build applications based on a number of blocks, so I'm interested 
in your view about how to build blocks based applications.

Is the question clearer now?

/Daniel

Re: [RT] composition vs. inheritance in blocks

Posted by Reinhard Poetz <re...@apache.org>.
Daniel Fagerstrom wrote:

> Reinhard Poetz wrote:
 >
>> I think I got the idea. Personally, I would solve this by composition; 
>> the profiling is just another reference of the block. Of course, as 
>> Stefano said, blocks have to be designed for this. If the application 
>> block hasn't factored out the profile aspect, then you can't replace 
>> implementation A by implementation B:
>>
>> --------------------------------------------------------------------------- 
>>
>> "Application block" (to be reused in many projects)
>> --------------------------------------------------------------------------- 
>>
>> <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>>  id="http://mycompany.com/blocks/application-block/1.0.0">
>>   <name>Application block</name>
>>   <requirements>
>>     <requires interface="http://mycompany.com/interfaces/skin/1.0"
>>       name="skin"
>>       default="http://mycompany.com/blocks/myskin/1.0.0"/>
>>     <requires interface="http://cocoon.apache.org/interfaces/profile/1.0"
>>       name="profile"
>>       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
>>     <requires interface="http://cocoon.apache.org/interfaces/portal/1.0"
>>       name="portal"
>>       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
>>   </requirements>
>> </block>
> 
> 
> It would work, but to achieve what I did in a few sitemap lines (above) 
> you have to create and deploy a special MyProfile block, and as I just 
> wanted to override a few things in my customized profile I have to 
> extend the original profile from the Portal block in some way. In the 
> sitemap in MyProfile you have to write  a copy of the profiles section 
> in the Portal block:
> 
> MyProfile sitemap
> -----------------
> 
> ...
> <profiles>
> <copletbasedata-load 
> uri="blocks:/profile/load-global-profile?profile=copletbasedata"/>
> <copletdata-global-load 
> uri="blocks:/profile/load-global-profile?profile=copletdata"/>
> <copletdata-role-load 
> uri="blocks:/profile/load-role-profile?profile=copletdata"/>
> <copletdata-user-load 
> uri="blocks:/profile/load-user-profile?profile=copletdata"/>
> <copletinstancedata-global-load 
> uri="blocks:/profile/load-global-profile?profile=copletinstancedata"/>
> <copletinstancedata-role-load 
> uri="blocks:/profile/load-role-profile?profile=copletinstancedata"/>
> <copletinstancedata-user-load 
> uri="blocks:/profile/load-user-profile?profile=copletinstancedata"/>
> <copletinstancedata-user-save 
> uri="blocks:/profile/save-user-profile?profile=copletinstancedata"/>
> <layout-global-load 
> uri="blocks:/profile/load-global-profile?profile=layout"/>
> <layout-role-load uri="blocks:/profile/load-role-profile?profile=layout"/>
> <layout-user-load uri="blocks:/profile/load-user-profile?profile=layout"/>
> <layout-user-save uri="blocks:/profile/save-user-profile?profile=layout"/>
> </profiles>
> ...
> <pipeline>
>  <match pattern="profile/load-user-profile">
>   ...
> </match>
> 
> Here the blocks protocol is supposed to first look in the own sitemap 
> (and find "load-user-profile") before it asks the super block. As you 
> can see you need a copy of the profiles section of the sitemap booth in 
> Portal and in MyProfile. 

No, you don't. The block "portal" only contains pipelines calls which the block 
"profile" provides in its sitemap:

Portal block
------------
- requires "MyProfile" that implements "profile"

<profiles>
  <copletbasedata-load
   uri="blocks:profile:/load-global-profile?profile=copletbasedata"/>
  <copletdata-global-load
   uri="blocks:profile:/load-global-profile?profile=copletdata"/>
   ..
</profiles>

(After reading Stefano's mail I found a mistake in my examples: The block name 
is a sub-protocol and not part of the path.)

You can have one block that provides default pipelines, let's call it 
"profile-default":

"profile-default"
-----------------
- implements "profile"

<map:match pattern="load-global-profile">
  ...
</map:match>


If you need special behaviour in your _custom_ profile block, you extend the 
"profile-default" block and override _only_ those parts that you want to see 
changed. In your custom portal block ("MyPortal") you change the requirement 
from "profile-default" to "MyProfile" and you're done.

"MyProfile"
-----------
- extends "profile-default"


> And you define and deploy small blocks for each 
> aspect you want to override in the original block. The behaviour of an 
> actual application will be spread out in all these small extended 
> blocks. I found it clumsy, complicated and burocratic compared to the 
> simple sitemap based extension mechanism I used in my example.

IIUC your point is that how your application works is spread over to many 
blocks. Maybe you're right but I don't think so, at least the examples we talked 
about here are overly complex using


>> What I do like is <mount uri-prefix="" src="blocks://portal"/> which 
>> makes it explicit what a block exports. I'm not sure about why this 
>> has to be a "two way contract".
> 
> 
> It must be a two way contract, as "extend and overide" is a two way 
> contract. If you have it one way you end up having to copy everything 
> that is an agregate of functionality as in the profile example above.

Yes, if something isn't designed for reusability, then you have to copy it. If 
you design for reusablity, you don't have to copy services.

> For another example of two way communication beween a default sitemap 
> and an extending one you can look at Forrest which make good use of 
> allowing user extensions 
> (http://forrest.apache.org/docs/dev/sitemap-ref.html, 
> http://svn.apache.org/viewcvs.cgi/forrest/trunk/main/webapp/sitemap.xmap?view=markup 
> e.g.).
> 
> Here is an example:
> 
>    <map:resource name="skinit">
>        <map:select type="exists">
>          <map:when 
> test="{project:skins-dir}{forrest:skin}/xslt/html/{type}.xsl">
>            <map:transform 
> src="{project:skins-dir}{forrest:skin}/xslt/html/{type}.xsl">
>              <map:parameter name="notoc" value="{notoc}"/>
>              <!-- For backwards-compat with 0.2 - 0.4 skins -->
>              <map:parameter name="isfaq" value="{notoc}"/>
>              <map:parameter name="nopdf" value="{nopdf}"/>
>              <map:parameter name="path" value="{path}"/>
>              <map:parameter name="config-file" value="{project:skinconf}"/>
>            </map:transform>
>          </map:when>
>          <map:otherwise>
>            <map:transform 
> src="{forrest:context}/skins/{forrest:skin}/xslt/html/{type}.xsl">
>              <map:parameter name="notoc" value="{notoc}"/>
>              <!-- For backwards-compat with 0.2 - 0.4 skins -->
>              <map:parameter name="isfaq" value="{notoc}"/>
>              <map:parameter name="nopdf" value="{nopdf}"/>
>              <map:parameter name="path" value="{path}"/>
>              <map:parameter name="config-file" value="{project:skinconf}"/>
>            </map:transform>
>          </map:otherwise>
>        </map:select>
>      <map:serialize/>
>    </map:resource>
> 
> if the style sheet exists in the extending directory given by 
> "project:skins-dir" it is used otherwise the default variant from 
> "forrest:context" is used. As you see it is a two way communication 
> there Forrest need explicit info about the loocation of the extending 
> application at deploy time. With the mechanism I propose we would get:
> 
> Forrest block sitemap
> ---------------------
> 
>    <map:resource name="skinit">
>      <map:transform 
> src="blocks:/skins/{forrest:skin}/xslt/html/{type}.xsl">
>      <map:parameter name="notoc" value="{notoc}"/>
>      <!-- For backwards-compat with 0.2 - 0.4 skins -->
>      <map:parameter name="isfaq" value="{notoc}"/>
>      <map:parameter name="nopdf" value="{nopdf}"/>
>      <map:parameter name="path" value="{path}"/>
>      <map:parameter name="config-file" value="{project:skinconf}"/>
>      </map:transform>
>      <map:serialize/>
>    </map:resource>
> 
> instead and could use Forrest from our own app with:
> 
> Own documentation pipeline
> --------------------------
> 
> <pipeline>
>  <match pattern="skins/common/xslt/html/document2html.xsl">
>    ...
>  </match>
> 
>  <mount uri-prefix="" src="blocks://forrest"/>
> </pipeline>
> 
> where mount:/ gives polymorphic lookup. The advantage, except for being 
> terser, with this solution compared to the one Forrest use today for the 
> block context is that the Forrest block doesn't need to know any 
> explicit paths to the extending application wich is especially important 
> if you want to use the same block in several contexts.

The same you reach if everything that should be extensible in Forrest, is moved 
into a "default-block". This can be overridden by a project specific block.

> 
>> If you write <copletdata-role-load 
>> uri="blocks:/load-role-profile?profile=copletdata"/> then it means 
>> that you make  it explicit what can be overriden and what not.
>> I would use <copletdata-role-load 
>> uri="blocks:/profile/load-role-profile?profile=copletdata"/> which 
>> requires another reference. Using the proposed <mount>-mechanism, you 
>> can reuse the "portal"-pipeline.
> 
> 
> I'm not certain that I follow you. I would (possibly) use:
> 
>  blocks://profile/load-profile
> 
> for refering to another block, and:
> 
>  blocks:/load-profile
> 
> for refering to the same block possibly with sub protocols:
> 
>  blocks:polymorph:
> 
> if we want to be explicit about when something can be looked up from an 
> extending sitemap
> 
>  blocks:super:
> 
> for refereing to the extended block.
> 
> A problem with blocks://profile, rather than blocks:profile// is if one 
> want to access the "root" block sitemap from a sub sitemap, but that 
> could maybe be done with blocks://this/.

Sorry, my usage of the blocks protocal was wrong in my former mails. I'm with 
Stefano here that the block is a sub-protocol and additionally we have a "super" 
sub-protocol referencing the parent block.

> 
>>                                        - o -
>>
>> I think for now we shoudn't support these two-way contracts but favour 
>> composition by references (incl. <map:mount uri="[another-block]"/>). 
>> If this gets too bureaucratic, we can still think about alternatives.
>>
>> WDYT?
> 
> 
> I think that it becomes to bureaucratic. But you maybe have some better 
> solutions to the issues I adress above. 

I think we should stop the discussion at this point for now (I don't think that 
anybody can follow it anymore). IIUC everything you proposed can be added in a 
backwards-compatible way to the existing proposal. But I'm confident we don't 
need it ;-)

> Also, I'm intersted in your view 
> about how to actually use the blocks in an application.

I can think of many scenarios where blocks make sense. We already talked abut 
them in this discussion (skinning, profiles, easy deployment, easy development, 
...). Does this answer your question or is it too general.

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Reinhard Poetz wrote:

> Daniel Fagerstrom wrote:
>
>> Reinhard Poetz wrote:
>
<snip/>

>> What does extends actually buy us here, couldn't we just use 
>> "requrires" for the relation to portal-skin/1.0.0.
>
> IIUC using "extends" was the original idea here.

I know, but I don't see any reasons to take that as written in stone. 
Extends is an implementation aspect in the otherwise declarative 
block.xml and as we have discussed it is probably better to be more 
explicit in the sitemap about what and how a block exposes things. 
Thurthermore since Stefano gave his original design there have been a 
trend towards considering the sitemap as the central point for 
configuration, look at Sylvain's and Carsten's recent work e.g. So my 
question remains, what does "extends" buy us?

>> <requires block="http://cocoon.apache.org/blocks/portal-skin/1.0.0" 
>> name="skin"/>
>>
>> and be explicit about what we expose from portal-skin/1.0.0?
>>
>>> SITEMAP.XMAP
>>> <map:match pattern="one-special.css">
>>>   <map:read src="styles/css/one-special.css"/>
>>> </map:match>
>>
>>
>>
>> Being explicit means that we end the sitemap with:
>>
>> <map:mount uri-prefix="" src="blocks://skin"/>
>
> >
>
>>>                                           - o -
>>>
>>> The project that wants to use the Portal is in the block "MyPortal". 
>>> It needs several components from "Portal" (generator, several 
>>> transformers) and it needs a block that provides the skin, or more 
>>> precisly, it needs a block that implements 
>>> http://cocoon.apache.org/interfaces/portal-skin/1.0. This can either 
>>> be "portal-skin", the default skin, or "MySkin", that provides one 
>>> additional CSS. Everything else is taken from "portal-skin".
>>>
>>>
>>> From my POV this solution is very clear and comprehensible. The 
>>> aspects "portal functionality" and "skinning" are separated and the 
>>> used implementations can simply be replaced by other implementations 
>>> (shown by using the "mySkin" block).
>>>
>>>                                           - o -
>>>
>>> What does your solution that ueses multiple inheritance look like? 
>>> (If this is a bad example to show the advantages of MI feel free to 
>>> enhance it!)
>>
>>
>>
>> First I will not use the term MI as it doesn't describe what I want 
>> to achieve that well and as it also seem to stir all kinds of bad 
>> reactions that distracts us from the task at hand.
>>
>> So I agree with most of what you show in your example, it looks neat. 
>> What I lack from it is how to reuse the sitemap in the Portal block.
>>
>> I would have a sitemap similar to the one in the demo portal in the 
>> Portal block. But e.g. the profiles part in the portal-handler 
>> configuration would rather be:
>>
>> Portal Sitemap
>> --------------
>>
>> ...
>> <profiles>
>>  <copletbasedata-load 
>> uri="blocks:/load-global-profile?profile=copletbasedata"/>
>>  <copletdata-global-load 
>> uri="blocks:/load-global-profile?profile=copletdata"/>
>>  <copletdata-role-load 
>> uri="blocks:/load-role-profile?profile=copletdata"/>
>>  <copletdata-user-load 
>> uri="blocks:/load-user-profile?profile=copletdata"/>
>>  <copletinstancedata-global-load 
>> uri="blocks:/load-global-profile?profile=copletinstancedata"/>
>>  <copletinstancedata-role-load 
>> uri="blocks:/load-role-profile?profile=copletinstancedata"/>
>>  <copletinstancedata-user-load 
>> uri="blocks:/load-user-profile?profile=copletinstancedata"/>
>>  <copletinstancedata-user-save 
>> uri="blocks:/save-user-profile?profile=copletinstancedata"/>
>>  <layout-global-load uri="blocks:/load-global-profile?profile=layout"/>
>>  <layout-role-load uri="blocks:/load-role-profile?profile=layout"/>
>>  <layout-user-load uri="blocks:/load-user-profile?profile=layout"/>
>>  <layout-user-save uri="blocks:/save-user-profile?profile=layout"/>
>> </profiles>
>> ...
>>
>> Meaning that the different configuration pipelines are found through 
>> the blocks manager that would ask the extending block (recursively) 
>> for the configuration pipelines first, and if they not are found 
>> there, the own pipeline would be used.
>>
>> Then MyPortal could redefine some of the configuration pipelines and 
>> reuse the rest from Portal:
>>
>> MyPortal Sitemap
>> ----------------
>>
>> ...
>> <pipeline>
>>  <match pattern="load-user-profile">
>>    ...
>>  </match>
>>
>>  <mount uri-prefix="" src="blocks://portal"/>
>> </pipline>
>> ...
>>
>> Now this mechanism is more limited than real inheritance. map:mount 
>> become a two way contract where the mounting sitemap can be asked 
>> about services through the block manager, but it doesn't export the 
>> interface of the "extended" block. If we have something like the we 
>> probably should have some way to differ between mounts that allow the 
>> mounted block to ask and those who don't.
>
> (I think) I understand what you want. You called it an "application 
> block" which is the base for all your applications. This application 
> block (e.g. a company portal) provides services that can be used and 
> customized by other blocks.

No it's much simpler ;) I'm not talking about reuse I'm talking about 
*use*. To make blocks a success they must of course be easy to use in 
user applications. And to make shure that they are easy to use, we must 
of course discuss what it looks like when we really use them.

So my application block above is not at all intended for reuse, it is an 
actual application (actually nearly all of what I have discussed in this 
thread is about ease of use rather than reuse). If you don't like 
packaging your applications as blocks that's fine with me we can discuss 
that case instead.

The reason that I want to package my applications as (not intended for 
reuse) blocks is that it will solve a number of practical problems for 
us in a convenient way. Today I have a (large) number of applications 
running under the same Cocoon at my developer machine. When we have 
added some new functionality to a webapp I run a script that packages 
the particular webapp with dependencies and some deployment info and 
installs it on a production machine. When the customer is satisfied with 
the test release I update the production release in a similar way. 
Packaging my webapp as a block will make it able for me to achieve the 
same thing without much scripting at all as it takes care about 
dependencies, deploy time parameters (db connections e.g.) and packaging.

For the idea of creating a reusable "application block" it is in my 
experience not such a good idea. We started that way when we wanted to 
reuse a whole application, using the design pattern that I have tried to 
explain in this thread. We did it more because of time constraint than 
because we actually believed it to be a good idea. Since then we have 
factored out a numeber of "vertical" blocks from the original 
application that handles different concerns, and that makes reuse much 
more flexible.

>
>>                                  --- o0o ---
>>
>> Concerning the skin I find it somewhat burocratic to need to define a 
>> new block for beeing able to extend it but I'm ok with it for the 
>> time beeing, we will see when we start to use the things. What I 
>> would prefer would be to do something like:
>>
>> MyPortal Sitemap
>> ----------------
>>
>> ...
>> <pipeline>
>>  <match pattern="load-user-profile">
>>    ...
>>  </match>
>>
>>  <match pattern="skin/one-special.css">
>>    <read src="styles/css/one-special.css"/>
>>   </match>
>>
>>  <mount uri-prefix="skin" src="blocks://skin"/>
>>
>>  <mount uri-prefix="" src="blocks://portal"/>
>> </pipline>
>> ...
>>
>>                                  --- o0o ---
>>
>> So what do you think about this?
>
>
> I think I got the idea. Personally, I would solve this by composition; 
> the profiling is just another reference of the block. Of course, as 
> Stefano said, blocks have to be designed for this. If the application 
> block hasn't factored out the profile aspect, then you can't replace 
> implementation A by implementation B:
>
> --------------------------------------------------------------------------- 
>
> "Application block" (to be reused in many projects)
> --------------------------------------------------------------------------- 
>
> <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>  id="http://mycompany.com/blocks/application-block/1.0.0">
>   <name>Application block</name>
>   <requirements>
>     <requires interface="http://mycompany.com/interfaces/skin/1.0"
>       name="skin"
>       default="http://mycompany.com/blocks/myskin/1.0.0"/>
>     <requires interface="http://cocoon.apache.org/interfaces/profile/1.0"
>       name="profile"
>       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
>     <requires interface="http://cocoon.apache.org/interfaces/portal/1.0"
>       name="portal"
>       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
>   </requirements>
> </block>

It would work, but to achieve what I did in a few sitemap lines (above) 
you have to create and deploy a special MyProfile block, and as I just 
wanted to override a few things in my customized profile I have to 
extend the original profile from the Portal block in some way. In the 
sitemap in MyProfile you have to write  a copy of the profiles section 
in the Portal block:

MyProfile sitemap
-----------------

...
<profiles>
 <copletbasedata-load 
uri="blocks:/profile/load-global-profile?profile=copletbasedata"/>
 <copletdata-global-load 
uri="blocks:/profile/load-global-profile?profile=copletdata"/>
 <copletdata-role-load 
uri="blocks:/profile/load-role-profile?profile=copletdata"/>
 <copletdata-user-load 
uri="blocks:/profile/load-user-profile?profile=copletdata"/>
 <copletinstancedata-global-load 
uri="blocks:/profile/load-global-profile?profile=copletinstancedata"/>
 <copletinstancedata-role-load 
uri="blocks:/profile/load-role-profile?profile=copletinstancedata"/>
 <copletinstancedata-user-load 
uri="blocks:/profile/load-user-profile?profile=copletinstancedata"/>
 <copletinstancedata-user-save 
uri="blocks:/profile/save-user-profile?profile=copletinstancedata"/>
 <layout-global-load 
uri="blocks:/profile/load-global-profile?profile=layout"/>
 <layout-role-load uri="blocks:/profile/load-role-profile?profile=layout"/>
 <layout-user-load uri="blocks:/profile/load-user-profile?profile=layout"/>
 <layout-user-save uri="blocks:/profile/save-user-profile?profile=layout"/>
</profiles>
...
<pipeline>
  <match pattern="profile/load-user-profile">
   ...
</match>

Here the blocks protocol is supposed to first look in the own sitemap 
(and find "load-user-profile") before it asks the super block. As you 
can see you need a copy of the profiles section of the sitemap booth in 
Portal and in MyProfile. And you define and deploy small blocks for each 
aspect you want to override in the original block. The behaviour of an 
actual application will be spread out in all these small extended 
blocks. I found it clumsy, complicated and burocratic compared to the 
simple sitemap based extension mechanism I used in my example.

> What I do like is <mount uri-prefix="" src="blocks://portal"/> which 
> makes it explicit what a block exports. I'm not sure about why this 
> has to be a "two way contract".

It must be a two way contract, as "extend and overide" is a two way 
contract. If you have it one way you end up having to copy everything 
that is an agregate of functionality as in the profile example above.

For another example of two way communication beween a default sitemap 
and an extending one you can look at Forrest which make good use of 
allowing user extensions 
(http://forrest.apache.org/docs/dev/sitemap-ref.html, 
http://svn.apache.org/viewcvs.cgi/forrest/trunk/main/webapp/sitemap.xmap?view=markup 
e.g.).

Here is an example:

    <map:resource name="skinit">
        <map:select type="exists">
          <map:when test="{project:skins-dir}{forrest:skin}/xslt/html/{type}.xsl">
            <map:transform src="{project:skins-dir}{forrest:skin}/xslt/html/{type}.xsl">
              <map:parameter name="notoc" value="{notoc}"/>
              <!-- For backwards-compat with 0.2 - 0.4 skins -->
              <map:parameter name="isfaq" value="{notoc}"/>
              <map:parameter name="nopdf" value="{nopdf}"/>
              <map:parameter name="path" value="{path}"/>
              <map:parameter name="config-file" value="{project:skinconf}"/>
            </map:transform>
          </map:when>
          <map:otherwise>
            <map:transform src="{forrest:context}/skins/{forrest:skin}/xslt/html/{type}.xsl">
              <map:parameter name="notoc" value="{notoc}"/>
              <!-- For backwards-compat with 0.2 - 0.4 skins -->
              <map:parameter name="isfaq" value="{notoc}"/>
              <map:parameter name="nopdf" value="{nopdf}"/>
              <map:parameter name="path" value="{path}"/>
              <map:parameter name="config-file" value="{project:skinconf}"/>
            </map:transform>
          </map:otherwise>
        </map:select>
      <map:serialize/>
    </map:resource>

if the style sheet exists in the extending directory given by 
"project:skins-dir" it is used otherwise the default variant from 
"forrest:context" is used. As you see it is a two way communication 
there Forrest need explicit info about the loocation of the extending 
application at deploy time. With the mechanism I propose we would get:

Forrest block sitemap
---------------------

    <map:resource name="skinit">
      <map:transform src="blocks:/skins/{forrest:skin}/xslt/html/{type}.xsl">
      <map:parameter name="notoc" value="{notoc}"/>
      <!-- For backwards-compat with 0.2 - 0.4 skins -->
      <map:parameter name="isfaq" value="{notoc}"/>
      <map:parameter name="nopdf" value="{nopdf}"/>
      <map:parameter name="path" value="{path}"/>
      <map:parameter name="config-file" value="{project:skinconf}"/>
      </map:transform>
      <map:serialize/>
    </map:resource>

instead and could use Forrest from our own app with:

Own documentation pipeline
--------------------------

<pipeline>
  <match pattern="skins/common/xslt/html/document2html.xsl">
    ...
  </match>

  <mount uri-prefix="" src="blocks://forrest"/>
</pipeline>

where mount:/ gives polymorphic lookup. The advantage, except for being 
terser, with this solution compared to the one Forrest use today for the 
block context is that the Forrest block doesn't need to know any 
explicit paths to the extending application wich is especially important 
if you want to use the same block in several contexts.

> If you write <copletdata-role-load 
> uri="blocks:/load-role-profile?profile=copletdata"/> then it means 
> that you make  it explicit what can be overriden and what not.
> I would use <copletdata-role-load 
> uri="blocks:/profile/load-role-profile?profile=copletdata"/> which 
> requires another reference. Using the proposed <mount>-mechanism, you 
> can reuse the "portal"-pipeline.

I'm not certain that I follow you. I would (possibly) use:

  blocks://profile/load-profile

for refering to another block, and:

  blocks:/load-profile

for refering to the same block possibly with sub protocols:

  blocks:polymorph:

if we want to be explicit about when something can be looked up from an 
extending sitemap

  blocks:super:

for refereing to the extended block.

A problem with blocks://profile, rather than blocks:profile// is if one 
want to access the "root" block sitemap from a sub sitemap, but that 
could maybe be done with blocks://this/.

>                                        - o -
>
> I think for now we shoudn't support these two-way contracts but favour 
> composition by references (incl. <map:mount uri="[another-block]"/>). 
> If this gets too bureaucratic, we can still think about alternatives.
>
> WDYT?

I think that it becomes to bureaucratic. But you maybe have some better 
solutions to the issues I adress above. Also, I'm intersted in your view 
about how to actually use the blocks in an application.

/Daniel


Re: [RT] composition vs. inheritance in blocks

Posted by Reinhard Poetz <re...@apache.org>.
Daniel Fagerstrom wrote:
> Reinhard Poetz wrote:
> <snip/>
> 
>> As promised, I've tried to come up with some pseudo-code that shows 
>> how "single-inheritance + composition" looks like in a particular 
>> example (portal + skinning).
> 
> 
> That is excelent.
> 
>>                                           - o -
>>
>> We have following block interfaces:
>> ===================================
>>  - http://cocoon.apache.org/interfaces/portal/1.0
>>  - http://cocoon.apache.org/interfaces/portal-skin/1.0
>>  - http://mycompany.com/interfaces/skin/1.0
>>
>>
>> Here the block implementations:
>> ===============================
>>
>> --------------------------------------------------------------------------- 
>>
>> "Portal"
>> --------------------------------------------------------------------------- 
>>
>> BLOCK.XML
>> <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>>  id="http://cocoon.apache.org/blocks/portal/1.0.0">
>>   <name>portal</name>
>>   <requirements>
>>     <requires 
>> interface="http://cocoon.apache.org/interface/portal-skin/1.0"
>>      name="portal"
>>      default="http://cocoon.apache.org/blocks/portal-skin/1.0.0"/>
>>   </requirements>
>>   <implements>
>>     <interface id="http://cocoon.apache.org/interfaces/portal/1.0"/>
>>   </implements>
>> </block>
>>
>> --------------------------------------------------------------------------- 
>>
>> "Portal-Skin"
>> --------------------------------------------------------------------------- 
>>
>> BLOCK.XML   <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>>  id="http://cocoon.apache.org/blocks/portal-skin/1.0.0">
>>   <name>portal-skin</name>
>>   <implements>
>>     <interface id="http://cocoon.apache.org/interfaces/portal-skin/1.0"/>
>>   </implements>
>> </block>
>>
>> SITEMAP.XMAP
>> <map:match pattern="*.css">
>>   <map:read src="styles/css/{1}.css"/>
>> </map:match>
>> <map:match pattern="styles/portal-page.xsl">
>>   <map:read src="styles/portal-page.xsl"/>
>> </map:match>
>>
>>
>> --------------------------------------------------------------------------- 
>>
>> "MyPortal"
>> --------------------------------------------------------------------------- 
>>
> 
> 
> Is MyPortal an actual application or is it a block that you are going to 
> use for building applications? Let's call them application block and 
> reusable block respectively. We must take application blocks into 
> account to get the whole picture, so I assume that MyPortal is an 
> application block that will contain real user profiles etc. Seeing that 
> it neither implements nor extends but rather use the portal block 
> enforces that view.
> 
>> BLOCK.XML   <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>>  id="http://mycompany.com/blocks/my-Portal/1.0.0">
>>   <name>MyPortal</name>
>>   <requirements>
>>     <requires interface="http://mycompany.com/interfaces/skin/1.0"
>>       name="skin"
>>       default="http://mycompany.com/blocks/myskin/1.0.0"/>
>>     <requires interface="http://cocoon.apache.org/interfaces/portal/1.0"
>>       name="portal"
>>       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
>>   </requirements>
>> </block>
>>
>> SITEMAP.XMAP
>> <map:match pattern="portal">
>>   <map:act type="portal:auth-protect">
>>     <map:parameter name="handler" value="portal-handler"/>
>>     <map:parameter name="application" value="portal"/>
>>
>>     <map:generate type="portal:portal"/>
>>     <map:transform src="blocks://skin/styles/portal-page.xsl">
>>       <map:parameter name="user" value="{ID}"/>
>>     </map:transform>
>>     <map:transform type="core:cinclude"/>
>>     <map:transform type="portal:portal-coplet"/>
>>     <map:transform type="portal:portal-new-eventlink"/>
>>     <map:transform type="core:encodeURL"/>
>>     <map:serialize type="portal:html-include"/>
>>   </map:act>
>> </map:match>
> 
> 
> Shouldn't this sitemap be part of Portal rather than MyPortal, AFAICS it 
> is a "blockified" version of the "portal" rule from the demo portal, so 
> there seem no to be no reason to reimplement it in MyBlock.
> 
>> (Note: Most of the used components come from the portal block, the 
>> rest from Cocon core; the stylesheet is provided by the "skin" block.)
>>
>> --------------------------------------------------------------------------- 
>>
>> "MySkin"
>> --------------------------------------------------------------------------- 
>>
>> BLOCK.XML
>> <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>>  id="http://mycompany.com/blocks/my-Portal/1.0.0">
>>   <name>MySkin</name>
>>   <implements>
>>     <interface id="http://cocoon.apache.org/interfaces/portal/1.0"/>
>>   </implements>
>>   <extends>http://cocoon.apache.org/blocks/portal-skin/1.0.0</extends>
>> </block>
> 
> 
> What does extends actually buy us here, couldn't we just use "requrires" 
> for the relation to portal-skin/1.0.0.

IIUC using "extends" was the original idea here.

> 
> <requires block="http://cocoon.apache.org/blocks/portal-skin/1.0.0" 
> name="skin"/>
> 
> and be explicit about what we expose from portal-skin/1.0.0?
> 
>> SITEMAP.XMAP
>> <map:match pattern="one-special.css">
>>   <map:read src="styles/css/one-special.css"/>
>> </map:match>
> 
> 
> Being explicit means that we end the sitemap with:
> 
> <map:mount uri-prefix="" src="blocks://skin"/>
 >
>>                                           - o -
>>
>> The project that wants to use the Portal is in the block "MyPortal". 
>> It needs several components from "Portal" (generator, several 
>> transformers) and it needs a block that provides the skin, or more 
>> precisly, it needs a block that implements 
>> http://cocoon.apache.org/interfaces/portal-skin/1.0. This can either 
>> be "portal-skin", the default skin, or "MySkin", that provides one 
>> additional CSS. Everything else is taken from "portal-skin".
>>
>>
>> From my POV this solution is very clear and comprehensible. The 
>> aspects "portal functionality" and "skinning" are separated and the 
>> used implementations can simply be replaced by other implementations 
>> (shown by using the "mySkin" block).
>>
>>                                           - o -
>>
>> What does your solution that ueses multiple inheritance look like? (If 
>> this is a bad example to show the advantages of MI feel free to 
>> enhance it!)
> 
> 
> First I will not use the term MI as it doesn't describe what I want to 
> achieve that well and as it also seem to stir all kinds of bad reactions 
> that distracts us from the task at hand.
> 
> So I agree with most of what you show in your example, it looks neat. 
> What I lack from it is how to reuse the sitemap in the Portal block.
> 
> I would have a sitemap similar to the one in the demo portal in the 
> Portal block. But e.g. the profiles part in the portal-handler 
> configuration would rather be:
> 
> Portal Sitemap
> --------------
> 
> ...
> <profiles>
>  <copletbasedata-load 
> uri="blocks:/load-global-profile?profile=copletbasedata"/>
>  <copletdata-global-load 
> uri="blocks:/load-global-profile?profile=copletdata"/>
>  <copletdata-role-load uri="blocks:/load-role-profile?profile=copletdata"/>
>  <copletdata-user-load uri="blocks:/load-user-profile?profile=copletdata"/>
>  <copletinstancedata-global-load 
> uri="blocks:/load-global-profile?profile=copletinstancedata"/>
>  <copletinstancedata-role-load 
> uri="blocks:/load-role-profile?profile=copletinstancedata"/>
>  <copletinstancedata-user-load 
> uri="blocks:/load-user-profile?profile=copletinstancedata"/>
>  <copletinstancedata-user-save 
> uri="blocks:/save-user-profile?profile=copletinstancedata"/>
>  <layout-global-load uri="blocks:/load-global-profile?profile=layout"/>
>  <layout-role-load uri="blocks:/load-role-profile?profile=layout"/>
>  <layout-user-load uri="blocks:/load-user-profile?profile=layout"/>
>  <layout-user-save uri="blocks:/save-user-profile?profile=layout"/>
> </profiles>
> ...
> 
> Meaning that the different configuration pipelines are found through the 
> blocks manager that would ask the extending block (recursively) for the 
> configuration pipelines first, and if they not are found there, the own 
> pipeline would be used.
> 
> Then MyPortal could redefine some of the configuration pipelines and 
> reuse the rest from Portal:
> 
> MyPortal Sitemap
> ----------------
> 
> ...
> <pipeline>
>  <match pattern="load-user-profile">
>    ...
>  </match>
> 
>  <mount uri-prefix="" src="blocks://portal"/>
> </pipline>
> ...
> 
> Now this mechanism is more limited than real inheritance. map:mount 
> become a two way contract where the mounting sitemap can be asked about 
> services through the block manager, but it doesn't export the interface 
> of the "extended" block. If we have something like the we probably 
> should have some way to differ between mounts that allow the mounted 
> block to ask and those who don't.


(I think) I understand what you want. You called it an "application block" which 
is the base for all your applications. This application block (e.g. a company 
portal) provides services that can be used and customized by other blocks.

>                                  --- o0o ---
> 
> Concerning the skin I find it somewhat burocratic to need to define a 
> new block for beeing able to extend it but I'm ok with it for the time 
> beeing, we will see when we start to use the things. What I would prefer 
> would be to do something like:
> 
> MyPortal Sitemap
> ----------------
> 
> ...
> <pipeline>
>  <match pattern="load-user-profile">
>    ...
>  </match>
> 
>  <match pattern="skin/one-special.css">
>    <read src="styles/css/one-special.css"/>
>   </match>
> 
>  <mount uri-prefix="skin" src="blocks://skin"/>
> 
>  <mount uri-prefix="" src="blocks://portal"/>
> </pipline>
> ...
> 
>                                  --- o0o ---
> 
> So what do you think about this?

I think I got the idea. Personally, I would solve this by composition; the 
profiling is just another reference of the block. Of course, as Stefano said, 
blocks have to be designed for this. If the application block hasn't factored 
out the profile aspect, then you can't replace implementation A by implementation B:

---------------------------------------------------------------------------
"Application block" (to be reused in many projects)
---------------------------------------------------------------------------
<block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
  id="http://mycompany.com/blocks/application-block/1.0.0">
   <name>Application block</name>
   <requirements>
     <requires interface="http://mycompany.com/interfaces/skin/1.0"
       name="skin"
       default="http://mycompany.com/blocks/myskin/1.0.0"/>
     <requires interface="http://cocoon.apache.org/interfaces/profile/1.0"
       name="profile"
       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
     <requires interface="http://cocoon.apache.org/interfaces/portal/1.0"
       name="portal"
       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
   </requirements>
</block>


What I do like is <mount uri-prefix="" src="blocks://portal"/> which makes it 
explicit what a block exports. I'm not sure about why this has to be a "two way 
contract".
If you write <copletdata-role-load 
uri="blocks:/load-role-profile?profile=copletdata"/> then it means that you make 
  it explicit what can be overriden and what not.
I would use <copletdata-role-load 
uri="blocks:/profile/load-role-profile?profile=copletdata"/> which requires 
another reference. Using the proposed <mount>-mechanism, you can reuse the 
"portal"-pipeline.

                                        - o -

I think for now we shoudn't support these two-way contracts but favour 
composition by references (incl. <map:mount uri="[another-block]"/>). If this 
gets too bureaucratic, we can still think about alternatives.

WDYT?

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] composition vs. inheritance in blocks

Posted by Nicola Ken Barozzi <ni...@apache.org>.
Daniel Fagerstrom wrote:
...
> This means IMO that we have to spend time discussing things even if it 
> in the short time horizont and for ones own goals whould have seemed 
> more productive to just commit some code.

Or commit two codes in separate branches and see what works best.

OTOMH, all this smells a lot like the Microsoft COM model versus 
language features.
It may be beneficial to read things on the Microsoft Component Object 
Model, as IIRC it used composition instead of inheritance, with 
analogous reasoning.

-- 
Nicola Ken Barozzi                   nicolaken@apache.org
             - verba volant, scripta manent -
    (discussions get forgotten, just code remains)
---------------------------------------------------------------------


Re: [RT] composition vs. inheritance in blocks

Posted by Stefano Mazzocchi <st...@apache.org>.
Daniel Fagerstrom wrote:

> As Stefano doesn't work fulltime at Cocoon anymore, the rest of us must 
> take our reponsibilty and make shure that our individual ideas actually 
> intgrates with others ideas and are benefical for Cocoon as a whole.

Daniel,

I have never worked fulltime on Cocoon and I have a long track records 
of keeping an open mind about architectural decisions and suggestions 
and I have not changed my attitude.

At the end of the day, my vote here counts as one, just like yours, so 
if you feel I'm an obstacle for your design ideas, get over it and do 
yourself a favor understanding that the value of this project is the 
community reaction, not the individual action.

-- 
Stefano.


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Reinhard Poetz wrote:

> Stefano Mazzocchi wrote:
>
>> Thank you.
>>
>> [boy this was exhausting]
>
>
> yes it was and maybe more dicussions will follow.

As both Stefano and I are involved in real blocks it seem unavoidable ;)

Although a friendlier discussion probably had been more efficient, we 
actually produced a lot of concretization and clarification of the 
involved concepts, so I think it lead us closer to the goal.

> Daniel, some others and I are putting a lot of energy into making real 
> blocks reality and its important that we _all_ follow the same vision 
> (in the end). Berin summarized 
> (http://www.jroller.com/page/bloritsch/20050401#why_can_t_oss_do) it 
> very well why I'm sure that we will be successful and that we are 
> close to the next step on Cocoon's ladder of evolution.

I agree that a common vision is central for our success. If we are lazy 
and just focused on keeping everything nice and cozy, the end result 
risk to be a commity product, a patch work of small individual visons 
whithout coherency. Such a thing will at most be mediocre.

We can compare Cocoon as a publishing framework which is based on one 
strong vision with Cocoon as a webapp framework where several different 
approaches coexists, whithout much integration and where we haven't 
pruned away abanoned paths. And as the different approaches are good at 
different things one often has to be knowledgable in all of them to 
build applications. Something that makes it unnecesarilly hard to learn 
developing Cocoon webapps and something that diffusses our effort as 
everything has to be supported.

As Stefano doesn't work fulltime at Cocoon anymore, the rest of us must 
take our reponsibilty and make shure that our individual ideas actually 
intgrates with others ideas and are benefical for Cocoon as a whole.

This means IMO that we have to spend time discussing things even if it 
in the short time horizont and for ones own goals whould have seemed 
more productive to just commit some code.

/Daniel


Re: [RT] composition vs. inheritance in blocks

Posted by Reinhard Poetz <re...@apache.org>.
Stefano Mazzocchi wrote:

> Thank you.
> 
> [boy this was exhausting]

yes it was and maybe more dicussions will follow. Daniel, some others and I are 
putting a lot of energy into making real blocks reality and its important that 
we _all_ follow the same vision (in the end). Berin summarized 
(http://www.jroller.com/page/bloritsch/20050401#why_can_t_oss_do) it very well 
why I'm sure that we will be successful and that we are close to the next step 
on Cocoon's ladder of evolution.

-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] composition vs. inheritance in blocks

Posted by Stefano Mazzocchi <st...@apache.org>.

Daniel Fagerstrom wrote:
> Stefano Mazzocchi wrote:
> 
>> Daniel Fagerstrom wrote:
>>
>>> Concerning the skin I find it somewhat burocratic to need to define a 
>>> new block for beeing able to extend it but I'm ok with it for the 
>>> time beeing, we will see when we start to use the things. 
>>
>>
>>
>> Cool.
>>
>>> What I would prefer would be to do something like:
>>>
>>> MyPortal Sitemap
>>> ----------------
>>>
>>> ...
>>> <pipeline>
>>>  <match pattern="load-user-profile">
>>>    ...
>>>  </match>
>>>
>>>  <match pattern="skin/one-special.css">
>>>    <read src="styles/css/one-special.css"/>
>>>   </match>
>>>
>>>  <mount uri-prefix="skin" src="blocks://skin"/>
>>>
>>>  <mount uri-prefix="" src="blocks://portal"/>
>>> </pipline>
>>> ...
>>>
>>>                                  --- o0o ---
>>>
>>> So what do you think about this?
>>
>>
>>
>> Did you really mean the above or you meant
>>
>>  <mount uri-prefix="skin" src="block:skin://"/>
>>  <mount uri-prefix="" src="block:portal://"/>
> 
>  >
>  > ?
> 
> I meant what you suggest, I adapted my notation to Reinhard's example.
> 
>> in that case, and the above is your sitemap mount at /, how do you 
>> avoid the conflict emerging by the fact that somebody else has mount 
>> another implementation of the skin block on /skin ?
> 
> 
> I general I would only mount applications or applications that are 
> packaged as a block to an external path. The blocks that just are part 
> of applications will only get accessed through the blocks protocol. And 
> its quite likely that I want to control or adapt the uri space from the 
> used block (skin e.g.) in my application which only is possible if I 
> serve it through the sitemap of my application.
> 
> In the example above I would only have mounted MyPortal if I acually 
> used it as an application and not as a building block in another 
> application. And I would only have mounted it at "/" if it was the sole 
> or main application within my Cocoon instance. So I don't see why I 
> should get any conflicts.
> 
> Furthermore it's not either or, if you have some good reason for 
> mounting all your (building) blocks at the exposed uri space of your 
> Cocoon I have no plans in trying to stop you from it ;). Then you should 
> of course avoid mounting them so that they shadow the uri space of other 
> blocks or your applications.
> 
>> Daniel, I perfectly understand why you want those features, but I have 
>> a bigger goal: allow blocks to be really polymorphic, not just an 
>> easier deploy tool.
> 
> 
> Cool, then we share the same goal. Real polymorphism means that if I 
> have two classes:
> 
> public class Base {
>   public String name() { return "Base"; }
>   public String msg() { return "I'm " + foo(); }
> }
> 
> public class Extended extends Base {
>   public String name() { return "Extended"; }
> }
> 
> then
> 
> Extended e = new Extended();
> System.out.println(e.name());
> 
> will obviously print "Extended".
> 
> and
> 
> System.out.println(e.msg());
> 
> will print "I'm Extended" rather than "I'm Base".
> 
>                                   --- o0o ---
> 
> Translating this to blocks we get:
> 
> BaseBlock Sitemap
> -----------------
> 
> <pipeline>
>   <match pattern="content">
>     <read src="base-content.xml"/>
>   </match>
> 
>   <match pattern="view">
>     <generate src="blocks:/content"/>
>     <transform src="content2html.xsl"/>
>     <serialize/>
>   </match>
> </pipeline>
> 
> ExtendedBlock Sitemap
> ---------------------
> 
> ExtendedBlock extends BaseBlock
> 
> <pipeline>
>   <match pattern="content">
>     <read src="extended-content.xml"/>
>   </match>
> </pipeline>
> 
> Saying that we mount ExtendedBlock at "/" then
> 
>   /content
> 
> obviuosly will respond with the content of "extended-content.xml"
> 
> with mere shadowing
> 
>   /view
> 
> would respond with an html rendered view of "base-content.xml" and with 
> real polymorphism it would respond with an html rendered view of 
> "extended-content.xml".

Daniel, you are beating a dead horse. This has been in the original 
design since day 1.

What I'm fighting against, in case you haven't noticed yet, is the 
concept of a blocking having more than one "extends", not on the concept 
of extension alltogether.

>                                   --- o0o ---
> 
> As long as we agree that we want real polymorphism for blocks rather 
> than just shadowing, I can wait with some adaption of MI until other 
> people see that they need it.

Great. Hopefully we can move on now.

>> With that in mind, the complexity increases, if you are composing your 
>> block out of several others (if you have just one block or you just 
>> use ones that provide java components, that is not the case).
>>
>> "explicit" mounting of blocks yields mount collision nightmares: 
>> blocks should be mount implicitly and thru the block manager (sort of 
>> a mount-table on steroids).
> 
> Are you refering to the blocks wiring.xml 
> (http://wiki.apache.org/cocoon/BlocksWiring)?

yes

>> explicit mounting works fine only if you are in control of all the 
>> dependencies, but this cannot be assumed, since blocks should be 
>> downloadable from the outside as well and might bring new dependencies.
> 
> Can you give an example of how this could happen?

You install "Linotype2", is a real block and it requires "Linotype 
Skin", "JCR Repository", "RDF TripleStore". The block manager goes to 
the block library on cocoon.apache.org and finds a list of possible 
blocks that implement those interfaces and that are known to be 
compatible with the version of the block you are now installing.

A dialog between you, the block manager and the block mirrors starts. 
The blocks are downloaded, unpacked, verified, installed and configured.

One of the configurations is the blocks suggest you their default mount 
point (or not, depending if the block is meant for direct public 
exposure or not), but you like your URIs in italian, so you move them.

All this was done without touching a single line in any block, including 
yours.

>> This said, I can't stop the above from happening: even if we have 
>> implicit mounting, you can go ahead and 'remount' it explicitly as you 
>> did above.
>>
>> The fact is that it's not needed if you do the following:
>>
>> <pipeline>
>>   <match pattern="load-user-profile">
>>     ...
>>   </match>
>>
>>   <match pattern="skin/one-special.css">
>>     <read src="styles/css/one-special.css"/>
>>    </match>
>>
>>   <mount-blocks/>
>>
>> </pipline>
> 
> What does "mount-blocks" do?

That's an idea I've been playing with, the use of <mount-blocks/> as the 
mounting equivalent of <xsl:apply-templates/> not sure it's a good idea, 
but allows you to explicitly indicate in what part of the pipeline the 
block mounts happen.

It solves some problems (and makes things more explicit) but I'm still 
not sure it really helps.

>> and the above is the sitemap of MyPortal that extends "Portal" and 
>> it's mount on / and requires "Skin" that is mount on '/skin'.
>>
>> Note however, how if you mount 'Skin' on '/style', the above breaks! 
>> The way I designed it to avoid this problem is:
> 
> As explained above, I don't mount Skin in itself, MyPortal only access 
> Skin through "blocks:skin" and its mount of skin in its own sitemap, so 
> nothing will not break.

Hmmm, I see.

The reason why I don't like this is that if I have things like a skin, 
which might be shared by lots of blocks, mount it in a 'block-relative' 
URL makes it appear as the same information is duplicated all over the 
place, making proxying/caching less efficient.

But sure, it's an approach.

>> MyPortal
>>  - extends Portal
>>  - requires Skin
>>  - mount on "/"
>> -----------------
>>
>>  <pipeline>
>>   <match pattern="load-user-profile">
>>     ...
>>   </match>
>>
>>  </pipeline>
>>
>> MySkin
>>  - extends Skin
>>  - mount on "/styles/"
>> ----------------------
>>
>>  <pipeline>
>>
>>   <match pattern="one-special.css">
>>    <read src="styles/css/one-special.css"/>
>>   </match>
>>
>>  </pipeline>
>>
>> Since <mount> exists and block: will be a Source protocol, it's 
>> impossible to stop you from doing explicit block mounting into your 
>> own block URL space. Note that this scatters the URL control in many 
>> files, instead of centralizing it at the block management level.
> 
> 
> I usually have several applications running under one Cocoon, so for me 
> its not attrcative to handle the "whithin application" url space in a 
> central place, I'll do that in the main sitemap of my application 
> (application block) instead. At the central level I would only mount my 
> applications and possibly some central resources that I want to make 
> available for all applications, without any adaptions or restrictions.
 >
>> I personally won't use it for the above reasons, but if it floats your 
>> boat, go ahead.
> 
> 
> Cool.
> 
>> My point remains: we don't need multiple inheritance of blocks to 
>> achieve what you need!
> 
> 
> As you have avoided commenting on my use cases for the adapted form of 
> MI that I have proposed, it seem to me like a rather far reaching 
> conclusion.
> 
> But we obviously doesn't get anywhere in this discussion. So let's move 
> on and start to actualy design and implement the blocks manager for 
> really polymorphic blocks with single inheritance.

Thank you.

[boy this was exhausting]

-- 
Stefano.


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Stefano Mazzocchi wrote:
> Daniel Fagerstrom wrote:
> 
>> Concerning the skin I find it somewhat burocratic to need to define a 
>> new block for beeing able to extend it but I'm ok with it for the time 
>> beeing, we will see when we start to use the things. 
> 
> 
> Cool.
> 
>> What I would prefer would be to do something like:
>>
>> MyPortal Sitemap
>> ----------------
>>
>> ...
>> <pipeline>
>>  <match pattern="load-user-profile">
>>    ...
>>  </match>
>>
>>  <match pattern="skin/one-special.css">
>>    <read src="styles/css/one-special.css"/>
>>   </match>
>>
>>  <mount uri-prefix="skin" src="blocks://skin"/>
>>
>>  <mount uri-prefix="" src="blocks://portal"/>
>> </pipline>
>> ...
>>
>>                                  --- o0o ---
>>
>> So what do you think about this?
> 
> 
> Did you really mean the above or you meant
> 
>  <mount uri-prefix="skin" src="block:skin://"/>
>  <mount uri-prefix="" src="block:portal://"/>
 >
 > ?

I meant what you suggest, I adapted my notation to Reinhard's example.

> in that case, and the above is your sitemap mount at /, how do you avoid 
> the conflict emerging by the fact that somebody else has mount another 
> implementation of the skin block on /skin ?

I general I would only mount applications or applications that are 
packaged as a block to an external path. The blocks that just are part 
of applications will only get accessed through the blocks protocol. And 
its quite likely that I want to control or adapt the uri space from the 
used block (skin e.g.) in my application which only is possible if I 
serve it through the sitemap of my application.

In the example above I would only have mounted MyPortal if I acually 
used it as an application and not as a building block in another 
application. And I would only have mounted it at "/" if it was the sole 
or main application within my Cocoon instance. So I don't see why I 
should get any conflicts.

Furthermore it's not either or, if you have some good reason for 
mounting all your (building) blocks at the exposed uri space of your 
Cocoon I have no plans in trying to stop you from it ;). Then you should 
of course avoid mounting them so that they shadow the uri space of other 
blocks or your applications.

> Daniel, I perfectly understand why you want those features, but I have a 
> bigger goal: allow blocks to be really polymorphic, not just an easier 
> deploy tool.

Cool, then we share the same goal. Real polymorphism means that if I 
have two classes:

public class Base {
   public String name() { return "Base"; }
   public String msg() { return "I'm " + foo(); }
}

public class Extended extends Base {
   public String name() { return "Extended"; }
}

then

Extended e = new Extended();
System.out.println(e.name());

will obviously print "Extended".

and

System.out.println(e.msg());

will print "I'm Extended" rather than "I'm Base".

                                   --- o0o ---

Translating this to blocks we get:

BaseBlock Sitemap
-----------------

<pipeline>
   <match pattern="content">
     <read src="base-content.xml"/>
   </match>

   <match pattern="view">
     <generate src="blocks:/content"/>
     <transform src="content2html.xsl"/>
     <serialize/>
   </match>
</pipeline>

ExtendedBlock Sitemap
---------------------

ExtendedBlock extends BaseBlock

<pipeline>
   <match pattern="content">
     <read src="extended-content.xml"/>
   </match>
</pipeline>

Saying that we mount ExtendedBlock at "/" then

   /content

obviuosly will respond with the content of "extended-content.xml"

with mere shadowing

   /view

would respond with an html rendered view of "base-content.xml" and with 
real polymorphism it would respond with an html rendered view of 
"extended-content.xml".

                                   --- o0o ---

As long as we agree that we want real polymorphism for blocks rather 
than just shadowing, I can wait with some adaption of MI until other 
people see that they need it.

> With that in mind, the complexity increases, if you are composing your 
> block out of several others (if you have just one block or you just use 
> ones that provide java components, that is not the case).
> 
> "explicit" mounting of blocks yields mount collision nightmares: blocks 
> should be mount implicitly and thru the block manager (sort of a 
> mount-table on steroids).

Are you refering to the blocks wiring.xml 
(http://wiki.apache.org/cocoon/BlocksWiring)?

> explicit mounting works fine only if you are 
> in control of all the dependencies, but this cannot be assumed, since 
> blocks should be downloadable from the outside as well and might bring 
> new dependencies.

Can you give an example of how this could happen?

> This said, I can't stop the above from happening: even if we have 
> implicit mounting, you can go ahead and 'remount' it explicitly as you 
> did above.
> 
> The fact is that it's not needed if you do the following:
> 
> <pipeline>
>   <match pattern="load-user-profile">
>     ...
>   </match>
> 
>   <match pattern="skin/one-special.css">
>     <read src="styles/css/one-special.css"/>
>    </match>
> 
>   <mount-blocks/>
> 
> </pipline>

What does "mount-blocks" do?

> 
> and the above is the sitemap of MyPortal that extends "Portal" and it's 
> mount on / and requires "Skin" that is mount on '/skin'.
> 
> Note however, how if you mount 'Skin' on '/style', the above breaks! The 
> way I designed it to avoid this problem is:

As explained above, I don't mount Skin in itself, MyPortal only access 
Skin through "blocks:skin" and its mount of skin in its own sitemap, so 
nothing will not break.

> MyPortal
>  - extends Portal
>  - requires Skin
>  - mount on "/"
> -----------------
> 
>  <pipeline>
>   <match pattern="load-user-profile">
>     ...
>   </match>
> 
>  </pipeline>
> 
> MySkin
>  - extends Skin
>  - mount on "/styles/"
> ----------------------
> 
>  <pipeline>
> 
>   <match pattern="one-special.css">
>    <read src="styles/css/one-special.css"/>
>   </match>
> 
>  </pipeline>
> 
> Since <mount> exists and block: will be a Source protocol, it's 
> impossible to stop you from doing explicit block mounting into your own 
> block URL space. Note that this scatters the URL control in many files, 
> instead of centralizing it at the block management level.

I usually have several applications running under one Cocoon, so for me 
its not attrcative to handle the "whithin application" url space in a 
central place, I'll do that in the main sitemap of my application 
(application block) instead. At the central level I would only mount my 
applications and possibly some central resources that I want to make 
available for all applications, without any adaptions or restrictions.

> I personally won't use it for the above reasons, but if it floats your 
> boat, go ahead.

Cool.

> My point remains: we don't need multiple inheritance of blocks to 
> achieve what you need!

As you have avoided commenting on my use cases for the adapted form of 
MI that I have proposed, it seem to me like a rather far reaching 
conclusion.

But we obviously doesn't get anywhere in this discussion. So let's move 
on and start to actualy design and implement the blocks manager for 
really polymorphic blocks with single inheritance.

/Daniel

Re: [RT] composition vs. inheritance in blocks

Posted by Stefano Mazzocchi <st...@apache.org>.
Daniel Fagerstrom wrote:

> Concerning the skin I find it somewhat burocratic to need to define a 
> new block for beeing able to extend it but I'm ok with it for the time 
> beeing, we will see when we start to use the things. 

Cool.

> What I would prefer 
> would be to do something like:
> 
> MyPortal Sitemap
> ----------------
> 
> ...
> <pipeline>
>  <match pattern="load-user-profile">
>    ...
>  </match>
> 
>  <match pattern="skin/one-special.css">
>    <read src="styles/css/one-special.css"/>
>   </match>
> 
>  <mount uri-prefix="skin" src="blocks://skin"/>
> 
>  <mount uri-prefix="" src="blocks://portal"/>
> </pipline>
> ...
> 
>                                  --- o0o ---
> 
> So what do you think about this?

Did you really mean the above or you meant

  <mount uri-prefix="skin" src="block:skin://"/>
  <mount uri-prefix="" src="block:portal://"/>

?

in that case, and the above is your sitemap mount at /, how do you avoid 
the conflict emerging by the fact that somebody else has mount another 
implementation of the skin block on /skin ?

Daniel, I perfectly understand why you want those features, but I have a 
bigger goal: allow blocks to be really polymorphic, not just an easier 
deploy tool.

With that in mind, the complexity increases, if you are composing your 
block out of several others (if you have just one block or you just use 
ones that provide java components, that is not the case).

"explicit" mounting of blocks yields mount collision nightmares: blocks 
should be mount implicitly and thru the block manager (sort of a 
mount-table on steroids). explicit mounting works fine only if you are 
in control of all the dependencies, but this cannot be assumed, since 
blocks should be downloadable from the outside as well and might bring 
new dependencies.

This said, I can't stop the above from happening: even if we have 
implicit mounting, you can go ahead and 'remount' it explicitly as you 
did above.

The fact is that it's not needed if you do the following:

<pipeline>
   <match pattern="load-user-profile">
     ...
   </match>

   <match pattern="skin/one-special.css">
     <read src="styles/css/one-special.css"/>
    </match>

   <mount-blocks/>

</pipline>

and the above is the sitemap of MyPortal that extends "Portal" and it's 
mount on / and requires "Skin" that is mount on '/skin'.

Note however, how if you mount 'Skin' on '/style', the above breaks! The 
way I designed it to avoid this problem is:

MyPortal
  - extends Portal
  - requires Skin
  - mount on "/"
-----------------

  <pipeline>
   <match pattern="load-user-profile">
     ...
   </match>

  </pipeline>

MySkin
  - extends Skin
  - mount on "/styles/"
----------------------

  <pipeline>

   <match pattern="one-special.css">
    <read src="styles/css/one-special.css"/>
   </match>

  </pipeline>

Since <mount> exists and block: will be a Source protocol, it's 
impossible to stop you from doing explicit block mounting into your own 
block URL space. Note that this scatters the URL control in many files, 
instead of centralizing it at the block management level.

I personally won't use it for the above reasons, but if it floats your 
boat, go ahead.

My point remains: we don't need multiple inheritance of blocks to 
achieve what you need!

-- 
Stefano.


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Reinhard Poetz wrote:
<snip/>

> As promised, I've tried to come up with some pseudo-code that shows 
> how "single-inheritance + composition" looks like in a particular 
> example (portal + skinning).

That is excelent.

>                                           - o -
>
> We have following block interfaces:
> ===================================
>  - http://cocoon.apache.org/interfaces/portal/1.0
>  - http://cocoon.apache.org/interfaces/portal-skin/1.0
>  - http://mycompany.com/interfaces/skin/1.0
>
>
> Here the block implementations:
> ===============================
>
> --------------------------------------------------------------------------- 
>
> "Portal"
> --------------------------------------------------------------------------- 
>
> BLOCK.XML
> <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>  id="http://cocoon.apache.org/blocks/portal/1.0.0">
>   <name>portal</name>
>   <requirements>
>     <requires 
> interface="http://cocoon.apache.org/interface/portal-skin/1.0"
>      name="portal"
>      default="http://cocoon.apache.org/blocks/portal-skin/1.0.0"/>
>   </requirements>
>   <implements>
>     <interface id="http://cocoon.apache.org/interfaces/portal/1.0"/>
>   </implements>
> </block>
>
> --------------------------------------------------------------------------- 
>
> "Portal-Skin"
> --------------------------------------------------------------------------- 
>
> BLOCK.XML   
> <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>  id="http://cocoon.apache.org/blocks/portal-skin/1.0.0">
>   <name>portal-skin</name>
>   <implements>
>     <interface id="http://cocoon.apache.org/interfaces/portal-skin/1.0"/>
>   </implements>
> </block>
>
> SITEMAP.XMAP
> <map:match pattern="*.css">
>   <map:read src="styles/css/{1}.css"/>
> </map:match>
> <map:match pattern="styles/portal-page.xsl">
>   <map:read src="styles/portal-page.xsl"/>
> </map:match>
>
>
> --------------------------------------------------------------------------- 
>
> "MyPortal"
> --------------------------------------------------------------------------- 
>

Is MyPortal an actual application or is it a block that you are going to 
use for building applications? Let's call them application block and 
reusable block respectively. We must take application blocks into 
account to get the whole picture, so I assume that MyPortal is an 
application block that will contain real user profiles etc. Seeing that 
it neither implements nor extends but rather use the portal block 
enforces that view.

> BLOCK.XML   
> <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>  id="http://mycompany.com/blocks/my-Portal/1.0.0">
>   <name>MyPortal</name>
>   <requirements>
>     <requires interface="http://mycompany.com/interfaces/skin/1.0"
>       name="skin"
>       default="http://mycompany.com/blocks/myskin/1.0.0"/>
>     <requires interface="http://cocoon.apache.org/interfaces/portal/1.0"
>       name="portal"
>       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
>   </requirements>
> </block>
>
> SITEMAP.XMAP
> <map:match pattern="portal">
>   <map:act type="portal:auth-protect">
>     <map:parameter name="handler" value="portal-handler"/>
>     <map:parameter name="application" value="portal"/>
>
>     <map:generate type="portal:portal"/>
>     <map:transform src="blocks://skin/styles/portal-page.xsl">
>       <map:parameter name="user" value="{ID}"/>
>     </map:transform>
>     <map:transform type="core:cinclude"/>
>     <map:transform type="portal:portal-coplet"/>
>     <map:transform type="portal:portal-new-eventlink"/>
>     <map:transform type="core:encodeURL"/>
>     <map:serialize type="portal:html-include"/>
>   </map:act>
> </map:match>

Shouldn't this sitemap be part of Portal rather than MyPortal, AFAICS it 
is a "blockified" version of the "portal" rule from the demo portal, so 
there seem no to be no reason to reimplement it in MyBlock.

> (Note: Most of the used components come from the portal block, the 
> rest from Cocon core; the stylesheet is provided by the "skin" block.)
>
> --------------------------------------------------------------------------- 
>
> "MySkin"
> --------------------------------------------------------------------------- 
>
> BLOCK.XML
> <block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
>  id="http://mycompany.com/blocks/my-Portal/1.0.0">
>   <name>MySkin</name>
>   <implements>
>     <interface id="http://cocoon.apache.org/interfaces/portal/1.0"/>
>   </implements>
>   <extends>http://cocoon.apache.org/blocks/portal-skin/1.0.0</extends>
> </block>

What does extends actually buy us here, couldn't we just use "requrires" 
for the relation to portal-skin/1.0.0.

<requires block="http://cocoon.apache.org/blocks/portal-skin/1.0.0" 
name="skin"/>

 and be explicit about what we expose from portal-skin/1.0.0?

> SITEMAP.XMAP
> <map:match pattern="one-special.css">
>   <map:read src="styles/css/one-special.css"/>
> </map:match>

Being explicit means that we end the sitemap with:

<map:mount uri-prefix="" src="blocks://skin"/>

>                                           - o -
>
> The project that wants to use the Portal is in the block "MyPortal". 
> It needs several components from "Portal" (generator, several 
> transformers) and it needs a block that provides the skin, or more 
> precisly, it needs a block that implements 
> http://cocoon.apache.org/interfaces/portal-skin/1.0. This can either 
> be "portal-skin", the default skin, or "MySkin", that provides one 
> additional CSS. Everything else is taken from "portal-skin".
>
>
> From my POV this solution is very clear and comprehensible. The 
> aspects "portal functionality" and "skinning" are separated and the 
> used implementations can simply be replaced by other implementations 
> (shown by using the "mySkin" block).
>
>                                           - o -
>
> What does your solution that ueses multiple inheritance look like? (If 
> this is a bad example to show the advantages of MI feel free to 
> enhance it!)

First I will not use the term MI as it doesn't describe what I want to 
achieve that well and as it also seem to stir all kinds of bad reactions 
that distracts us from the task at hand.

So I agree with most of what you show in your example, it looks neat. 
What I lack from it is how to reuse the sitemap in the Portal block.

I would have a sitemap similar to the one in the demo portal in the 
Portal block. But e.g. the profiles part in the portal-handler 
configuration would rather be:

Portal Sitemap
--------------

...
<profiles>
  <copletbasedata-load uri="blocks:/load-global-profile?profile=copletbasedata"/>
  <copletdata-global-load uri="blocks:/load-global-profile?profile=copletdata"/>
  <copletdata-role-load uri="blocks:/load-role-profile?profile=copletdata"/>
  <copletdata-user-load uri="blocks:/load-user-profile?profile=copletdata"/>
  <copletinstancedata-global-load uri="blocks:/load-global-profile?profile=copletinstancedata"/>
  <copletinstancedata-role-load uri="blocks:/load-role-profile?profile=copletinstancedata"/>
  <copletinstancedata-user-load uri="blocks:/load-user-profile?profile=copletinstancedata"/>
  <copletinstancedata-user-save uri="blocks:/save-user-profile?profile=copletinstancedata"/>
  <layout-global-load uri="blocks:/load-global-profile?profile=layout"/>
  <layout-role-load uri="blocks:/load-role-profile?profile=layout"/>
  <layout-user-load uri="blocks:/load-user-profile?profile=layout"/>
  <layout-user-save uri="blocks:/save-user-profile?profile=layout"/>
</profiles>
...

Meaning that the different configuration pipelines are found through the 
blocks manager that would ask the extending block (recursively) for the 
configuration pipelines first, and if they not are found there, the own 
pipeline would be used.

Then MyPortal could redefine some of the configuration pipelines and 
reuse the rest from Portal:

MyPortal Sitemap
----------------

...
<pipeline>
  <match pattern="load-user-profile">
    ...
  </match>

  <mount uri-prefix="" src="blocks://portal"/>
</pipline>
...

Now this mechanism is more limited than real inheritance. map:mount 
become a two way contract where the mounting sitemap can be asked about 
services through the block manager, but it doesn't export the interface 
of the "extended" block. If we have something like the we probably 
should have some way to differ between mounts that allow the mounted 
block to ask and those who don't.

                                  --- o0o ---

Concerning the skin I find it somewhat burocratic to need to define a 
new block for beeing able to extend it but I'm ok with it for the time 
beeing, we will see when we start to use the things. What I would prefer 
would be to do something like:

MyPortal Sitemap
----------------

...
<pipeline>
  <match pattern="load-user-profile">
    ...
  </match>

  <match pattern="skin/one-special.css">
    <read src="styles/css/one-special.css"/>
   </match>

  <mount uri-prefix="skin" src="blocks://skin"/>

  <mount uri-prefix="" src="blocks://portal"/>
</pipline>
...

                                  --- o0o ---

So what do you think about this?

/Daniel


Re: [RT] composition vs. inheritance in blocks

Posted by Reinhard Poetz <re...@apache.org>.
Daniel Fagerstrom wrote:

> Ok, I'll give you a new example trying to explain the concept. Let's 
> start with the portal block and say that I want to use that for my app, 
> MyPortal, but I want a different skin. The skin consists of the 
> stylesheet "styles/portal-page.xsl" among other things. We assume that 
> the designer of the portal block wanted to make the skin overridable so 
> there is a sitemap rule that exposes the stylesheet in the Portal block.
> 
> <match pattern="styles/portal-page.xsl">
>   <read src="default-portal-page.xsl"/>
> </match>
> 
> Now I let MyPortal extends Portal and reimplements the stylesheet in 
> MyPortal
> 
> <match pattern="styles/portal-page.xsl">
>   <read src="my-portal-page.xsl"/>
> </match>
> 
> and thanks to polymorphism the user of MyPortal will get 
> "my-portal-page.xsl" when asking for "styles/portal-page.xsl" and 
> everything else will be delivered from Portal.
> 
> But is that what we want? Taking a closer look at the sitemap in Portal 
> there are a number of sitemap rules that uses "styles/portal-page.xsl" 
> for creating other resources: "portal", "loggedin" and 
> "resources/login-error.xml". What about them, should they use the the 
> stylesheet from Portal or from MyPortal? In general it depends, but in 
> this case our aim was to change to our on skin for the portal so we 
> should use it everywhere.
> 
> This is also covered by the polymorphism concept from OO. A service that 
> is defined and used in the base block but overridden in the extending 
> block should use the overriding service in the base block as well. But 
> IMO it could be confusing if the default behaviour would be to have 
> polymorphic lookup as default in blocks and because of that I proposed a 
> block:polymorph subprotocol for being explicit about what service 
> accesses in a (base) block that are supposed to be overridable. So in 
> the Portal block we could have a sitemap rule:
> 
> <match pattern="portal">
>   ...
>   <transform src="block:polymorph:/styles/portal-page.xsl"/>
>   ...
> </match>
> 
> if we access "portal" from the MyPortal block and have overrided 
> "styles/portal-page.xsl" in MyPortal, the version from MyPortal will be 
> used instead.


As promised, I've tried to come up with some pseudo-code that shows how 
"single-inheritance + composition" looks like in a particular example (portal + 
skinning).


                                           - o -

We have following block interfaces:
===================================
  - http://cocoon.apache.org/interfaces/portal/1.0
  - http://cocoon.apache.org/interfaces/portal-skin/1.0
  - http://mycompany.com/interfaces/skin/1.0


Here the block implementations:
===============================

---------------------------------------------------------------------------
"Portal"
---------------------------------------------------------------------------
BLOCK.XML
<block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
  id="http://cocoon.apache.org/blocks/portal/1.0.0">
   <name>portal</name>
   <requirements>
     <requires interface="http://cocoon.apache.org/interface/portal-skin/1.0"
      name="portal"
      default="http://cocoon.apache.org/blocks/portal-skin/1.0.0"/>
   </requirements>
   <implements>
     <interface id="http://cocoon.apache.org/interfaces/portal/1.0"/>
   </implements>
</block>

---------------------------------------------------------------------------
"Portal-Skin"
---------------------------------------------------------------------------
BLOCK.XML	
<block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
  id="http://cocoon.apache.org/blocks/portal-skin/1.0.0">
   <name>portal-skin</name>
   <implements>
     <interface id="http://cocoon.apache.org/interfaces/portal-skin/1.0"/>
   </implements>
</block>

SITEMAP.XMAP
<map:match pattern="*.css">
   <map:read src="styles/css/{1}.css"/>
</map:match>
<map:match pattern="styles/portal-page.xsl">
   <map:read src="styles/portal-page.xsl"/>
</map:match>


---------------------------------------------------------------------------
"MyPortal"
---------------------------------------------------------------------------
BLOCK.XML	
<block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
  id="http://mycompany.com/blocks/my-Portal/1.0.0">
   <name>MyPortal</name>
   <requirements>
     <requires interface="http://mycompany.com/interfaces/skin/1.0"
       name="skin"
       default="http://mycompany.com/blocks/myskin/1.0.0"/>
     <requires interface="http://cocoon.apache.org/interfaces/portal/1.0"
       name="portal"
       default="http://cocoon.apache.org/blocks/portal/1.0.0"/>
   </requirements>
</block>

SITEMAP.XMAP
<map:match pattern="portal">
   <map:act type="portal:auth-protect">
     <map:parameter name="handler" value="portal-handler"/>
     <map:parameter name="application" value="portal"/>

     <map:generate type="portal:portal"/>
     <map:transform src="blocks://skin/styles/portal-page.xsl">
       <map:parameter name="user" value="{ID}"/>
     </map:transform>
     <map:transform type="core:cinclude"/>
     <map:transform type="portal:portal-coplet"/>
     <map:transform type="portal:portal-new-eventlink"/>
     <map:transform type="core:encodeURL"/>
     <map:serialize type="portal:html-include"/>
   </map:act>
</map:match>

(Note: Most of the used components come from the portal block, the rest from 
Cocon core; the stylesheet is provided by the "skin" block.)

---------------------------------------------------------------------------
"MySkin"
---------------------------------------------------------------------------
BLOCK.XML
<block xmlns="http://apache.org/cocoon/blocks/cob/1.0"
  id="http://mycompany.com/blocks/my-Portal/1.0.0">
   <name>MySkin</name>
   <implements>
     <interface id="http://cocoon.apache.org/interfaces/portal/1.0"/>
   </implements>
   <extends>http://cocoon.apache.org/blocks/portal-skin/1.0.0</extends>
</block>

SITEMAP.XMAP
<map:match pattern="one-special.css">
   <map:read src="styles/css/one-special.css"/>
</map:match>

                                           - o -

The project that wants to use the Portal is in the block "MyPortal". It needs 
several components from "Portal" (generator, several transformers) and it needs 
a block that provides the skin, or more precisly, it needs a block that 
implements http://cocoon.apache.org/interfaces/portal-skin/1.0. This can either 
be "portal-skin", the default skin, or "MySkin", that provides one additional 
CSS. Everything else is taken from "portal-skin".


 From my POV this solution is very clear and comprehensible. The aspects "portal 
functionality" and "skinning" are separated and the used implementations can 
simply be replaced by other implementations (shown by using the "mySkin" block).

                                           - o -

What does your solution that ueses multiple inheritance look like? (If this is a 
bad example to show the advantages of MI feel free to enhance it!)



-- 
Reinhard Pötz           Independent Consultant, Trainer & (IT)-Coach 

{Software Engineering, Open Source, Web Applications, Apache Cocoon}

                                        web(log): http://www.poetz.cc
--------------------------------------------------------------------


Re: [RT] composition vs. inheritance in blocks

Posted by Ralph Goers <Ra...@dslextreme.com>.
Daniel Fagerstrom wrote:

> Ralph Goers wrote:
>
>> Daniel Fagerstrom wrote:
>>
>>> Ok, I'll give you a new example trying to explain the concept. Let's 
>>> start with the portal block and say that I want to use that for my 
>>> app, MyPortal, but I want a different skin. The skin consists of the 
>>> stylesheet "styles/portal-page.xsl" among other things. We assume 
>>> that the designer of the portal block wanted to make the skin 
>>> overridable so there is a sitemap rule that exposes the stylesheet 
>>> in the Portal block.
>>>
>>> <match pattern="styles/portal-page.xsl">
>>>   <read src="default-portal-page.xsl"/>
>>> </match>
>>>
>>> Now I let MyPortal extends Portal and reimplements the stylesheet in 
>>> MyPortal
>>>
>>> <match pattern="styles/portal-page.xsl">
>>>   <read src="my-portal-page.xsl"/>
>>> </match>
>>>
>>> and thanks to polymorphism the user of MyPortal will get 
>>> "my-portal-page.xsl" when asking for "styles/portal-page.xsl" and 
>>> everything else will be delivered from Portal.
>>
>>
>>
>> Normally, I try to avoid these "theoretical" posts, but since you are 
>> picking on the portal...  Frankly, if the way you are proposing this 
>> was actually how the portal worked we would not be using it.  
>> Luckily, to do what you are suggesting is as simply as doing 
>> something like:
>>
>> <map:match pattern="styles/portal-page.xsl">
>>  <map:read 
>> src="{globalConfig:/global-variables/skin}styles/portal-page.xsl"/>
>> </map:match>
>>
>> I understand you were trying to make a point, but sometimes I feel 
>> like these diatribes resort to using a sledgehammer where a simple 
>> screwdriver would do the job nicely.
>
>
> I based my example on the portal as Carsten asked about how one could 
> use blocks for skins and for the portal (although my example didn't 
> answer his questions). I also chosed it, to make the discussion less 
> theoretical as it in the end is about highly practical things. And I 
> doubt that we will ever get to the "real blocks", if we don't discuss 
> and get feedback on practical usage.
>
> Now I'm aware that the portal samples use the construction you show 
> above, but it doesn't achieve exactly the same thing as the 
> construction I propose. If you want to use a slightly modified skin, I 
> would assume that you start by copying the +30 files from 
> skins/commons and then point "global-variables/skin" to the new 
> location and start to modify whatever you wanted to modify.
>
> With my solution you just copy the file, in this case 
> "portal-page.xsl" that you actually want to modify and write an 
> overriding sitemap rule to use it. After having used thing like the 
> global variable trick for a number of years in various applications, 
> we had a tremendous amonount of different generations of esentially 
> the same files and numerous copies of slightly modified sitemap 
> snippets. Hardly supprising it was a maintainance nightmare. After 
> having start to use the pattern that I propose we have seen a drastic 
> decrease in the number of files in our new applications.
>
> So is it complicated? Not particular. As we use it in our apps we 
> would write:
>
> <map:match pattern="styles/portal-page.xsl">
> <map:read src="cocoon://{request:sitemapPath}/styles/portal-page.xsl"/>
> </map:match>
>
Actually, we use
<map:read src="prefs://presentation/styles/.portal-page.xsl"/>

The input source takes care of finding the "correct" version of the file 
based upon who the client is and whether they actually have a file. If 
they don't, the default version of the file is used.  The point is, the 
problem is being attacked where it exists, not by making many 
incarnations of a block. That will get to be unwieldy and cumbersome.

Ralph


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Ralph Goers wrote:

> Daniel Fagerstrom wrote:
>
>> Ok, I'll give you a new example trying to explain the concept. Let's 
>> start with the portal block and say that I want to use that for my 
>> app, MyPortal, but I want a different skin. The skin consists of the 
>> stylesheet "styles/portal-page.xsl" among other things. We assume 
>> that the designer of the portal block wanted to make the skin 
>> overridable so there is a sitemap rule that exposes the stylesheet in 
>> the Portal block.
>>
>> <match pattern="styles/portal-page.xsl">
>>   <read src="default-portal-page.xsl"/>
>> </match>
>>
>> Now I let MyPortal extends Portal and reimplements the stylesheet in 
>> MyPortal
>>
>> <match pattern="styles/portal-page.xsl">
>>   <read src="my-portal-page.xsl"/>
>> </match>
>>
>> and thanks to polymorphism the user of MyPortal will get 
>> "my-portal-page.xsl" when asking for "styles/portal-page.xsl" and 
>> everything else will be delivered from Portal.
>
>
> Normally, I try to avoid these "theoretical" posts, but since you are 
> picking on the portal...  Frankly, if the way you are proposing this 
> was actually how the portal worked we would not be using it.  Luckily, 
> to do what you are suggesting is as simply as doing something like:
>
> <map:match pattern="styles/portal-page.xsl">
>  <map:read 
> src="{globalConfig:/global-variables/skin}styles/portal-page.xsl"/>
> </map:match>
>
> I understand you were trying to make a point, but sometimes I feel 
> like these diatribes resort to using a sledgehammer where a simple 
> screwdriver would do the job nicely.

I based my example on the portal as Carsten asked about how one could 
use blocks for skins and for the portal (although my example didn't 
answer his questions). I also chosed it, to make the discussion less 
theoretical as it in the end is about highly practical things. And I 
doubt that we will ever get to the "real blocks", if we don't discuss 
and get feedback on practical usage.

Now I'm aware that the portal samples use the construction you show 
above, but it doesn't achieve exactly the same thing as the construction 
I propose. If you want to use a slightly modified skin, I would assume 
that you start by copying the +30 files from skins/commons and then 
point "global-variables/skin" to the new location and start to modify 
whatever you wanted to modify.

With my solution you just copy the file, in this case "portal-page.xsl" 
that you actually want to modify and write an overriding sitemap rule to 
use it. After having used thing like the global variable trick for a 
number of years in various applications, we had a tremendous amonount of 
different generations of esentially the same files and numerous copies 
of slightly modified sitemap snippets. Hardly supprising it was a 
maintainance nightmare. After having start to use the pattern that I 
propose we have seen a drastic decrease in the number of files in our 
new applications.

So is it complicated? Not particular. As we use it in our apps we would 
write:

<map:match pattern="styles/portal-page.xsl">
 <map:read src="cocoon://{request:sitemapPath}/styles/portal-page.xsl"/>
</map:match>

in the reusable portal sitemap. The "cocoon://{request:sitemapPath}/" 
prefix "absolutizes" the URI so that it will be searched from the root 
sitemap and a sitemap that mounts the portal sitemap can modify the 
behaviour by writing an alternative rule for an uri. request:sitemapPath 
is new in 2.2, so in 2.1 one need to write a module that makes 
Environment.getURIPefix() available.

When you want to resue and modify the behaviour of the reusable portal 
sitemap you write a new sitemap:

...
<pipeline>
  <match pattern="styles/portal-page.xsl">
    <read src="my-portal-page.xsl"/>
  </match>

  <mount uri-prefix="" src="context://block/portal"/>
</pipeline>

If this mechanism was used in the portal, there could be a small base 
portal with overridable example configurations and example data, in the 
portal jar. And a new portal user could start trying it as simple as:

<pipeline>
  <mount uri-prefix="" src="resource://org/apache/cocoon/portal/site"/>
</pipeline>

and the incrementally add own behaviour while always having a working 
portal. Today I would assume that a typical new user start by copying 
the demo and goes from there. It works, but it mean that they after a 
while they have several copies of base functionality in different portal 
based webapps, that they need to maintain and maybe synchronize with 
improvements in new Cocoon versions.

                                     --- o0o ---

My aim is to make this mechanism or something equally powerful part of 
the blocks.

/Daniel


Re: [RT] composition vs. inheritance in blocks

Posted by Ralph Goers <Ra...@dslextreme.com>.
Daniel Fagerstrom wrote:

> Ok, I'll give you a new example trying to explain the concept. Let's 
> start with the portal block and say that I want to use that for my 
> app, MyPortal, but I want a different skin. The skin consists of the 
> stylesheet "styles/portal-page.xsl" among other things. We assume that 
> the designer of the portal block wanted to make the skin overridable 
> so there is a sitemap rule that exposes the stylesheet in the Portal 
> block.
>
> <match pattern="styles/portal-page.xsl">
>   <read src="default-portal-page.xsl"/>
> </match>
>
> Now I let MyPortal extends Portal and reimplements the stylesheet in 
> MyPortal
>
> <match pattern="styles/portal-page.xsl">
>   <read src="my-portal-page.xsl"/>
> </match>
>
> and thanks to polymorphism the user of MyPortal will get 
> "my-portal-page.xsl" when asking for "styles/portal-page.xsl" and 
> everything else will be delivered from Portal.

Normally, I try to avoid these "theoretical" posts, but since you are 
picking on the portal...  Frankly, if the way you are proposing this was 
actually how the portal worked we would not be using it.  Luckily, to do 
what you are suggesting is as simply as doing something like:

<map:match pattern="styles/portal-page.xsl">
  <map:read 
src="{globalConfig:/global-variables/skin}styles/portal-page.xsl"/>
</map:match>

I understand you were trying to make a point, but sometimes I feel like 
these diatribes resort to using a sledgehammer where a simple 
screwdriver would do the job nicely.

Ralph


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Stefano Mazzocchi wrote:
> 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?

No, you still don't get it. Super can certainly be useful in some cases 
but that's not what I'm talking about. Lets just forget about the 
multiplicity of the inheritance or even the term inheritance until we at 
least are discussing the same subject.

Ok, I'll give you a new example trying to explain the concept. Let's 
start with the portal block and say that I want to use that for my app, 
MyPortal, but I want a different skin. The skin consists of the 
stylesheet "styles/portal-page.xsl" among other things. We assume that 
the designer of the portal block wanted to make the skin overridable so 
there is a sitemap rule that exposes the stylesheet in the Portal block.

<match pattern="styles/portal-page.xsl">
   <read src="default-portal-page.xsl"/>
</match>

Now I let MyPortal extends Portal and reimplements the stylesheet in 
MyPortal

<match pattern="styles/portal-page.xsl">
   <read src="my-portal-page.xsl"/>
</match>

and thanks to polymorphism the user of MyPortal will get 
"my-portal-page.xsl" when asking for "styles/portal-page.xsl" and 
everything else will be delivered from Portal.

But is that what we want? Taking a closer look at the sitemap in Portal 
there are a number of sitemap rules that uses "styles/portal-page.xsl" 
for creating other resources: "portal", "loggedin" and 
"resources/login-error.xml". What about them, should they use the the 
stylesheet from Portal or from MyPortal? In general it depends, but in 
this case our aim was to change to our on skin for the portal so we 
should use it everywhere.

This is also covered by the polymorphism concept from OO. A service that 
is defined and used in the base block but overridden in the extending 
block should use the overriding service in the base block as well. But 
IMO it could be confusing if the default behaviour would be to have 
polymorphic lookup as default in blocks and because of that I proposed a 
block:polymorph subprotocol for being explicit about what service 
accesses in a (base) block that are supposed to be overridable. So in 
the Portal block we could have a sitemap rule:

<match pattern="portal">
   ...
   <transform src="block:polymorph:/styles/portal-page.xsl"/>
   ...
</match>

if we access "portal" from the MyPortal block and have overrided 
"styles/portal-page.xsl" in MyPortal, the version from MyPortal will be 
used instead.

                       --- o0o ---

So we have two aspects of polymorphism, the first is that services from 
an extending block overides services in an extended block. But also that 
  services that are used as *part* of other services in the extended 
block will be overrided by corresponding services in the extending block.

So, my main message is that I want this second aspect of polymorphism in 
blocks as well. IMO (and experience) it makes blocks much more useful. A 
block can contain overridable default values and example data so that it 
can be used at once, then the user can override one thing at a time 
during development. I gave an example of how one can work by using this 
aspect of polymorphism in my last mail.

                       --- o0o ---

So what I'm proposing is that we should have this kind of polymorphism 
in block. Or if anyone have a better mechanism that solves the same problem.

> [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!]
Don't worry, I don't like deep inheritance hierarchies.


>                                   - o -
> 
> As for MI, like I said before (and you carefully snipped),
Funny that you comment my snipping, in a mail where you snipped away 
everything but two lines from my mail.

> 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).

I read it before and didn't comment because 1) I don't agree 2) IMO we 
waste time by discussing sweeping analogues. If we want to get any 
closer to real blocks we need to discuss concrete cases.

> 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

No I don't. If you read my answer to Peter you could see that I even 
start to doubt that it is meaningful to state that a block extends 
another at some global level. I'm interested in being able to use, and 
in some cases use and override services from several other blocks.

> 
> 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.

It's OK for me as long as A and B2 (or C2) can have the kind of 
polymorph connection that I described innthe beginning.

Also I would appriciate if you could replace the letters and the numbers 
above with something more concrete, and if you could flesh out some 
details about how they actually are going to communicate. Before that it 
is rather hard to compare our different approaches or even know if it is 
different rather than complementing approaches. And above all it is hard 
to get to the point where we can start to actually implement it.

/Daniel


Re: [RT] composition vs. inheritance in blocks

Posted by Stefano Mazzocchi <st...@apache.org>.
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.


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Stefano Mazzocchi wrote:

> Daniel Fagerstrom wrote:
>
>> Stefano Mazzocchi wrote:
>>
>>> Daniel Fagerstrom wrote:
>>
>> <snip/>
>>
>>> I don't like multiple inheritance and this is not just because I 
>>> learned OOP thru java, but because every single time I wish I had 
>>> multiple implementation inheritance in java I found a way to go 
>>> around the problem with single implementation inheritance that was 
>>> more elegant.
>>
>> I learned OOP thru C++, so I even have had the possibility of using 
>> multiple implementation inheritance, not just the work arounds ;) And 
>> in most cases composition is better than multiple implementation 
>> inheritance, but in the cases where you merge two different concern 
>> areas it is useful and natural according to my experience. While I 
>> don't find the "extend the largest abstract base class and repeat the 
>> interface and delgate to the other" ideom used in Java particulary 
>> elegant.
>>
>> But, although I believe that we should use well known concepts from 
>> OO as much as possible in the design of blocks, as we know some of 
>> the consequnces of them and as they are familiar to the users, we 
>> must be aware about that blocks and typical objects have quite 
>> different levels of granularity and are not completely analogous.
>>
>>                                    --- o0o ---
>>
>> So what I propose is that "extend and override" is a convenient and 
>> productive way to build webapps. You start from a working default 
>> application and add your own data and modify the behaviours that you 
>> need to modify. If you have used Forrest, you know what I'm talking 
>> about. But the difference between Forrest and what I propose is that 
>> you don't need any complicated sitemap tricks and global 
>> configurations with search paths, if we makes the block polymorphic.
>>
>>                                    --- o0o ---
>>
>> This is not just armchair speculations from me. We have built a 
>> number of webapps during the last year based on sitemap polymorphism. 
>> The mechanism is rather simple, in the sitemap of the base 
>> application we use a variant of the cocoon protocol:
>>
>> cocoon:polymorph:/foo.xml
>>
>> that basically calls
>>
>> cocoon://<sitemap-path>/foo.xml
>>
>> by mounting the base application in the end of the "extending" 
>> sitemap, the polymorph sitemap rules can be overrided just by 
>> defining the uri in the before the mount.
>>
>> Its easy and works well. Of course one have to do some thinking to 
>> build a reusable base application, but that goes generally for 
>> reusability.
>>
>> We started to use this pattern because we had a webapp, that a number 
>> of customers wanted slight variations of. In the beging we just made 
>> the new webapps extend a slight abstraction of the original webapp. 
>> Not because I thought it was a good idea, but more because of time 
>> constraints. Our experience is, hardly supprising, that it is more 
>> flexible to base your webapp on a number of orthogonal vertical 
>> frameworks. So we have factored out some such from the original webapp.
>>
>>                                    --- o0o ---
>>
>> So our experience is:
>> * extend and override is productive
>> * vertical frameworks are easier to reuse
>
>
> If you are talking about
>
>  block A extends block B
>
> then the functionality that you describe above is already included in 
> the original real block design and you don't even need the (ugly!) 
> polymorphic protocol flavor, since the block protocol should takes 
> care of all this transparently (thru the block dependency map of the 
> block manager).

Citing from 
http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=111209768003970&w=2

>In your example block A extends block B, then in block B we can have a 
>sitemap rule like:
>
><map:match pattern="**.html">
>  <map:generate src="{1}.xml"/>
>  <map:transform src="block:polymorph:/stylesheets/document2html.xslt"/>
>  <map:serialize/>
></map:match>
>
>The block:polymorphism makes that stylesheets/document2html.xslt is 
>taken from A rather than B. Say that you use that stylesheet in several 
>rules, then you change multiple behaviours by overriding it.
>  
>
I described why I think its safer to be explicit about when an 
(extended) block should find a service by polymorphic rather than local 
lookup in 
http://marc.theaimsgroup.com/?l=xml-cocoon-dev&m=111183895029727&w=2:

>Ok, allready discussed that above. I think we need to be more explicit 
>about what behaviour we want. If we just write:
>
><map:transform src="stylesheets/document2html.xslt"/>
>
>that means normally the same as:
>
><map:transform src="context:/stylesheets/document2html.xslt"/>
>
>and I don't think it is a good idea for isolation between block to be 
>able to overide what is in the current context, only things that are 
>exposed through the sitemap should IMO be overidable:
>
><map:transform src="block:polymorph:/stylesheets/document2html.xslt"/>.
>  
>
So I talk about polymorphic access *whithin* a possibly extended block. 
I'm fully aware that you described how A can override B by exposing an 
uri that is exposed in B, and I agree with the proposed mechanism. 
Question is how to handle the use of a service within the extended block 
(B) if this service is overriden i the extending block (A).

> But (as usual), you jumped directly from that to
>
>  block A extends block b *and* c

I wrote:

> Our experience is, hardly supprising, that it is more flexible to base 
> your webapp on a number of orthogonal vertical frameworks. So we have 
> factored out some such from the original webapp. 

on the line before my conclusion, and also described why I wanted it 
earlier in the thread, but (as usual) you jumped in and started 
screaming without bothering to read the whole thread.

> which, to me, is not the painless jump that you (and Peter) seem to 
> suggest.

As already said, I have practical experience of using multiple 
inheritance in C++ and poymorphic extensions of sitemaps in Cocoon. And, 
like any other powerful construct, you have to learn how to use it and 
it can be missused, but in my experience, it simplifies life if you use 
it in the right way.

A coleauge of mine was involved in building some rather large systems in 
Common Lisp long time ago, and used multiple (implementation) 
inheritance as one of the major ways to compose the systems. Hi find the 
single inheriatnce idea in Java ridiculous, and claims that he was about 
a magnitude more productive when he programmed in Common Lisp rather 
than in Java. Now comparing langauges is rather unproductive, I just 
wanted to point out that multiple inheritance not is bad per se, it all 
depends on what you use it for and how it is implemented in the 
particular language.

>> This implies AFAICS multiple inheritance
>
> not at all. you can have block 'cascading'/'wrapping' (you name it) 
> without multiple inheritance.

Sure, but if you want to base your webapp on several blocks that takes 
care of different concerns you have to chose which of them you want to 
be able to extend if you have single inheritance.

                                              --- o0o ---

But let's take a look at an example instead. We have built a number of 
webapps for administring sells campaigns for a number of companies 
within the same concern that are based on the polymorphic sitemap 
inheritance scheme that I described above. The webapps have 
functionality for administring the campaigns (of course), functionality 
for selecting and optimizing what customers to communicate with, 
documentation of how it works and about data models, visualization of 
the results of the campaigns, it communicates with some other systems, 
database administration functionality that we use internally etc.

Ok, when building a new system like this I start with a sitemap like:

...
<pipeline>
  <match pattern="sysadm/**">
    <mount uri-prefix="sysadm" src="context://block/sysadm"/>
  </match>
  <match pattern="campaign/**">
    <mount uri-prefix="campaign" src="context://block/campaign"/>
  </match>
  <match pattern="doc/**">
    <mount uri-prefix="doc" src="context://block/doc"/>
  </match>

  <!- other "blocks" -->

  <match pattern="**">
    <mount uri-prefix="" src="context://block/skin"/>
  </match>
</pipeline>
...

By typing "index.html" in my browser I get the default start page from 
"/block/skin", its a little bit like the default start page from 
Forrest: menu, menubar, bread crumb, short description about how to 
continue the development in the main page, etc.

First step is puting the other functionality in the menu, so I write an 
own "site.xml" that overides the polymorphically used in skin:

<pipeline>
  <match pattern="site.xml">
    ...
  </match>
  <!-- as before -->


whithin skin "site.xml" is used through "block:polymorph:/site.xml" and 
the overriding version will be used instead. Now my application have 
menu links to the default implementation of the other blocks (that may 
contain own manu definitions). I continue by overiding the uris to some 
of the icons, the start page, some css rules and maybe a "setting.xml" 
that describe some of the texts etc in the skin. Now I have customized 
how the application looks, start page an the top menu structure.

Next, probably after having created sub sitemaps for campaign, doc etc, 
I start to customize the parts of my webapp, by overriding some default 
behaviour in campaign, doc etc. I override the default (example) db meta 
description for my particular campaign database, change some of the adm 
forms etc. I use the same db meta description to my doc "block" as well 
for geting various data views: table overview and a connection diagram. 
For more general use we should of course factor out the db documentation 
to a separate dbdoc block, but all our webapps are db based so we 
haven't found it worthwhile yet.

                                              --- o0o ---

The important thing here is that my "blocks" are useable as is with 
example or default data, so that you just can mount them and test them. 
Then the things that are designed to be overidden is used through the 
"block:polymorph" protocol and can be overiding by puting a rule before 
the mount in the mounting sitemap.

To make this way of building webapps as simple and convenient as 
possible it is of course important to have common formats and design 
conventions between the block. And to focus the blocks so that they do 
one thing good instead of doing a little bit of everything. Also most of 
the blocks: systemadm, campaign and doc above should be "content" blocks 
and let the skin take care of view aspects.

If the blocks doesn't use the same formats things get more complicated, 
but it is still possible to handle. Say that "campaign" and "doc" uses 
different db description formats. Then you could write something like:

<match pattern="campaign/db.xml"/>
  <read src="db.xml"/>
</match>

<match pattern="doc/db.meta"/>
  <generate src="db.xml"/>
  <transform src="myDMMeta2TheirDBMeta.xsl"/>
  <serialize/>
</match>

<!-- mount the campaign and doc blocks -->

                                              --- o0o ---

So what I want to have in blocks, is this possiblity to extend and 
override functionality in several blocks. But I don't see any need for 
leting my "application level" blocks export all the services from the 
blocks it extend the functionality from. For sitemap services I prefer 
to explicitly export things with "mount" and for components we could 
have some similar mechanism as I described in my comment to Peter's mail.

>> as you have to implement polymorphism by hand if you use composition. 
>
>
> No. Absolutely not. Go back and read all my emails about the block 
> protocol: the functionality you describe is already there and doesn't 
> require MI at all.

I have read the ones that have links from 
http://wiki.apache.org/cocoon/Blocks and serched the archives for block 
discussions numerous times, and haven't found anything that adresses the 
usage scenario that I described above. If there are other relevant mails 
that adresses this, please do us all a service and add the links to the 
Wiki.

<snip/>

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

/Daniel


Re: [RT] composition vs. inheritance in blocks

Posted by Stefano Mazzocchi <st...@apache.org>.
Daniel Fagerstrom wrote:
> Stefano Mazzocchi wrote:
> 
>> Daniel Fagerstrom wrote:
> 
> 
> <snip/>
> 
>> I don't like multiple inheritance and this is not just because I 
>> learned OOP thru java, but because every single time I wish I had 
>> multiple implementation inheritance in java I found a way to go around 
>> the problem with single implementation inheritance that was more elegant.
> 
> 
> I learned OOP thru C++, so I even have had the possibility of using 
> multiple implementation inheritance, not just the work arounds ;) And in 
> most cases composition is better than multiple implementation 
> inheritance, but in the cases where you merge two different concern 
> areas it is useful and natural according to my experience. While I don't 
> find the "extend the largest abstract base class and repeat the 
> interface and delgate to the other" ideom used in Java particulary elegant.
> 
> But, although I believe that we should use well known concepts from OO 
> as much as possible in the design of blocks, as we know some of the 
> consequnces of them and as they are familiar to the users, we must be 
> aware about that blocks and typical objects have quite different levels 
> of granularity and are not completely analogous.
> 
>                                    --- o0o ---
> 
> So what I propose is that "extend and override" is a convenient and 
> productive way to build webapps. You start from a working default 
> application and add your own data and modify the behaviours that you 
> need to modify. If you have used Forrest, you know what I'm talking 
> about. But the difference between Forrest and what I propose is that you 
> don't need any complicated sitemap tricks and global configurations with 
> search paths, if we makes the block polymorphic.
> 
>                                    --- o0o ---
> 
> This is not just armchair speculations from me. We have built a number 
> of webapps during the last year based on sitemap polymorphism. The 
> mechanism is rather simple, in the sitemap of the base application we 
> use a variant of the cocoon protocol:
> 
> cocoon:polymorph:/foo.xml
> 
> that basically calls
> 
> cocoon://<sitemap-path>/foo.xml
> 
> by mounting the base application in the end of the "extending" sitemap, 
> the polymorph sitemap rules can be overrided just by defining the uri in 
> the before the mount.
> 
> Its easy and works well. Of course one have to do some thinking to build 
> a reusable base application, but that goes generally for reusability.
> 
> We started to use this pattern because we had a webapp, that a number of 
> customers wanted slight variations of. In the beging we just made the 
> new webapps extend a slight abstraction of the original webapp. Not 
> because I thought it was a good idea, but more because of time 
> constraints. Our experience is, hardly supprising, that it is more 
> flexible to base your webapp on a number of orthogonal vertical 
> frameworks. So we have factored out some such from the original webapp.
> 
>                                    --- o0o ---
> 
> So our experience is:
> * extend and override is productive
> * vertical frameworks are easier to reuse

If you are talking about

  block A extends block B

then the functionality that you describe above is already included in 
the original real block design and you don't even need the (ugly!) 
polymorphic protocol flavor, since the block protocol should takes care 
of all this transparently (thru the block dependency map of the block 
manager).

But (as usual), you jumped directly from that to

  block A extends block b *and* c

which, to me, is not the painless jump that you (and Peter) seem to suggest.

> This implies AFAICS multiple inheritance

not at all. you can have block 'cascading'/'wrapping' (you name it) 
without multiple inheritance.

> as you have to implement 
> polymorphism by hand if you use composition. 

No. Absolutely not. Go back and read all my emails about the block 
protocol: the functionality you describe is already there and doesn't 
require MI at all.

> If you have better ideas 
> about how to achive default behaviour that is easy to override, I'm of 
> course interested to discus them instead.

see above.

> We have only used polymorphism on sitemap level, if it is usefull for 
> components is another question, I would assume that, but it needs 
> further thinking.

exactly.

>> I would go a little further and say that I believe inheritance is 
>> useful only when used as a 'cascading' mechanism, in any other sense 
>> is harmful: composition should be used instead.
>>
>> Why so?
>>
>> It's extremely hard to design for inheritance, a lot easier to design 
>> for composition.
> 
> These are different concerns. Of course we should support composition, 
> no doubt about that, but based on the reasons and experiences described 
> above I want inheritance as well. 

I completely agree that inheritance is useful. Dead useful. But single 
inheritance not multiple one.

> And it is no doubt easier to design 
> components than vertical frameworks, but that doesn't mean that we 
> should avoid designing framewoks.

hell no. I had enough 'build the framework before we even know where the 
problem is' avalonish crap in my life, thanks.

Until somebody proves me that this is no way to obtain a required 
functionality without MI, I'm -1 on it.

>> And performing composition thru multiple-inheritance is a really 
>> terrible way to do it. Why? because you need to go very deep in 
>> describing what behaviors get exposed and what are protected, 
>> otherwise things get messy very fast.
> 
> Sure, it is well known deep hierarchies of implementation inheritance 
> often leads to problems. People tried to use it as "the golden hammer" 
> once, but that doesn't make it less usefull for what it is good for.

Sure, for cascading. Agreed. therefore 'single' inheritance.

>> Also, multiple-inheritance stops further composition: you seem to 
>> suggest that a block that inherit multiply is a 'leaf block', one that 
>> is your own application and that will not be used by others.
> 
> Yes, that is correct, I want it to be as simple as possible to put 
> together a webapp based on ready made vertical frameworks.

and can you tell me why MI is supposed to help you achieving this?

>> Well, one of the reasons for block design was to sparkle the creation 
>> of reusable application components without people to think much about 
>> them: multiple-inheritance yields horizontal behavior changes to the 
>> inherited components, which means that if I have block A inherit block 
>> B and then block C that wants to use A but was already using B, but A 
>> modified B's behavior a little with the inheritance, you have a problem!
> 
> Sure, you have to keep your blocks orthogonal to make them reusable, 
> overlapping behaviour leads to a mess.

Bingo.

> But honestly, reusabillity has been considered a major topic in the 
> software business for a number of decades. We all know that it doesn't 
> happen spontaniously, you have to design for it and you have to reuse 
> your component or framework a number of times and make lot of 
> improvements before it becomes more generally reusable.

Very very true, and my argument is that MI moves the pain one step down, 
so that you never go thru exactly *that* design for reuse phase that 
composition forces you to go thru.

>> I am strongly against multiple implementation inheritance for blocks, 
>> because what you want to do, if you care about reusability, is really 
>> multiple composition and that is achieved with being allowed to 
>> implement multiple behavioral interfaces.
> 
> Of course I want to support that as well.

Very well, then we have composition (multiple implementation of 
interfaces) and single inherit
> 
>> If you *don't* care for reusability, then it's true that multiple 
>> implementation inheritnace can serve as a cheaper form of composition.
> 
> 
> For the majority of Cocoon users I would assume that blocks that are 
> possible to extend and override is easier to reuse (considered that they 
> have a good design of course), than just a lump of components and 
> stylesheets.
> 
>> But if I had to pick between improving block reusability or ease of 
>> composition, I would go with the first, hoping that tools/syntax-sugar 
>> would help the second (as it happened with Java).
> 
> 
> It's not either or. It's not exactly rocket science to build a mechanism 
> for mutiple inheritance so we can have booth.
> 
> We just need to discuss what we want to achieve and how to achive it to 
> get it right.
> 
> /Daniel
> 
> 
> 


-- 
Stefano.


Re: [RT] composition vs. inheritance in blocks

Posted by Daniel Fagerstrom <da...@nada.kth.se>.
Stefano Mazzocchi wrote:

> Daniel Fagerstrom wrote:

<snip/>

> I don't like multiple inheritance and this is not just because I 
> learned OOP thru java, but because every single time I wish I had 
> multiple implementation inheritance in java I found a way to go around 
> the problem with single implementation inheritance that was more elegant.

I learned OOP thru C++, so I even have had the possibility of using 
multiple implementation inheritance, not just the work arounds ;) And in 
most cases composition is better than multiple implementation 
inheritance, but in the cases where you merge two different concern 
areas it is useful and natural according to my experience. While I don't 
find the "extend the largest abstract base class and repeat the 
interface and delgate to the other" ideom used in Java particulary elegant.

But, although I believe that we should use well known concepts from OO 
as much as possible in the design of blocks, as we know some of the 
consequnces of them and as they are familiar to the users, we must be 
aware about that blocks and typical objects have quite different levels 
of granularity and are not completely analogous.

                                    --- o0o ---

So what I propose is that "extend and override" is a convenient and 
productive way to build webapps. You start from a working default 
application and add your own data and modify the behaviours that you 
need to modify. If you have used Forrest, you know what I'm talking 
about. But the difference between Forrest and what I propose is that you 
don't need any complicated sitemap tricks and global configurations with 
search paths, if we makes the block polymorphic.

                                    --- o0o ---

This is not just armchair speculations from me. We have built a number 
of webapps during the last year based on sitemap polymorphism. The 
mechanism is rather simple, in the sitemap of the base application we 
use a variant of the cocoon protocol:

cocoon:polymorph:/foo.xml

that basically calls

cocoon://<sitemap-path>/foo.xml

by mounting the base application in the end of the "extending" sitemap, 
the polymorph sitemap rules can be overrided just by defining the uri in 
the before the mount.

Its easy and works well. Of course one have to do some thinking to build 
a reusable base application, but that goes generally for reusability.

We started to use this pattern because we had a webapp, that a number of 
customers wanted slight variations of. In the beging we just made the 
new webapps extend a slight abstraction of the original webapp. Not 
because I thought it was a good idea, but more because of time 
constraints. Our experience is, hardly supprising, that it is more 
flexible to base your webapp on a number of orthogonal vertical 
frameworks. So we have factored out some such from the original webapp.

                                    --- o0o ---

So our experience is:
* extend and override is productive
* vertical frameworks are easier to reuse

This implies AFAICS multiple inheritance, as you have to implement 
polymorphism by hand if you use composition. If you have better ideas 
about how to achive default behaviour that is easy to override, I'm of 
course interested to discus them instead.

We have only used polymorphism on sitemap level, if it is usefull for 
components is another question, I would assume that, but it needs 
further thinking.

> I would go a little further and say that I believe inheritance is 
> useful only when used as a 'cascading' mechanism, in any other sense 
> is harmful: composition should be used instead.
>
> Why so?
>
> It's extremely hard to design for inheritance, a lot easier to design 
> for composition.

These are different concerns. Of course we should support composition, 
no doubt about that, but based on the reasons and experiences described 
above I want inheritance as well. And it is no doubt easier to design 
components than vertical frameworks, but that doesn't mean that we 
should avoid designing framewoks.

> And performing composition thru multiple-inheritance is a really 
> terrible way to do it. Why? because you need to go very deep in 
> describing what behaviors get exposed and what are protected, 
> otherwise things get messy very fast.

Sure, it is well known deep hierarchies of implementation inheritance 
often leads to problems. People tried to use it as "the golden hammer" 
once, but that doesn't make it less usefull for what it is good for.

> Also, multiple-inheritance stops further composition: you seem to 
> suggest that a block that inherit multiply is a 'leaf block', one that 
> is your own application and that will not be used by others.

Yes, that is correct, I want it to be as simple as possible to put 
together a webapp based on ready made vertical frameworks.

> Well, one of the reasons for block design was to sparkle the creation 
> of reusable application components without people to think much about 
> them: multiple-inheritance yields horizontal behavior changes to the 
> inherited components, which means that if I have block A inherit block 
> B and then block C that wants to use A but was already using B, but A 
> modified B's behavior a little with the inheritance, you have a problem!

Sure, you have to keep your blocks orthogonal to make them reusable, 
overlapping behaviour leads to a mess.

But honestly, reusabillity has been considered a major topic in the 
software business for a number of decades. We all know that it doesn't 
happen spontaniously, you have to design for it and you have to reuse 
your component or framework a number of times and make lot of 
improvements before it becomes more generally reusable.

> I am strongly against multiple implementation inheritance for blocks, 
> because what you want to do, if you care about reusability, is really 
> multiple composition and that is achieved with being allowed to 
> implement multiple behavioral interfaces.

Of course I want to support that as well.

> If you *don't* care for reusability, then it's true that multiple 
> implementation inheritnace can serve as a cheaper form of composition.

For the majority of Cocoon users I would assume that blocks that are 
possible to extend and override is easier to reuse (considered that they 
have a good design of course), than just a lump of components and 
stylesheets.

> But if I had to pick between improving block reusability or ease of 
> composition, I would go with the first, hoping that tools/syntax-sugar 
> would help the second (as it happened with Java).

It's not either or. It's not exactly rocket science to build a mechanism 
for mutiple inheritance so we can have booth.

We just need to discuss what we want to achieve and how to achive it to 
get it right.

/Daniel