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 |
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] |
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 |
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:1) HTTPRequests have no knowledge of resolution. If a resource needs #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. 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.As I see it, one implementation issue of the second would be that an 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. :) 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.The benefit of the first is that it separates resolution from request. If a 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.I am still leaning towards 1) however after writing the above, my lean is 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). 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.- We add an object -- call it a ResponseFactory, for now -- that holds 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 |
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 |
Free forum by Nabble | Edit this page |