[Pangloss] Re: [openframe] [RFC] OpenFrame AppKit ideas

Steve Purkis spurkis at quiup.com
Tue Apr 8 11:39:59 BST 2003


Hi James,

Thanks for the comments and suggestions.  I've forwarded your last post 
on to Pangloss and cross-posted again as I think it still applies - I'm 
trying to feel out the framework I'll be building Pangloss in and would 
like the others to see the process.  So please watch replies again .. :)

After taking some time to digest your message I've come to the 
conclusion that I'd misinterpreted the goals of AppKit.  I was assuming 
it was meant to be a production quality application framework for the 
web, along with extensibility, bells 'n whistles and such.  And so I 
was holding it up to the light, comparing it to others that I know 
about and trying to point out ways to improve AppKit.

I think this best sums it up for me:

On Monday, April 7, 2003, at 06:34  pm, James A. Duncan wrote:
> For now I remain unconvinced.  Not that what you're proposing isn't 
> valuable, but I don't think that AppKit is the right place for it 
> straight away.   This is the main reason that some of the things that 
> we've done at Fotango similar to what you're suggesting  haven't been 
> rolled into AppKit (well, that and general time limitations).
>
> However, I think that OpenFrame as-a-whole would benefit from 
> something along these lines, and would allow you to do it easily (in 
> as much as openframe on its own gives you a good starting point, some 
> useful scaffolding, and won't get in the way too much).
>
> Hmm, dictionary.com -> thesaurus -> strut -> Lintel? Crossbar? Joist? 
> Girder?


What a shame: you guys have already solved all these problems, but 
haven't had time to release them to the world?!  *sniff* !  It would 
certainly make my job a lot easier! ;-)

But seriously, if you do get around to releasing something and need a 
hand with it let me know.  In the meantime I think I'll follow your 
suggestion and investigate a separate OpenFrame project.

Next question: is it ok to piggy-back discussions on the OpenFrame list 
until the idea solidifies, or would it make sense to start up another 
one from the start?

At any rate, you've made a lot of good points I'd like to cover below.  
I've tried to cut out the ones that are covered by the above so it's 
not too long winded:


>> I'm forced to invent a way of handling errors.  I suppose I could
>> just stick them in the Session and let the template writer deal
>> with it.  But then I gotta remove them on each request, and what
>> if I want to handle them before they get to the template?
>
> Thats fine, invent a way to handle errors.  Its pretty hard to come up 
> with a clever way of abstracting errors and localizing them, and have 
> it cross cut your presentation and business logic.  This is a 
> difficult problem, and not one I've managed yet to solve or find a 
> system that elegantly solves it for me.

It is hard to abstract this, yes.  The way I've handled it in the past 
has been to throw exceptions my business logic layer, and then convert 
the exceptions that reach the presentation layer into error flags that 
the template writer can use.  (Assuming the presentation layer is 
defined by a template, of course :).

This puts the onus on the Template writer to cover all the error flags 
that can be set which requires some discipline and, while annoying, 
works for the situations I've encountered thus far.

I was hoping to use Locale::Maketext for situations where error flags 
are not enough, though I admit I haven't thought it through yet.


>   Rather than putting a two-bit hack into OpenFrame for this, we've 
> left it out 'cause we've not yet encountered a sensible way of doing 
> this without varying degree of hoopage.   I suppose the best way from 
> a pure programming perspective is to throw an exception that knows how 
> to render itself in multiple languages.

Arguable - the presentation layer might want to interpret the error and 
output something completely different.  I like exceptions to be dumb.

Anyways, one idea is to come up with various error-handling toolkits 
for OpenFrame.  That way at least users would have something to go on, 
but can roll their own if need be.


>   However, I hate message files that are based on key value pairs and 
> thats the easiest way to be able to hand someone a file to translate.  
> Come to think of it, I just hate presentation layers.... :-)

Come now, you won't get any sweets if you keep talking like that! ;-)



>> But most importantly, I'm not convinced entry points are a good
>> idea.  They don't give enough control over the path of execution:
>
> Something we've done at fotango to great effect is to give the 
> pipeline control over the flow of execution.  Rather than trying to 
> put the entirety of an application in one segment we split it up into 
> its constituent parts.  For example, we'd have an image loader, a 
> title changer, a rotator, and a renderer.  We'd stick them in a 
> pipeline-of-pipelines that if drawn in xml might look something like 
> this:
>
> 	<pipeline>
> 	  <segment> album_loader </segment>
> 	  <segment> image_loader </segment>
> 	  <pipeline>
> 		<segment> decline_without_image </segment >
> 		<segment> rotate_an_image </segment>
> 		<segment> change_an_image_title </segment>
> 		<segment> render_an_image </segment>
> 	  </pipeline>
> 	  <pipeline>
> 		<segment> decline_without_album </segment>
> 		<segment> change_an_albums_title </segment>
> 		<segment> render_an_album </segment>
> 	  </pipeline>
> 	</pipeline>
>
> The loader's will load the appropriate object when they can, and then 
> the decliners sat at the top of the embedded pipelines return a 
> Pipeline::Production if there isn't something the rest of the chain of 
> execution down that particular pipeline can handle.  By using this 
> method rather than AppKit::App's fairly obscure entry-point 
> mini-language, we've been able to get expressive classes that cause 
> the model do one thing and one thing only.  By joining them together 
> in various ways we can quickly create new applications or by writing 
> the merest sliver of code bring as-yet unused parts of the model into 
> play.

So you're essentially classifying your segments and blocking entry to a 
pipeline when there's nothing in it that it can handle.  Good idea - I 
can see the utility in that.  For example, you could branch off another 
pipeline that handled privileged operations that declined requests 
based on type of user.  You'd also get a good overview of your 
application without all the clutter.  I will definitely look further 
into this.


>>   Actions
>> 	A thing that gets done, like logging in, making a payment,
>> 	or displaying a summary.  These are usually short 'n sweet
>> 	ie, a thin layer passing messages to your app objects.
>
> Thats essentially what a Pipeline::Segment _should_ do.  The hangman 
> example is actually a pretty good example of this. All the business 
> logic is held inside Games::GuessWord (or Games::WordGuess, I can 
> never remember which), and it acts as the controller for the 
> application.  Although I'll admit that the Hangman example could use 
> some refactoring and that it does kinda tie the controller and bits of 
> the view together, its model is removed from the other two elements.

I agree that there are a lot of similarities between a Segment and the 
idea of an Action.  The main difference is that an Action would be a 
bit more specific about what it does: validates and executes actions 
based on OF::Request's.

As for making sure developers write good controllers... well, as in 
OpenFrame, you can only give them the toolkit.  What they do with it is 
up to them...  Though you might be able to force a limit on the number 
of ops executed in the Segment after it is dispatched ;-)


>>   URL -> Action mapping
>> 	Each Action has a url, set in a config file.
>
> The other problem with this is a localization issue - if you take a 
> piece of a URL, for example 'red.html', your french translater is 
> probably going to want to translate this to 'rouge.html'.   Depending 
> on how tightly your URL's are bound to your actions you're going to 
> either have to duplicate the section that calls into your application 
> _or_ have some sort of pattern matching.  I'm not particularly in fond 
> of either of those two outcomes.

I got that wrong: each Action has one or more URLs.  Which means 
pattern matching, yes.  I was thinking along the lines of 
DispatchOnUri, and frankly I still don't see much wrong with that.


> In general I detest config files.  Config files are mini-languages, 
> and can be far better expressed in a programming language.  I get the 
> feeling I hold a different opinion on this from most people > 
> however....

I see your point, but I disagree.  It's true, config files *are* 
mini-languages, but that's precisely why they're so useful.  They make 
a world of difference for non-programmers -- imagine how difficult it 
would be to administrate a machine if you had to know every programming 
language available to do it?  A well thought out config file can save a 
lot of hassle...

Of course, if you go ahead and program an easy to use administration 
interface then you could theoretically do away with config files.. :)


>>   Action Forwards
>> 	Each Action can have one or more named 'forwarding' url's
>> 	which can be used to choose which template page to load.
>> 	    success => "/success.html"
>> 	    failure => "/failure.html"
>> 	these are also set in a config file.
>
> See above :-)  Again with this I'd rather see the programmer decide 
> what is going to happen, rather than having a configuration file that 
> gets placed in obscure parts of the system.

The programmer does decide what will happen and defines it in a config 
file.  It's almost like saying: The administrator chooses which 
templates to load.  Which may or may not be handy.  And may or may not 
be extra hassle for the programmer.  Hmm.. now you've got me wondering.


> One of the things I like _least_ about OpenFrame is the proliferation 
> of dumb data objects that it seems to encourage. This is partly my 
> fault because I also dislike the idea of introducing named keying into 
> a Pipeline::Store,subclass but of course people have gone and done 
> this anyway :-)
>
>  Lots of these things seem like just that without much in the way of 
> behaviour which causes me to feel a little disturbed about them.  The 
> current OpenFrame gets away with just a couple of data objects: 
> OF::Request, OF::Response, and OF::Cookies (OF::Cookie is just a 
> wrapper around CGI::Cookie, but at least that gives it *some* 
> behaviour :-) and I'd be worried about setting a trend by having more 
> data objects than behavioral objects in the system.

Point taken.  I'll try to avoid this.


>> Localisation
>> ------------
>> I'm still a bit fuzzy on this.  AFAICS, localisation needs to
>> be done in three places:
>>
>> 	1. Reporting Application Errors (404, 500, etc.)
>> 	2. Choosing which template to process
>> 	3. Displaying messages to the user from a template
>>
>> Which means we need hooks in these places.  But perhaps the
>> problem could be solved in general by a Localisation segment
>> that puts something in the Store that other segments can use?
>
> We do that at Fotango for CIG as well as other systems that are being 
> worked on at the moment.  We have a Site-map class that maps URLs to 
> abstract paths in the system, and back to templates.  The site-map 
> also carries all the text and error messages that are used by the 
> templates.  The problem with it is that although the information is 
> kept in one place and one place only it also seems to be a pain to 
> remember just where that place is.  Again, I hate presentation layers 
> so I'm probably not best to comment on this mechanism as opposed to 
> any other - I hate them all :-)

Hmm..  The idea of a site map that maps URLs to paths and back seems 
like a sound idea to me.  But including all the text + error messages 
in this object seems misplaced to me.  Yes, they all contain text that 
can be localized, but that's the only thing they share in common.  To 
me, that's not enough of a reason to lump them all together.  Have you 
considered introducing a Template class that includes messages (errors 
and text), and knows how to localize them?

-Steve



More information about the Pangloss mailing list