Class methods and representations

0 views
Skip to first unread message

Dean Landolt

unread,
Nov 6, 2009, 10:41:19 AM11/6/09
to persevere...@googlegroups.com
Now that slash-delimited class ids as namespaces are sorta supported in 1.0, I've been given some thought to one of the oddities with them. For a class without slashes, say Class/Foo, load("/Foo") and load("/Foo/") are equivalent, both returning the foo.instances array. But for slashed classes, say Class/foo/Bar, load("/foo/Bar/") returns the foo/Bar instances array but load("/foo/Bar") returns a 404. This inconsistency has been nagging at me, and I think I've found a way to close the gap with a really useful feature...

I understand that having trailing slashes be significant by default confuses people, but I would contend it's not totally sensible to return the same thing for load("/Foo") and load("/Foo/") -- so I'd propose that by default /Foo should permanently redirect to /Foo/ (and foo/Bar to /foo/Bar/) -- it seems like the sensible thing to do. But I'd also like the ability to configure my classes to instead alias /foo/Bar (the non-trailing slash version) to /Class/foo/Bar to be able to have a clean path toward class methods and representations.

So as an example, say I have a text/html representation of my foo/Bar class that has some interface elements that eventually lead to foo/Bar instances. From a usability standpoint I think /foo/Bar returning the foo.Bar class representation makes way more sense than /Class/foo/Bar, especially because the instances themselves will be available at /foo/Bar/n. Same goes for class methods -- /foo/Bar.search('baz') as the url to the class method makes more sense to me than /Class/foo/Bar.search('baz'). Does all of this make sense?

As an aside, does anyone know a convenience way to get at an object's class? Presumably one could do a global[obj.id.split("/").slice(0, -1).join("/")] -- is this the best way, or is there something better out there? Technically persvr allows you to put slashes in ids as well, which would break this -- I haven't tried this in a while but I remember some (expected) buggy behavior.

Paul Spaulding

unread,
Nov 6, 2009, 11:38:54 AM11/6/09
to Persevere
Dean, I would like to know more about this. Are you saying that you
use slashes in the Class definition files?

Class({
id: 'foo/bar'
,...
})

Does using slashes provide some benefit in Persevere over using
another separator such as an underscore as in id: 'foo_bar'?
If you have a namespace hierarchy like this:
foo
/bar
/baz
fuz
/bar
/baz
Is there a way of having a single baz definition, or does it still
need to be broken up into separate foo/bar/baz and fuz/bar/baz files?

Dean Landolt

unread,
Nov 6, 2009, 1:30:05 PM11/6/09
to persevere...@googlegroups.com
On Fri, Nov 6, 2009 at 11:38 AM, Paul Spaulding <pjs6...@gmail.com> wrote:

Dean, I would like to know more about this.  Are you saying that you
use slashes in the Class definition files?

Class({
 id: 'foo/bar'
 ,...
})

Precisely. This makes instances accessible at /foo/bar/<instance_id>

It's proven to be a nice pattern. At first Kris suggested (and convinced me) that it was better to delimit packages with dots (something not possible in persvr currently), but then decided that having both -- slashes for network, dots for console, presumably made more sense. He fixed a few bugs associated with slashes in ids (there were just a few little things) so that's why I said "sorta supported" -- I don't think it's officially blessed but it's at least on the radar.
 

Does using slashes provide some benefit in Persevere over using
another separator such as an underscore as in id: 'foo_bar'?

Not in particular. It just happens to be a very common paradigm, and aligns nicely with HTTP semantics. /foo/bar/baz/1 is a whole lot more logical than /foo_bar_baz/1 -- and it allows you to use relative path semantics. So /foo/bar/baz/1/../.. should equal /foo/bar (which, per my proposal, would be an alias to /Class/foo/bar -- pretty helpful). Also, /foo/bar/baz/1/../../ would give you /foo/bar/, already an alias to /Class/foo/bar.instances -- see the logic? Use another /.. and you're up to /foo. This obviously wouldn't work with underscores -- you'd have to fall back to string manipulation and bake in the notion of _ as a reserved character in your domain.
 
If you have a namespace hierarchy like this:
foo
 /bar
   /baz
fuz
 /bar
   /baz
Is there a way of having a single baz definition, or does it still
need to be broken up into separate foo/bar/baz and fuz/bar/baz files?

Sure, you reuse the definition (by wrapping the Class constructor and changing the id based on some context), but obviously they'd be different classes as far as persvr is concerned (which is how it should be).

I was toying with the id of having a Package constructor that was really just a class wrapper that did a little bookkeeping, and would add special class and package wrappers to the generated object. You'd be able to do something like...

foo.Package({id: "bar"}); // results in /Class/foo/bar and foo.bar as class alias in global obj
foo.bar.Class({id: "Baz"}); // results in /Class/foo/bar/Baz and foo.bar.Baz alias in global obj


So foo would be a Package (just a read only class with Class and Package helpers). The "extends" property could be filled out automagically to foo, obviously...

Then foo.bar would be a Package too, with "extends": foo.bar. And foo.bar.Baz would be a class (with just a Class helper on it to make subclasses). It would be pretty simple to do -- I started on an implementation but realized I didn't really like it all that much. First I wrote a patch to hack persvr to add slashed based classes as dot-namespaced globals, but then realized I could go this route. Then it occurred to me this was all pretty imperfect and I'd rather just do this:

foo.bar = Class({id: "foo/bar", "extends": foo ... });
foo.bar.Baz = Class({id: "foo/bar", "extends": foo.bar ... });

This gives me more flexibility in case I don't want a namespaced global alias for a class, or want it to be something else.

Paul Spaulding

unread,
Nov 6, 2009, 2:33:45 PM11/6/09
to Persevere
Interesting stuff. Thanks!

On Nov 6, 1:30 pm, Dean Landolt <d...@deanlandolt.com> wrote:
> On Fri, Nov 6, 2009 at 11:38 AM, Paul Spaulding <pjs67...@gmail.com> wrote:
>
> > Dean, I would like to know more about this.  Are you saying that you
> > use slashes in the Class definition files?
>
> > Class({
> >  id: 'foo/bar'
> >  ,...
> > })
>
> Precisely. This makes instances accessible at /foo/bar/<instance_id>
>
> It's proven to be a nice pattern. At first Kris suggested (and convinced me)
> that it was better to delimit packages with dots (something not possible in
> persvr currently), but then decided that having both -- slashes for network,
> dots for console, presumably made more sense. He fixed a few bugs associated
> with slashes in ids (there were just a few little things) so that's why I
> said "sorta supported" -- I don't think it's officially blessed but it's at
> least on the radar.
>
>
>
> > Does using slashes provide some benefit in Persevere over using
> > another separator such as an underscore as in id: 'foo_bar'?
>
> Not in particular. It just happens to be a very common paradigm, and aligns
> nicely with HTTP semantics. /foo/bar/baz/1 is a whole lot more logical than
> /foo_bar_baz/1 -- and it allows you to use relative path semantics. So
> /foo/bar/baz/1/../.. *should *equal /foo/bar (which, per my proposal, would
> be an alias to /Class/foo/bar -- pretty helpful). Also,
> /foo/bar/baz/1/../../ would give you /foo/bar/, already an alias to
> /Class/foo/bar.instances -- see the logic? Use another /.. and you're up to
> /foo. This obviously wouldn't work with underscores -- you'd have to fall
> back to string manipulation *and* bake in the notion of _ as a reserved
Reply all
Reply to author
Forward
0 new messages