[Catalyst] How much chain?

J. Shirley jshirley at gmail.com
Fri Jul 11 17:04:03 BST 2008


On Fri, Jul 11, 2008 at 6:58 AM, Ian Docherty <catalyst at iandocherty.com> wrote:
> Thomas Klausner wrote:
>>
>> ... do I need to hang myself?
>>
>> I'm (finally) playing around with chained, and like it very much.
>> But now I have some sort of design question, on which I'd like to collect
>> some feedback:
>>
>> Say, you want to edit things. The general way of editing is the same for
>> most things, only the thingies you want to edit differ (i.e. their fields).
>>
>> (slightly OT, but some background: We want to use HTML::FormFu for actual
>> form generation, but do not want to use the config-file aproach, but
>> something like a 'registry' where each field and it's definition is stored
>> (basically we have several different things using similar fields...))
>>
>>
>> What to you think is better:
>> A) lots of chain
>>
>> package Thing:
>> use base 'Generic';
>> sub base : Chained('/') PathPart('thing') CaptureArgs(0) {}
>> sub setup_fields : Chained('item') CaptureArgs(0) {
>>    # define a list of fields and store them in stash
>> }
>>
>> package Generic;
>> sub item : Chained('base') PathPart('') CaptureArgs(1) {
>>    # load thing and store in stash
>> }
>> sub show_form : Chained('setup_fields') Args(0) {
>>    # take field list, make form, etc }
>>
>> I'd end up with an URL like  /thing/123/setup_fields/show_form
>>
>
> I really don't think you should expose your implementation in your URI. For
> example if in the future you decide to re-write your system to not use
> FormFu and not have a setup_fields and a show_form method you have to change
> your interface. It is rather like the advantages you get by encapsulation in
> OO programming, you can change the internal implementation without worrying
> about the interface.
>>
>> B) Plain Old Methods
>>
>> package Thing:
>> use base 'Generic';
>> sub base : Chained('/') PathPart('thing') CaptureArgs(0) {}
>> sub edit : Chained('item') Args(0) {
>>    my ($self, $c) = @_;
>>    $self->setup_fields($c, ... );
>>    $self->make_form;
>>    # }
>>
>> package Generic;
>> sub item : Chained('base') PathPart('') CaptureArgs(1) {
>>    # load thing and store in stash
>> }
>> sub setup_fields {}
>> sub make_form {}
>> sub handle_form {}
>>
>> I'd end up with an URL like  /thing/123/edit
>> which IMO looks nicer.
>>
>
> And IMO too. this is exactly how to use chaining. Don't hang yourself by
> trying to use chaining for everything.
>>
>> So, is A) just overdoing chained? B) looks ok, but is it using chained to
>> it's full potential?
>>
>
> It is using chaining to it's full potential (given the simple example you
> gave) but in a more complex example, e.g.
> /manufacturer/123/component/456/subcomponent/789/edit
>
> it would be clearer that chaining is going to make something like this much
> easier by putting the manufacturer object on the stash, then the next chain
> puts the component object on, then the subcomponent, then it chains to the
> 'edit' controller.
>>
>> I'd really like to hear some of your thoughts...
>>
>>
>
>

Using Chained gives you complete flexibility regarding your URL semantics.

If you want /item/id/123/edit:

sub setup_base : Chained('/') PathPart('item') CaptureArgs(0) { }
sub setup_item : Chained('setup_base') PathPart('') CaptureArgs(2) {
    my ( $self, $c, $find_by, $item_id ) = @_;
    # Search and store in stash
}
sub item_root : Chained('setup_item') PathPart('') Args(0) { }
sub setup_fields : Chained('setup_item') PathPart('') CaptureArgs(0) { }
sub edit_item : Chained('setup_fields') PathPart('edit') Args(0) { }

That would give you /item/*/*/edit and /item/*/* - both showing the
right thing to the user and not binding any external API to your
internal structure.

I wouldn't construct my chains in this fashion (I would have
setup_fields as a more abstract Private action to forward to) but it's
perfectly valid, and my main point is that with Chained you can
construct any external URI you want to display to the user very
simply.

-J



More information about the Catalyst mailing list