URIResolution

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
5 messages Options
Reply | Threaded
Open this post in threaded view
|

URIResolution

Steve Alan Waring
Hi Ken (and all),

Thanks for the latest VW code and the information on the wiki. I have
downloaded the Swazoo packages from Store, and I will work my way through
them this week.

One issue is resolution, as I see it, the difference between VW and Dolphin
is that as the resolution progresses, the (VW) URIResolution instance sets
its state changes (ie position) into the HTTPMessage instance while the
(Dolphin) URIResolution instance doesnt.

If required, a (VW) Resource can access this state through the hTTPMessage
(and as Ken notes on the wiki, this is also duplicated in the tailStream it
is sent by the uRIResolution).

If required, a (Dolphin) Resource can access this state through the
uRIResolution.

I dont see a clear benefit between the two, but to explain why Dolphin takes
it current approach:

-It removes a duplication (URIResolution's position and HTTPRequest's
resourcePosition).
-It places all state changes during resolution into the one object. I
believe this state belongs more to the URIResolution instance than the
HTTPRequest instance.
-(VW) HTTPRequest's resourcePosition is the only instance variable which
changes once a request has been read.
-URIResolution is a class that could gain more responsibility and
functionality if more control is needed in resolution.
-While it does force some Resources (ie FileResource) to become aware of
URIResolution, these are Resources that are involved in the resolution
process and in effect take over the responsibility of resolution from
URIResolution. Dolphin makes this responsibility transfer explicit.

It will be easy to bring Dolphin into line with VW, but before I do, are
there any thoughts on this?

Thanks,
Steve



Reply | Threaded
Open this post in threaded view
|

Re: URIResolution

Ken Treis-4
Steve,

Some interesting ideas.  You're making me really think about a design
that I put together a while ago.  :)

I'm going to snip a couple parts of your email and respond to them
individually:

On Monday, March 4, 2002, at 05:48 AM, Steve Waring wrote:

> If required, a (Dolphin) Resource can access this state through the
> URIResolution.

If I understand correctly, the Dolphin code sends a message like
#answerTo:resolution: instead of the #answerTo:resolvedOn:.  I must
admit that I don't like the presence of the stream in that (latter)
message, because it is information that's currently readily available in
the first argument.

> -It removes a duplication (URIResolution's position and HTTPRequest's
> resourcePosition).

This is a Good Thing.

> -It places all state changes during resolution into the one object. I
> believe this state belongs more to the URIResolution instance than the
> HTTPRequest instance.

This is also a good idea.  I could never put my finger on what bothered
me about the very existence of URIResolution>>setResourcePathIn: , but I
think you've found it.

> -(VW) HTTPRequest's resourcePosition is the only instance variable which
> changes once a request has been read.

That's not entirely true.  A session resource may stick something in the
environmentData of the Request, even though it's not entirely sure that
one of its children will be able to answer.  If none of its children can
answer, it removes its session from the environment.

> -URIResolution is a class that could gain more responsibility and
> functionality if more control is needed in resolution.

I don't quite understand what you mean here -- perhaps because I am
having a hard time seeing what other sort of control might be needed in
resolution.  But I agree that it makes sense to concentrate the behavior
of the resolution in URIResolution.

> -While it does force some Resources (ie FileResource) to become aware of
> URIResolution, these are Resources that are involved in the resolution
> process and in effect take over the responsibility of resolution from
> URIResolution. Dolphin makes this responsibility transfer explicit.

This could be handled cleanly, though.  I think there's some real value
in keeping HTTPRequest>>tailPath around, even if it forwards its
behavior on to a URIResolution.

-=-=-=-

I'd like to propose a design that follows what you've done with the
URIResolution in Dolphin but also addresses a couple of the issues I've
seen while building Swazoo code.  Apart from the design issues that
you've mentioned, I'd like to see us eliminate:

- The current #answerTo -> #reallyAnswerTo indirection.  It's a
hold-over from the days before URIResolution existed.

- The need to pass more than one parameter when getting a response out
of a Resource.

- (if possible) The need to pass the Request all over the place when
building up a more complicated reply.  There is a lot of behavior that
surrounds the both the request and the resource during this process, and
that begs for an object to be created that holds both of them while
building a response.

So, here's the proposal:

- After an HTTPRequest is read off of the socket, we immediately assign
it a URIResolution (perhaps by means of URIResolution
class>>resolveRequest:startingAt:).  The URIResolution then proceeds to
do his job, which basically amounts to getting a response out of some
resource.

- We implement HTTPRequest>>tailPath as a simple forwarder to the
URIResolution, which builds a tailPath by copying his URI parts from
(position + 1) to (last).

- Resource>>answerTo:resolvedOn: and #reallyAnswerTo:resolvedOn: go
away, replaced with a single #answerTo:.

- We add an object -- call it a ResponseFactory, for now -- that holds
three instance variables: the request, the resource, and the response.  
This object will be subclassed by particular resources, and code will be
added to each subclass that fleshes out and builds the response.  The
factory is told to build the response, and then it is asked for the
response in a separate message. This does several things for us:
        - It eliminates the need to pass the request all over the place
while building a response.
        - It provides a well-defined place for putting behavior that is
request-specific.
        - It's a place where it's safe to save per-request state.  
Subclasses can add instance variables if needed.

I'm not sure how to integrate something like the ResponseFactory (and
I'm open to calling it something else); perhaps we could add direct
subclass of Resource that implements the ResponseFactory indirection in
#answerTo:?  It doesn't really matter to me.  I don't want to force this
paradigm on all Resources, because it's overkill for some of them.  But
for anything complicated, it sure simplifies things.  Thoughts?  Has
anybody else run into this?

In any case, please give feedback on the above design.  And Steve,
thanks for taking the time to look at this issue in the first place.  It
needs a fix, but you had the initiative to actually think it through and
do something about it.  Once we agree on something, we can dive in and
get it done.


--
Ken Treis
[hidden email]



Reply | Threaded
Open this post in threaded view
|

Re: URIResolution

Steve Alan Waring
Hi Ken,

> If I understand correctly, the Dolphin code sends a message like
> #answerTo:resolution: instead of the #answerTo:resolvedOn:.  I must
> admit that I don't like the presence of the stream in that (latter)
> message, because it is information that's currently readily available in
> the first argument.

Yes, Dolphin sends #answerTo:resolution: which for compatibility reasons
sends #answerTo:resolvedOn: (which in turn sends
#reallyAnswerTo:resolvedOn:). A cleaner approach in this design would be for
Resource>>answerTo:resolution: to send #answerTo:

I like your proposal, I think it would fit nicely into the Dolphin version.

Since receiving your message, I have been tossing up the pros/cons of the
following designs, the first is closer to the current Dolphin
implementation, the second is what I understand to be your proposal. In
essence:

1) HTTPRequests have no knowledge of resolution. If a resource needs
resolution information, it must access it through a URIResolution.
2) A HTTPRequest keeps a pointer to its URIResolution. A Resource accesses
the resolution information through the Request. (In effect, Request
implements the "resolution" protocol and implements it by forwarding to
URIResolution.) Is this a correct understanding?

I see the benefits of the second being:
-A resource only need implement #answerTo:
-HTTPRequest>>tailPath can be implemented
-All information about the request and its resolution state can be accessed
from a single object.

As I see it, one implementation issue of the second would be that an
HTTPRequest would have a pointer to a URIResolution, and that URIResolution
has a pointer to the HTTPRequest. Is this an indication that we can still
tweak this design?

The benefit of the first is that it separates resolution from request. If a
URIResolution is supplied with a SwazooURI, it can be used to locate a
resource and deliver any object to it for answering. Currently on
Dolphinharbor we are testing a server which reads requests from FastCGI
connections, and resolves those requests using SwazooResources. While this
could be done using either of the designs, the second would require the
"resolution" protocol to be added to a fastCGI request.

I am still leaning towards 1) however after writing the above, my lean is
less :)

What do you think?

>
> - We add an object -- call it a ResponseFactory, for now -- that holds
> three instance variables: the request, the resource, and the response.
> This object will be subclassed by particular resources, and code will be
> added to each subclass that fleshes out and builds the response.  The
> factory is told to build the response, and then it is asked for the
> response in a separate message. This does several things for us:
> - It eliminates the need to pass the request all over the place
> while building a response.
> - It provides a well-defined place for putting behavior that is
> request-specific.
> - It's a place where it's safe to save per-request state.
> Subclasses can add instance variables if needed.

A framework to do this could be very useful. I have built classes (
SwazooCacheControl and ChunkedEntity come to mind) that contain the
request/response and resource in the past, and having a framework might
encourage reuse.

Are you planning to use ResponseFactories to build content?

Thanks,
Steve
www.dolphinharbor.org




Reply | Threaded
Open this post in threaded view
|

Re: URIResolution

Ken Treis-4
Steve Waring wrote:

  
1) HTTPRequests have no knowledge of resolution. If a resource needs
resolution information, it must access it through a URIResolution.
2) A HTTPRequest keeps a pointer to its URIResolution. A Resource accesses
the resolution information through the Request. (In effect, Request
implements the "resolution" protocol and implements it by forwarding to
URIResolution.) Is this a correct understanding?
That's not quite what I meant.  I still expect that URIResolution will be the only one that implements the resolution protocol.  He does the work, he holds the data, he implements the methods.  The only behavior that would be forwarded is:

#resourcePath
#tailPath
#rootConstruct:

These are the only three methods in HTTPRequest and its subclasses that refer to the resourcePosition.  I even discovered that we have an unused instance variable called #resourcePath that we need to get rid of.

If any resource needs some sort of more involved information from the Resolution (is there any more information in the Resolution that anybody would need?), it can ask the request for the resolution and get is information "from the horse's mouth".

And, if we end up adding a parent reference to each resource, then the need for #tailPath and #rootConstruct: goes away entirely, leaving us with just one forwarded message.
As I see it, one implementation issue of the second would be that an
HTTPRequest would have a pointer to a URIResolution, and that URIResolution
has a pointer to the HTTPRequest. Is this an indication that we can still
tweak this design?
Perhaps, but I'm not too concerned about back-pointers, especially among two objects that work closely with each other.  The Resolution needs the request in order to traverse its URI and attempt to get responses from candidate Resources, but it could be made to pass the request as an argument.  That'd complicate the code; it's much cleaner with a direct reference. Both of these objects are short-lived, anyhow.

Actually, this makes a sort of intuitive sense to me.  There are two stages that a request goes through: (1) read but unresolved and (2) resolved.  When resolved, the Request has a Resolution (i.e., has a reference to a resolution for itself).  This isn't a very strong argument, I understand, so feel free to shoot it down.  :)
The benefit of the first is that it separates resolution from request. If a
URIResolution is supplied with a SwazooURI, it can be used to locate a
resource and deliver any object to it for answering. Currently on
Dolphinharbor we are testing a server which reads requests from FastCGI
connections, and resolves those requests using SwazooResources. While this
could be done using either of the designs, the second would require the
"resolution" protocol to be added to a fastCGI request.
I don't know much about how FastCGI works, but a FastCGIResolution could just as easily interact with any one of our HTTPRequests in the same way that our current URIResolution does.  I probably wasn't very clear about what I meant by "forwarding methods", but I was really only thinking of #tailPath.
I am still leaning towards 1) however after writing the above, my lean is
less :)

What do you think?
I can also see some merit in #1, and I could be persuaded towards either solution.  It wouldn't be a hard refactoring to move from one to the other if a real driver appears.

Unless I've completely convinced you otherwise, let's go with your proposal to use #answerTo:resolution:.  This will be the quickest way to unify the code bases; besides that, your design has been built already while mine is just an idea.  :)  I don't have the time to implement it tonight, but maybe tomorrow evening I could dive in.

It does have me thinking, though: perhaps the Request itself really *should* implement the resolution protocol.  URIResolution goes away, and requests just "know how to resolve themselves".  We've already gone through the following two designs with mixed success:

1. Resources know how to resolve requests (this was ugly, so we implemented #2)
2. URIResolutions know how to resolve requests (requires a tango between the Request, the URIResolution, and the Resource).

Our current implementation (#2 in this list) is better, but we're already talking about cleaning it up (both to remove some remnants of the old #1 code and to deal with some limitations of #2).  There's a sort of Alan Kay-ish ring to "requests resolve themselves"....

Again, I don't know enough about FastCGI to see how we'd solve your FastCGI question in this design.  Maybe with a different type of URI?  I'd hope that it's not too different from receiving and parsing a URI.  If Apache happens to parse the URI for you, then all we'd really need is a different sort if URI (and maybe a different instance creator on HTTPRequests).

            
- We add an object -- call it a ResponseFactory, for now -- that holds
three instance variables: the request, the resource, and the response.
This object will be subclassed by particular resources, and code will be
added to each subclass that fleshes out and builds the response. The
factory is told to build the response, and then it is asked for the
response in a separate message. This does several things for us:
- It eliminates the need to pass the request all over the place
while building a response.
- It provides a well-defined place for putting behavior that is
request-specific.
- It's a place where it's safe to save per-request state.
Subclasses can add instance variables if needed.

A framework to do this could be very useful. I have built classes (
SwazooCacheControl and ChunkedEntity come to mind) that contain the
request/response and resource in the past, and having a framework might
encourage reuse.

Are you planning to use ResponseFactories to build content?
Yes, I had been planning on that (and I have used Swazoo to build content previously).  There have been times when this has worked out well -- i.e., you render a component entirely differently based on whether the user is logged in as an administrator or not -- but at other times it's become hard to manage.  It's a lot harder to write HTML using streams than it is to write it in a flat file.

I've been using Swazoo in a bit of a bubble, so I wanted to find out if I was the only one who found myself passing the request all over the place while building up a reply.  As I think about it, the reason for doing that has always been for content generation, and perhaps Swazoo Resources aren't the best place to generate content.  What other Swazoo resources have you built, and how much content generation have they done?


Ken
Reply | Threaded
Open this post in threaded view
|

Re: URIResolution

Steve Alan Waring
Hi Ken,

> Unless I've completely convinced you otherwise, let's go with your
> proposal to use #answerTo:resolution:.  This will be the quickest way to
> unify the code bases; besides that, your design has been built already
> while mine is just an idea.  :)  I don't have the time to implement it
> tonight, but maybe tomorrow evening I could dive in.

I am easy either way. Once you have something implemented let me know which
you prefer.

> Again, I don't know enough about FastCGI to see how we'd solve your
> FastCGI question in this design.  Maybe with a different type of URI?
>  I'd hope that it's not too different from receiving and parsing a URI.
>  If Apache happens to parse the URI for you, then all we'd really need
> is a different sort if URI (and maybe a different instance creator on
> HTTPRequests).

The difference is mainly in the parsing. I have a builder object that takes
the CGI parameters ( ie the "Params" list at:
http://www.dolphinharbor.org/ns1/test ) and builds a Request. I will be able
to implement it in either design.

> I've been using Swazoo in a bit of a bubble, so I wanted to find out if
> I was the only one who found myself passing the request all over the
> place while building up a reply.  As I think about it, the reason for
> doing that has always been for content generation, and perhaps Swazoo
> Resources aren't the best place to generate content.  What other Swazoo
> resources have you built, and how much content generation have they done?

I did have a dynamic content generation system on Dolphinharbor early on,
but I didnt like how it worked and I have scraped it.

I recently added some soap client pages which generate content:
http://www.dolphinharbor.org/interop/spraySoapOperaClient.html
http://www.dolphinharbor.org/spray/r3/index.html ("client" links)

These pages share the same SwazooResource class. Each instance has its own
entityClass. To answer a GET or POST, the resource creates an instance of
the entityClass which builds the appropriate response. It is not a general
framework, it works using a mixture of string macroExpansion and streaming.

For dynamic content generation, I like how Zope's ZPT system works, and
Seaside http://www.beta4.com/seaside looks great. Seaside might be difficult
to port to Dolphin because of its use of continuations, but I read that
there is a VW port on the way.

Thanks,
Steve
www.dolphinharbor.org