Hi Rainer. I'm very sorry that I have not been responding for so much time but
there were lots of
issues lately. The last one I got injured while skiing in Austria and I had no
motivation to touch
computers for some time...
Before I start to address your specific points I would like to say that I have
spoken with Reinhard
and he told me that he liked ideas posted in this thread and he told me he was
going to take
proposed approach in his next work on top of 2.2. That gave me more conviction
that I'm on right
track giving you advice.
I hope that Reinhard could speak about his thoughts on the list himself,
though... :)
Rainer Pruy pisze:
> Agreed, that would better reflect it's role in page composition.
> However, a small but nevertheless important role is authentication and
> (global) authorization.
> I have the firm conviction that it is bad design to rely on each subordinate
> block (the "A"s) to correctly implement the
> authentication and authorization contract of the overall application.
> Especially if we allow for such blocks to be contributed by
> "third parties". Not involved with putting up the application in the first
> place (e.g. customers).
I've been thinking about authentication and authorization as well. I agree it's
bad design to rely
on subordinate blocks implementing such important piece of functionality.
However, I think it's also
a bad design to mix content generation/aggregation with authentication and
authorization. My idea is
to create another sitemap (or maybe whole block) just handling authorization.
It would exploit all
the power that comes from sitemap matching so you could create a sophisticated
patterns.
The idea is to make a request (having the same information as the request
coming from browser) to
your special block and let it to return only a status code:
a) 202 Accepted if request should be dispatcher to its target block
b) 401 Unauthorized if user is not authorized
c) 403 Forbidden in case when user does not have necessary karma
In cases b and c original request would never reach its target block. This
functionality could be
easily implemented in a DispatcherServlet of servlet service framework for
example by overriding its
service() method. Probably it would a good idea to refactor code in
DispatcherServlet class so its
easier for extending classes to plug such special handlers.
I think it's quite obvious that this resembles the AOP functionality from
Spring. I think such
design would be very clear and would keep things like content authorization and
content generation
that are orthogonal separate.
> If there is no inversion of control, and passing (POST) requests resulting
> from submitting forms does not work transparently, the
> there must be provisions with M to process forms from any subordinate block.
I don't get your point. Why do you want M to bother of POST request that A
block should handle directly?
> As it adds "single point of authentication/authorization" it is not redundant
> in the first place.
> When just considering contribution to resulting page, you are right.
See above. M should not be involved in authentication/authorization because
it's responsible for
content generation only.
>> If you invert roles, then A block also uses delegation for generating common
>> layout but this time
>> there is only one procedure taking numerous parameters and the second,
>> responsible for generation of
>> common stuff, takes only a few of them or maybe even none. I see such
>> situation as improvement and
>> less complex code.
>
> Yes, it will simplify code for M while adding a bit to each subordinate ("A").
Yep, but it's better to distribute the complexity among many blocks instead of
creating one big
beast that in the end must be tied to all of blocks because it must handle all
edge cases.
Having one central point makes sense if the complexity can be reduced but here
we are talking about
only about complexity management and not reduction.
>>> Responsibility of interactional behaviour for a certain region of the final
>>> page is delegated to block A (actually one of the forms
>>> implemented there). Probably the use case is closer to portal cases than to
>>> normal "plain" interactions.
>> Yes, this is about a portal case.
>
> It will extend to it a bit more, if M would have areas, where more than one
> subordinate is to be displayed at a time with the
> resulting page. In such case there would be more changes required to both
> blocks involved as only one of them can take over control.
> (Imagine, both subordinates are going to show forms...)
Yep, but the data coming from browser is interesting for one block only at the
time. It's the block
whose form has been submitted. Other blocks should redisplay its content
without any extra
processing because there was no data to process, right?
>>> I'm looking at the whole structure like I would at an OO object instance. I
>>> do have an instance that has provisions of calling some
>>> methods on local "data" instances (fields). The signature is quite clear.
>>> The actual implementation might cover a wider range of known
>>> or not yet known behaviour. Nevertheless _control_ is delegated to such
>>> methods. Of course you could restructure the whole thing to
>>> always call the instance data method and cause it to use some
>>> implementation parts of the (former) entry class making the former
>>> instances derived classes in the new structure. This is what I did
>>> understand to be the equivalent of the solution you suggested. But
>>> I doubt this will lead to a "natural" structure of responsibilities,
>>> especially if not all methods of the original instance data
>>> classes should be exposed to (arbitrary) callers of M.
>> I also try to think about whole problem in OO terms but apart from plain
>> concepts of OO I try to
>> take into account best practices like isolation.
>>
>> If you are programming in any OO language you probably consider global
>> variables a bad practise as
>> well as passing heavy amounts of data all over around. You strive for design
>> where methods of
>> objects are specialized, don't you?
>
> I can not see where in the current structure we would have something
> resembling global variables.
The global variable here is the request coming from browser. Your original idea
was to let every
block access the whole request coming from browser. I think it's a bad idea and
it resembles global
variable to some extent.
> I'm just trying to apply some abstract concepts (from OO world in this case)
> to SSP.
>
> We are providing derivation and overriding semantics for "data".
> A block currently exposes (some) pipelines to be "called" (used) from other
> blocks.
> Any such pipeline will get called on the purpose of retrieving the "data"
> associated with said pipeline.
> A contract will usually include basic semantics and format of such data.
>
> This will suffice for most cases. nevertheless, as long as a pipeline is
> allowed to provide aspects of control (flow via map:call
> (function or continuation) the actual data just is a side effect (the
> activities carried out while retrieving the data result are a
> side effect in the first place but as the initial side effect is the main
> interest here, view on things and attributions should be
> changed).
>
> This is close to the difference on stateless and stateful classes with OO
> languages. (and please everyone, do not start a discussion
> on whether stateless or stateful designs are superior).
>
> Current use of SSP supports "functional" calls, where result just depends on
> parameters. The question effectivly no is, whether SSP
> should/will/must support any stateful semantics that cocoon itself has
> provisions for.
Yup, you have got the point. My own opinion is that it's the best if SSF did
not support stateful
semantics or at least it shouldn't be done the way when you pass everything
everywhere.
>> The second one is the most important because it destroys the whole idea of
>> your M block. You
>> probably wanted to have one nice, universal pipeline delegating generation
>> of some parts of your
>> pages to subordinate blocks. However, if some of them require M block to
>> pass some data of original
>> request it becomes kind of troublesome because you need to dynamically chose
>> if you need to pass
>> data or not. I bet you (or one of your young developers) will end up with
>> passing everything to
>> every block. That would be a complete disaster and contradiction of ideas
>> behind SSF.
>
> I'm fully aware, that in practice implementors will choose to just pass the
> complete request (at least for avoiding to seriously
> consider what really would be needed or really should be available with
> subordinate blocks). This was reasoning behind my remark for
> probably short circuiting such special case to improve performance. But risk
> of misuse by programmers might not be sound ground for
> rejecting a major concept.
Let me explain my hesitation on making SSF more sophisticated. We already have
something that you
ask for in Cocoon, it's cocoon: protocol. It provides access to the data coming
from original
request when you make internal pipeline calls (internal requests). I tell you,
it gave people a lot
of freedom but at the same time it allowed them to bake sitemap full of crap
that I wouldn't call
the best practice but it's my own opinion. More objective part is a point of
view of Cocoon
developer. I'm such and believe me I become sick when I hear about cocoon:
protocol because it (with
it's friend map:mount) the main reason why we got to the point where almost
nobody can maintain
Cocoon's core because it is so complex. Yes, I'm speaking about implementation
details but they are
hell important to me and I think they should be important to the whole
community because
unmaintainable code will hurt everyone in the long term...
Personally, I don't believe that the functionality we are talking about can be
implemented in a
clean way leading to maintainable code. Moreover, I don't care that much when I
can give you example
of a much better architecture that Cocoon applications should take that doesn't
require
functionality of cocoon: protocol.
Anyway, I'm still open and willing to discuss. :-)
>> Imagine you have many, many roads crossing each other in one point. You can
>> easily imagine that no
>> matter how big crossroads you will build with how many fancy spiral ramps
>> you will build it's going
>> to be a major bottleneck in the whole traffic. What I suggest is to build
>> more, smaller crossroads
>> that will distribute the overall hindrance among many different places.
>
> You're absolutely right, M is a major bottleneck and that is on purpose. M in
> my case (the central crossing) is just the big toll
> station (to keep the picture)
>>> Thus, if the current SSP already is creating some kind of request, what
>>> does prevent it to allow for setting up a POST (or any other
>>> request method besides GET). Ok, there is some need for a syntax to make
>>> clear what kind of request should be performed, while the
>>> regular use case would prefer following the request method that triggered
>>> the subsequent call. This will also provide a clean
>>> transitive semantics for internal resources: some are best exposed using
>>> GET, others require POST, or other methods. And it is up to
>>> any caller can ensure correct usage.
>> There is a subtle problem with this approach. You mentioned servlet service
>> calls in your previous
>> e-mails so you are aware of the fact that internally they use POST requests
>> to pass XML data to be
>> processed. What if someone stumbles upon the idea of creating a service that
>> requires access to the
>> original request. Sure, let's pass the POST data coming from browser, but
>> what the heck are going to
>> do with the XML data that needs to be passed as well?
>
> Sorry, here I got lost.
> Where does XML data come in here?
> For my (probably simplistic perspective) SSP is the method call runtime
> implementation for an object based structure based on cocoon
> blocks. Calls my result from a "browser" or form other blocks (or probably
> from other sources e.g. web services...).
> Naively, I assume a block should be provided the very same "calling"
> possibilities than a browser would have (and currently does have,
> obviously).
Your probably should study this thread[1] and this[2] issue. Postable source is
already implemented
and used in 2.2's demos (for styling). Internally, postable source makes a POST
request, more
details you will find in referenced thread. How would you handle request coming
from postable source
when you would need to pass original post data coming from browser as well?
>>> URLs being resolved to pipelines somehow resemble accessing fields in OO
>>> languages. It sounds quite unnatural to just invert
>>> algorithmic control to cleanly get access to some (probably overloaded)
>>> fields when delegating control would be more appropriate?
>>> (Leaving the question unanswered whether my initial use case would serve a
>>> good argument example here).
>> It's more making methods call than accessing to the fields. What if you take
>> argument of redundant
>> parameters (data) passing?
>
> Can you explain a bit more here on what you have in mind?
Still the same: passing whole request to the called is like passing parameters
to the methods that
completely do not need them.
[1] http://thread.gmane.org/gmane.text.xml.cocoon.devel/67477/focus=67480
[2] https://issues.apache.org/jira/browse/COCOON-2046
Best regards.
--
Grzegorz Kossakowski
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]