You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@shindig.apache.org by John Hjelmstad <fa...@google.com> on 2011/08/02 02:54:25 UTC

Re: javascript readability..

Hey Jesse:

We haven't loudly advertised exportJs() yet since we've been adding a final
piece of functionality to it for deferred symbol binding, and because
Shindig (on account of it being still by default on JDK 1.5 if nothing else)
doesn't use closure compiled JS by default yet.

For context, deferred symbol binding applies to features consisting of
methods that return nothing synchronously. Synthetic example:

// namespace setup here
gadgets.foo.doSomething = function(key, value, callback) {
  // do something with key and value
  callback(somethingComputed);
};

Deferred symbol binding allows us to emit a tiny JS loader "stub" that just
enqueues arguments to a method with this name. That stub -- actually the
async JS loader -- then loads the payload, which when loaded executes the
real method.

This allows fast integration of code via:
<script src="http://myserver.com/gadgets/js/foofeature.js"></script>
<script>
  gadgets.foo.doSomething('myKey', 'myValue', function(data) { /* myCallback
*/ });
</script>

...for syntactic convenience while maintaining asynchronous loading
semantics for latency purposes (ie. not blocking the page load).

The functionality overall is activated by the flag supportDefer="true" in
feature.xml, and server-side configuration for same. Without it, the above
syntax is not activated and things work as before.

I implemented a version of this with both deferred and full symbol binding
in exportJs() but found a few shortcomings with the approach. we're
rejiggering it today. I'd hold off for a short time while we do so to avoid
merge conflicts. The relevant JS CL is: https://reviews.apache.org/r/1237/

Cheers,
John
PS. Time will tell whether I regret it, but thanks for the props on the
method overall :) It's hard to measure precisely how valuable the technique
is since much of its value is preventative, ie. A) disallowing use of helper
methods as if they were supported APIs, and B) prevents symbol
clashes/occlusion with arbitrary contexts in which "our" JS is imported --
hopefully all while allowing a coding style that "feels" as if none of this
edifice exists.

On Fri, Jul 29, 2011 at 7:09 AM, Ciancetta, Jesse E. <jc...@mitre.org>wrote:

> Hey John,
>
> I hadn’t seen the exportJs support before (I haven’t done any work with
> features in a long time) -- that does look very similar!  (and as an aside
> -- hats off to whoever came up with that scheme to be able to closure
> compile JS in isolation but still have fully qualified symbols available in
> the global space -- its absolutely brilliant)
>
> I wrote a quick test gadget which required feature exportjs and did some
> testing -- and it comes pretty close to doing everything we'd need already,
> so I don’t see any reason why it couldn’t be augmented to handle all the
> cases my helper function does.  Then it'd just be a matter of making it part
> of the core feature set so it would be available for use in any features
> that wanted to take advantage of it.
>
> So I guess that comes back to Paul's original question though -- if enough
> people preferred the first style Paul proposed I'd be happy to take a crack
> at augmenting exportJs to support this use case.  So we'd end up with JS
> that looked something like this:
>
> //could be from foo-utils.js
> exportJs("shindig.util", (function() {
>     var privateData = "this is private";
>
>    var privateFunction = function() {
>        console.log(privateData);
>    };
>
>    var calculateFoo = function() {
>        privateFunction();
>    };
>
>    var doAlotOfFoo = function() {
>        //do alot of foo
>    };
>
>    return {
>        calculateFoo: calculateFoo,
>        doAlotOfFoo: doAlotOfFoo
>    };
> })());
>
> //could be from bar-utils.js
> exportJs("shindig.util", (function() {
>     var privateFunction = function() {
>        console.log("calculateBar called");
>    };
>
>    var calculateBar = function() {
>        privateFunction();
>    };
>
>    return {
>        publicData: "this is public",
>        calculateBar: calculateBar
>    };
> })());
>
> exportJs("shindig.some.emptyNamespace", {});
> shindig.some.emptyNamespace.xyz = "ABC";
>
> --Jesse
>
> >-----Original Message-----
> >From: John Hjelmstad [mailto:fargo@google.com]
> >Sent: Thursday, July 28, 2011 5:58 PM
> >To: dev@shindig.apache.org
> >Subject: Re: javascript readability..
> >
> >Hey Jesse,
> >
> >Interesting idea here -- this sounds suspiciously akin to the
> functionality
> >already present in exportJs(...) used for exporting symbols. This method
> >upserts the namespace in much the same way as your helper method does.
> >Thoughts on whether we could reuse or augment that?
> >
> >-j
> >
> >On Thu, Jul 28, 2011 at 7:52 AM, Ciancetta, Jesse E. <jcian@mitre.org
> >wrote:
> >
> >> I agree with John -- I also prefer the first style Paul presented (which
> I
> >> believe is also the most prevalent style in Shindig currently).
> >>
> >> With respect to the issues that Michael raised about building up a
> >> namespace from across different files -- this got me thinking about a
> little
> >> namespace utility a colleague of mine wrote a while back.  That utility
> just
> >> took a target namespace like "shindig.util.foo", created an empty object
> in
> >> it (without clobbering any parts of the target namespace that may have
> >> already existed) and returned it -- so you could then do something like
> >> shindig.util.foo.x = ... directly without needing to create each piece
> of
> >> the namespace manually.
> >>
> >> And with some (well, a lot) of tweaking I was able to turn that function
> >> into a more general purpose namespacing function that takes an optional
> >> object to place into the target namespace -- and if the target namespace
> >> already exists it takes the properties of the optional object and
> appends
> >> them to the existing namespace.
> >>
> >> So I think if enough people preferred the first style Paul presented,
> >> something like this could be used to work around the issues Michael
> raised.
> >>  Here is the function and some sample usages (with the caveat that I
> haven’t
> >> actually used this for anything real so there could be some bugs in it):
> >>
> >> var shindig = shindig || (function() {
> >>    var namespace = function(targetNamespace, optObject) {
> >>        //get a reference to the global window object
> >>        var object = window;
> >>
> >>        //if no object was provided to put into the namespace create an
> >> empty one
> >>        optObject = optObject || {};
> >>
> >>        //split the namespace into its parts
> >>        var namespaces = targetNamespace.split(".");
> >>
> >>        //for each part of the namespace
> >>        for (var i = 0; i < namespaces.length; i++) {
> >>            //see if this part is already defined
> >>            if (typeof object[namespaces[i]] === "undefined") {
> >>                //if its not defined already -- put an object into it
> >>                //if we're at the end of the targetNamespace, put the new
> >> object into it,
> >>                //otherwise drop in an empty object as a placeholder
> >>                object[namespaces[i]] = (i + 1) == namespaces.length ?
> >> optObject : {};
> >>            } else {
> >>                //there is already something here -- see if we're at the
> end
> >> of the targetNamespace
> >>                if ((i + 1) == namespaces.length) {
> >>                    //make sure its an object we can append to
> >>                    if (typeof object[namespaces[i]] === "object") {
> >>                        //go ahead and add all the public properties on
> >> optObject to the target namespace
> >>                        for (var property in optObject) {
> >>                            object[namespaces[i]][property] =
> >> optObject[property];
> >>                        }
> >>                    } else {
> >>                        throw "Cannot append new properties to object of
> >> type " + typeof object[namespaces[i]];
> >>                    }
> >>                }
> >>            }
> >>
> >>            object = object[namespaces[i]];
> >>        }
> >>
> >>        return object;
> >>    };
> >>
> >>    return {
> >>        namespace: namespace
> >>    };
> >> })();
> >>
> >> //could be from foo-utils.js
> >> shindig.namespace("shindig.util", (function() {
> >>    var privateData = "this is private";
> >>
> >>    var privateFunction = function() {
> >>        console.log(privateData);
> >>    };
> >>
> >>    var calculateFoo = function() {
> >>        privateFunction();
> >>    };
> >>
> >>    var doAlotOfFoo = function() {
> >>        //do alot of foo
> >>    };
> >>
> >>    return {
> >>        calculateFoo: calculateFoo,
> >>        doAlotOfFoo: doAlotOfFoo
> >>    };
> >> })());
> >>
> >> //could be from bar-utils.js
> >> shindig.namespace("shindig.util", (function() {
> >>    var privateFunction = function() {
> >>        console.log("calculateBar called");
> >>    };
> >>
> >>    var calculateBar = function() {
> >>        privateFunction();
> >>    };
> >>
> >>    return {
> >>        publicData: "this is public",
> >>        calculateBar: calculateBar
> >>    };
> >> })());
> >>
> >> shindig.namespace("shindig.some.emptyNamespace");
> >> shindig.some.emptyNamespace.xyz = "ABC";
> >>
> >> >-----Original Message-----
> >> >From: Michael Hermanto [mailto:mhermanto@gmail.com]
> >> >Sent: Tuesday, July 26, 2011 6:15 PM
> >> >To: dev@shindig.apache.org
> >> >Subject: Re: javascript readability..
> >> >
> >> >What didn't work for me with --
> >> >   shindig.foo = function() {
> >> >     return { 'bar': ... };
> >> >   }();
> >> >... is that methods in the same namespace have to be all
> >> >defined/implemented
> >> >in one file.
> >> >
> >> >ie: it's fine if all gadgets.rpc.* is implemented in a file rpc.js, but
> >> not
> >> >fine when gadgets.util.* are implemented across different
> files/features
> >> >across core.util.dom, core.util.string, etc. When feature core.util
> pulls
> >> >all these files in, it will effectively stomp all the
> previously-defined
> >> >core.util.*.
> >> >
> >> >The tendency has been to make libraries smaller and more focussed to
> >what
> >> >they do, ie: this means breaking up features into sub-features. To do
> so,
> >> I
> >> >had to convert more-focussed core.util.[dom|string|...] to
> fully-defined
> >> >names. Unless the above style (with shindig.foo) doesn't have this
> >> >limitation (ie: can incrementally define more methods on top what has
> >been
> >> >defined), I personally prefer the fully-defined names, for consistency.
> >> >
> >> >
> >> >
> >> >2011/7/26 ๏̯͡๏ Jasvir Nagra <ja...@google.com>
> >> >
> >> >> I don't have a strong preference either way although it's nice when
> >> >> reviewing code to have all the exported things exported once when
> they
> >> >> share
> >> >> a scope full of private helpers and other state.  It also helps
> convey
> >> when
> >> >> the setup of a particular part of the object graph is done.
> >> >> Eg.
> >> >>
> >> >> shindig.foo = (function() {
> >> >>  // ... all the helper functions and shared state ...
> >> >>  ...
> >> >>  return { bar: bar, baz: baz };
> >> >> }();
> >> >> // at this point I know from convention that shindig.foo is done
> being
> >> >> setup
> >> >> and will have just "bar" and "baz"
> >> >>
> >> >> vs.
> >> >>
> >> >> shindig.foo.bar = function() { ... }
> >> >> /// ... a lot of code later
> >> >> shindig.foo.baz = function() { ... }
> >> >>
> >> >> If the amount of code between shindig.foo and the return is long, I'd
> >> >> suggest another alternative that I think has the advantage of both:
> >> >>
> >> >> (function() {
> >> >>  // ... all the helper functions and shared state ...
> >> >>
> >> >>  shindig.foo = {
> >> >>    bar: bar,
> >> >>    baz: baz
> >> >>  }
> >> >> })();
> >> >>
> >> >> On Tue, Jul 26, 2011 at 2:19 PM, John Hjelmstad <fa...@google.com>
> >> >wrote:
> >> >>
> >> >> > With the model we're using with exportJs, you actually can't as
> easily
> >> do
> >> >> > that or wrap "singleton"/namespaced items, unless you .
> exportJs(...)
> >> is
> >> >> > injected after the closure.
> >> >> >
> >> >> > function() {
> >> >> >  foo.bar.baz = function() { }
> >> >> > }();
> >> >> > exportJs("foo.bar", [foo,foo.bar], {baz:"baz"});
> >> >> >
> >> >> > Of course, you can if you also update the style guide to prepend
> >> window:
> >> >> >
> >> >> > function() {
> >> >> >  window.foo.bar.baz = function() { }
> >> >> > }();
> >> >> >
> >> >> > ...though that requirement seems a little awkward and verbose to
> me.
> >> >> >
> >> >> > --j
> >> >> >
> >> >> > On Tue, Jul 26, 2011 at 2:12 PM, Dan Dumont <dd...@us.ibm.com>
> >> >wrote:
> >> >> >
> >> >> > > As mentioned by Paul before you can define:
> >> >> > >
> >> >> > > function(){
> >> >> > >   FooClass.prototype.method = function() { }
> >> >> > >  FooClass.prototype.method2 = function() { }
> >> >> > > }();
> >> >> > >
> >> >> > > to get a local scope.
> >> >> > >
> >> >> > > I think this makes it easier to audit what must be included in an
> >> >> export.
> >> >> > > And when you come up for air soon, maybe we can talk about AMD
> >> >format
> >> >> and
> >> >> > > what that brings to the table.  :)
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > From:   John Hjelmstad <fa...@google.com>
> >> >> > > To:     dev@shindig.apache.org,
> >> >> > > Date:   07/26/2011 04:43 PM
> >> >> > > Subject:        Re: javascript readability..
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > > I still prefer status quo, as it reads more like a proper class
> to
> >> me,
> >> >> > > while
> >> >> > > being less verbose and centralizing the exported method
> definitions
> >> in
> >> >> a
> >> >> > > single place.
> >> >> > >
> >> >> > > As well, this question's corollary is whether to convert all
> >> >> instantiable
> >> >> > > objects to the form:
> >> >> > >
> >> >> > > FooClass.prototype.method = function() { }
> >> >> > > FooClass.prototype.method2 = function() { }
> >> >> > >
> >> >> > > ...from:
> >> >> > > FooClass = function() {
> >> >> > >  // private state
> >> >> > >  function method() { }
> >> >> > >  function method2() { }
> >> >> > >  return {
> >> >> > >    method: method,
> >> >> > >    method2: method2
> >> >> > >  };
> >> >> > > };
> >> >> > >
> >> >> > > On this note, I'm conflicted. I like having actual private state,
> >> but
> >> >> > > prototype-style is more efficient.
> >> >> > >
> >> >> > > Enough people have complained over time about each of the
> existing
> >> >> idioms
> >> >> > > though that I suppose I could go the other direction, if it's
> >> causing
> >> >> > > development trouble.
> >> >> > >
> >> >> > > --j
> >> >> > >
> >> >> > > On Tue, Jul 26, 2011 at 6:17 AM, Ryan J Baxter <
> rjbaxter@us.ibm.com
> >> >
> >> >> > > wrote:
> >> >> > >
> >> >> > > > +1 As well, I think its easier to read.
> >> >> > > >
> >> >> > > > -Ryan
> >> >> > > >
> >> >> > > > Email: rjbaxter@us.ibm.com
> >> >> > > > Phone: 978-899-3041
> >> >> > > > developerWorks Profile
> >> >> > > >
> >> >> > > >
> >> >> > > >
> >> >> > > > From:   Dan Dumont/Westford/IBM@Lotus
> >> >> > > > To:     dev@shindig.apache.org,
> >> >> > > > Date:   07/26/2011 09:00 AM
> >> >> > > > Subject:        Re: javascript readability..
> >> >> > > >
> >> >> > > >
> >> >> > > >
> >> >> > > > +1
> >> >> > > >
> >> >> > > >
> >> >> > > >
> >> >> > > > From:   Paul Lindner <li...@inuus.com>
> >> >> > > > To:     dev@shindig.apache.org,
> >> >> > > > Date:   07/26/2011 02:51 AM
> >> >> > > > Subject:        javascript readability..
> >> >> > > >
> >> >> > > >
> >> >> > > >
> >> >> > > > Hi,
> >> >> > > >
> >> >> > > > I'm curious to know what people think about some of the idioms
> in
> >> the
> >> >> > JS
> >> >> > > > code you find in shindig.  There's an awful lot of stuff like
> >> this:
> >> >> > > >
> >> >> > > > shindig.foo = function(){
> >> >> > > >  //...
> >> >> > > >  var myFunction = function() {
> >> >> > > >     }
> >> >> > > >
> >> >> > > >  return {'foo': myFunction,
> >> >> > > >            'bar': function() {
> >> >> > > >               return 'bar';
> >> >> > > >            }};
> >> >> > > > }();
> >> >> > > >
> >> >> > > >
> >> >> > > > Just search for @member to see the various places.
> >> >> > > >
> >> >> > > > What would people think if we moved to fully defined names for
> >> >> > > > function/method definitions instead?
> >> >> > > >
> >> >> > > > You could still wrap this inside a closure if you wanted local
> >> scope:
> >> >> > > >
> >> >> > > > function() {
> >> >> > > >  shindig.foo.foo = function() {
> >> >> > > >     ...
> >> >> > > >  }
> >> >> > > >  shindig.foo.bar = function() {
> >> >> > > >     ...
> >> >> > > >  }
> >> >> > > > }();
> >> >> > > >
> >> >> > > > --
> >> >> > > > Paul Lindner -- lindner@inuus.com -- linkedin.com/in/plindner
> >> >> > > >
> >> >> > > >
> >> >> > > >
> >> >> > > >
> >> >> > > >
> >> >> > > >
> >> >> > > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> > >
> >> >> >
> >> >>
> >>
>

Re: javascript readability..

Posted by Phillip Rhodes <mo...@gmail.com>.
On Tue, Aug 2, 2011 at 1:46 AM, Craig McClanahan <cr...@gmail.com> wrote:
> Yes, I understand all about rapidly evolving code,
> but I'd be happy with enough documentation that magicians (not even
> necessarily mere mortals) that haven't memorized the codebase might get an
> idea what is possible already :-).  Can I sweet talk you guys into at least
> a few blog entries about this cool stuff?  :-)


+1 from another Shindig n00b.  :-)



Cheers,


Phil

Re: javascript readability..

Posted by Craig McClanahan <cr...@gmail.com>.
This is a comment from the peanut gallery at the moment, but as I get more
and more in to the Shindig code base, I discover more and more "hidden gems"
like this that are totally invisible to someone not intimately familiar with
the Shindig codebase.  Yes, I understand all about rapidly evolving code,
but I'd be happy with enough documentation that magicians (not even
necessarily mere mortals) that haven't memorized the codebase might get an
idea what is possible already :-).  Can I sweet talk you guys into at least
a few blog entries about this cool stuff?  :-)

Craig McClanahan


On Mon, Aug 1, 2011 at 6:15 PM, Ryan J Baxter <rj...@us.ibm.com> wrote:

> +1, once the feature is ready of course.
>
> -Ryan
>
> Email: rjbaxter@us.ibm.com
> Phone: 978-899-3041
> developerWorks Profile
>
>
>
> From:   Henry Saputra <he...@gmail.com>
> To:     dev@shindig.apache.org,
> Date:   08/01/2011 09:13 PM
> Subject:        Re: javascript readability..
>
>
>
> I think a wiki entry for this exportJs feature would greatly help
> Shindig community to understand more about design and the impl chosen.
>
> - Henry
>
> On Mon, Aug 1, 2011 at 5:54 PM, John Hjelmstad <fa...@google.com> wrote:
> > Hey Jesse:
> >
> > We haven't loudly advertised exportJs() yet since we've been adding a
> final
> > piece of functionality to it for deferred symbol binding, and because
> > Shindig (on account of it being still by default on JDK 1.5 if nothing
> else)
> > doesn't use closure compiled JS by default yet.
> >
> > For context, deferred symbol binding applies to features consisting of
> > methods that return nothing synchronously. Synthetic example:
> >
> > // namespace setup here
> > gadgets.foo.doSomething = function(key, value, callback) {
> >  // do something with key and value
> >  callback(somethingComputed);
> > };
> >
> > Deferred symbol binding allows us to emit a tiny JS loader "stub" that
> just
> > enqueues arguments to a method with this name. That stub -- actually the
> > async JS loader -- then loads the payload, which when loaded executes
> the
> > real method.
> >
> > This allows fast integration of code via:
> > <script src="http://myserver.com/gadgets/js/foofeature.js"></script>
> > <script>
> >  gadgets.foo.doSomething('myKey', 'myValue', function(data) { /*
> myCallback
> > */ });
> > </script>
> >
> > ...for syntactic convenience while maintaining asynchronous loading
> > semantics for latency purposes (ie. not blocking the page load).
> >
> > The functionality overall is activated by the flag supportDefer="true"
> in
> > feature.xml, and server-side configuration for same. Without it, the
> above
> > syntax is not activated and things work as before.
> >
> > I implemented a version of this with both deferred and full symbol
> binding
> > in exportJs() but found a few shortcomings with the approach. we're
> > rejiggering it today. I'd hold off for a short time while we do so to
> avoid
> > merge conflicts. The relevant JS CL is:
> https://reviews.apache.org/r/1237/
> >
> > Cheers,
> > John
> > PS. Time will tell whether I regret it, but thanks for the props on the
> > method overall :) It's hard to measure precisely how valuable the
> technique
> > is since much of its value is preventative, ie. A) disallowing use of
> helper
> > methods as if they were supported APIs, and B) prevents symbol
> > clashes/occlusion with arbitrary contexts in which "our" JS is imported
> --
> > hopefully all while allowing a coding style that "feels" as if none of
> this
> > edifice exists.
> >
> > On Fri, Jul 29, 2011 at 7:09 AM, Ciancetta, Jesse E.
> <jc...@mitre.org>wrote:
> >
> >> Hey John,
> >>
> >> I hadn’t seen the exportJs support before (I haven’t done any work with
> >> features in a long time) -- that does look very similar!  (and as an
> aside
> >> -- hats off to whoever came up with that scheme to be able to closure
> >> compile JS in isolation but still have fully qualified symbols
> available in
> >> the global space -- its absolutely brilliant)
> >>
> >> I wrote a quick test gadget which required feature exportjs and did
> some
> >> testing -- and it comes pretty close to doing everything we'd need
> already,
> >> so I don’t see any reason why it couldn’t be augmented to handle all
> the
> >> cases my helper function does.  Then it'd just be a matter of making it
> part
> >> of the core feature set so it would be available for use in any
> features
> >> that wanted to take advantage of it.
> >>
> >> So I guess that comes back to Paul's original question though -- if
> enough
> >> people preferred the first style Paul proposed I'd be happy to take a
> crack
> >> at augmenting exportJs to support this use case.  So we'd end up with
> JS
> >> that looked something like this:
> >>
> >> //could be from foo-utils.js
> >> exportJs("shindig.util", (function() {
> >>     var privateData = "this is private";
> >>
> >>    var privateFunction = function() {
> >>        console.log(privateData);
> >>    };
> >>
> >>    var calculateFoo = function() {
> >>        privateFunction();
> >>    };
> >>
> >>    var doAlotOfFoo = function() {
> >>        //do alot of foo
> >>    };
> >>
> >>    return {
> >>        calculateFoo: calculateFoo,
> >>        doAlotOfFoo: doAlotOfFoo
> >>    };
> >> })());
> >>
> >> //could be from bar-utils.js
> >> exportJs("shindig.util", (function() {
> >>     var privateFunction = function() {
> >>        console.log("calculateBar called");
> >>    };
> >>
> >>    var calculateBar = function() {
> >>        privateFunction();
> >>    };
> >>
> >>    return {
> >>        publicData: "this is public",
> >>        calculateBar: calculateBar
> >>    };
> >> })());
> >>
> >> exportJs("shindig.some.emptyNamespace", {});
> >> shindig.some.emptyNamespace.xyz = "ABC";
> >>
> >> --Jesse
> >>
> >> >-----Original Message-----
> >> >From: John Hjelmstad [mailto:fargo@google.com]
> >> >Sent: Thursday, July 28, 2011 5:58 PM
> >> >To: dev@shindig.apache.org
> >> >Subject: Re: javascript readability..
> >> >
> >> >Hey Jesse,
> >> >
> >> >Interesting idea here -- this sounds suspiciously akin to the
> >> functionality
> >> >already present in exportJs(...) used for exporting symbols. This
> method
> >> >upserts the namespace in much the same way as your helper method does.
> >> >Thoughts on whether we could reuse or augment that?
> >> >
> >> >-j
> >> >
> >> >On Thu, Jul 28, 2011 at 7:52 AM, Ciancetta, Jesse E. <jcian@mitre.org
> >> >wrote:
> >> >
> >> >> I agree with John -- I also prefer the first style Paul presented
> (which
> >> I
> >> >> believe is also the most prevalent style in Shindig currently).
> >> >>
> >> >> With respect to the issues that Michael raised about building up a
> >> >> namespace from across different files -- this got me thinking about
> a
> >> little
> >> >> namespace utility a colleague of mine wrote a while back.  That
> utility
> >> just
> >> >> took a target namespace like "shindig.util.foo", created an empty
> object
> >> in
> >> >> it (without clobbering any parts of the target namespace that may
> have
> >> >> already existed) and returned it -- so you could then do something
> like
> >> >> shindig.util.foo.x = ... directly without needing to create each
> piece
> >> of
> >> >> the namespace manually.
> >> >>
> >> >> And with some (well, a lot) of tweaking I was able to turn that
> function
> >> >> into a more general purpose namespacing function that takes an
> optional
> >> >> object to place into the target namespace -- and if the target
> namespace
> >> >> already exists it takes the properties of the optional object and
> >> appends
> >> >> them to the existing namespace.
> >> >>
> >> >> So I think if enough people preferred the first style Paul
> presented,
> >> >> something like this could be used to work around the issues Michael
> >> raised.
> >> >>  Here is the function and some sample usages (with the caveat that I
> >> haven’t
> >> >> actually used this for anything real so there could be some bugs in
> it):
> >> >>
> >> >> var shindig = shindig || (function() {
> >> >>    var namespace = function(targetNamespace, optObject) {
> >> >>        //get a reference to the global window object
> >> >>        var object = window;
> >> >>
> >> >>        //if no object was provided to put into the namespace create
> an
> >> >> empty one
> >> >>        optObject = optObject || {};
> >> >>
> >> >>        //split the namespace into its parts
> >> >>        var namespaces = targetNamespace.split(".");
> >> >>
> >> >>        //for each part of the namespace
> >> >>        for (var i = 0; i < namespaces.length; i++) {
> >> >>            //see if this part is already defined
> >> >>            if (typeof object[namespaces[i]] === "undefined") {
> >> >>                //if its not defined already -- put an object into it
> >> >>                //if we're at the end of the targetNamespace, put the
> new
> >> >> object into it,
> >> >>                //otherwise drop in an empty object as a placeholder
> >> >>                object[namespaces[i]] = (i + 1) == namespaces.length
> ?
> >> >> optObject : {};
> >> >>            } else {
> >> >>                //there is already something here -- see if we're at
> the
> >> end
> >> >> of the targetNamespace
> >> >>                if ((i + 1) == namespaces.length) {
> >> >>                    //make sure its an object we can append to
> >> >>                    if (typeof object[namespaces[i]] === "object") {
> >> >>                        //go ahead and add all the public properties
> on
> >> >> optObject to the target namespace
> >> >>                        for (var property in optObject) {
> >> >>                            object[namespaces[i]][property] =
> >> >> optObject[property];
> >> >>                        }
> >> >>                    } else {
> >> >>                        throw "Cannot append new properties to object
> of
> >> >> type " + typeof object[namespaces[i]];
> >> >>                    }
> >> >>                }
> >> >>            }
> >> >>
> >> >>            object = object[namespaces[i]];
> >> >>        }
> >> >>
> >> >>        return object;
> >> >>    };
> >> >>
> >> >>    return {
> >> >>        namespace: namespace
> >> >>    };
> >> >> })();
> >> >>
> >> >> //could be from foo-utils.js
> >> >> shindig.namespace("shindig.util", (function() {
> >> >>    var privateData = "this is private";
> >> >>
> >> >>    var privateFunction = function() {
> >> >>        console.log(privateData);
> >> >>    };
> >> >>
> >> >>    var calculateFoo = function() {
> >> >>        privateFunction();
> >> >>    };
> >> >>
> >> >>    var doAlotOfFoo = function() {
> >> >>        //do alot of foo
> >> >>    };
> >> >>
> >> >>    return {
> >> >>        calculateFoo: calculateFoo,
> >> >>        doAlotOfFoo: doAlotOfFoo
> >> >>    };
> >> >> })());
> >> >>
> >> >> //could be from bar-utils.js
> >> >> shindig.namespace("shindig.util", (function() {
> >> >>    var privateFunction = function() {
> >> >>        console.log("calculateBar called");
> >> >>    };
> >> >>
> >> >>    var calculateBar = function() {
> >> >>        privateFunction();
> >> >>    };
> >> >>
> >> >>    return {
> >> >>        publicData: "this is public",
> >> >>        calculateBar: calculateBar
> >> >>    };
> >> >> })());
> >> >>
> >> >> shindig.namespace("shindig.some.emptyNamespace");
> >> >> shindig.some.emptyNamespace.xyz = "ABC";
> >> >>
> >> >> >-----Original Message-----
> >> >> >From: Michael Hermanto [mailto:mhermanto@gmail.com]
> >> >> >Sent: Tuesday, July 26, 2011 6:15 PM
> >> >> >To: dev@shindig.apache.org
> >> >> >Subject: Re: javascript readability..
> >> >> >
> >> >> >What didn't work for me with --
> >> >> >   shindig.foo = function() {
> >> >> >     return { 'bar': ... };
> >> >> >   }();
> >> >> >... is that methods in the same namespace have to be all
> >> >> >defined/implemented
> >> >> >in one file.
> >> >> >
> >> >> >ie: it's fine if all gadgets.rpc.* is implemented in a file rpc.js,
> but
> >> >> not
> >> >> >fine when gadgets.util.* are implemented across different
> >> files/features
> >> >> >across core.util.dom, core.util.string, etc. When feature core.util
> >> pulls
> >> >> >all these files in, it will effectively stomp all the
> >> previously-defined
> >> >> >core.util.*.
> >> >> >
> >> >> >The tendency has been to make libraries smaller and more focussed
> to
> >> >what
> >> >> >they do, ie: this means breaking up features into sub-features. To
> do
> >> so,
> >> >> I
> >> >> >had to convert more-focussed core.util.[dom|string|...] to
> >> fully-defined
> >> >> >names. Unless the above style (with shindig.foo) doesn't have this
> >> >> >limitation (ie: can incrementally define more methods on top what
> has
> >> >been
> >> >> >defined), I personally prefer the fully-defined names, for
> consistency.
> >> >> >
> >> >> >
> >> >> >
> >> >> >2011/7/26 ๏̯͡๏ Jasvir Nagra <ja...@google.com>
> >> >> >
> >> >> >> I don't have a strong preference either way although it's nice
> when
> >> >> >> reviewing code to have all the exported things exported once when
> >> they
> >> >> >> share
> >> >> >> a scope full of private helpers and other state.  It also helps
> >> convey
> >> >> when
> >> >> >> the setup of a particular part of the object graph is done.
> >> >> >> Eg.
> >> >> >>
> >> >> >> shindig.foo = (function() {
> >> >> >>  // ... all the helper functions and shared state ...
> >> >> >>  ...
> >> >> >>  return { bar: bar, baz: baz };
> >> >> >> }();
> >> >> >> // at this point I know from convention that shindig.foo is done
> >> being
> >> >> >> setup
> >> >> >> and will have just "bar" and "baz"
> >> >> >>
> >> >> >> vs.
> >> >> >>
> >> >> >> shindig.foo.bar = function() { ... }
> >> >> >> /// ... a lot of code later
> >> >> >> shindig.foo.baz = function() { ... }
> >> >> >>
> >> >> >> If the amount of code between shindig.foo and the return is long,
> I'd
> >> >> >> suggest another alternative that I think has the advantage of
> both:
> >> >> >>
> >> >> >> (function() {
> >> >> >>  // ... all the helper functions and shared state ...
> >> >> >>
> >> >> >>  shindig.foo = {
> >> >> >>    bar: bar,
> >> >> >>    baz: baz
> >> >> >>  }
> >> >> >> })();
> >> >> >>
> >> >> >> On Tue, Jul 26, 2011 at 2:19 PM, John Hjelmstad
> <fa...@google.com>
> >> >> >wrote:
> >> >> >>
> >> >> >> > With the model we're using with exportJs, you actually can't as
> >> easily
> >> >> do
> >> >> >> > that or wrap "singleton"/namespaced items, unless you .
> >> exportJs(...)
> >> >> is
> >> >> >> > injected after the closure.
> >> >> >> >
> >> >> >> > function() {
> >> >> >> >  foo.bar.baz = function() { }
> >> >> >> > }();
> >> >> >> > exportJs("foo.bar", [foo,foo.bar], {baz:"baz"});
> >> >> >> >
> >> >> >> > Of course, you can if you also update the style guide to
> prepend
> >> >> window:
> >> >> >> >
> >> >> >> > function() {
> >> >> >> >  window.foo.bar.baz = function() { }
> >> >> >> > }();
> >> >> >> >
> >> >> >> > ...though that requirement seems a little awkward and verbose
> to
> >> me.
> >> >> >> >
> >> >> >> > --j
> >> >> >> >
> >> >> >> > On Tue, Jul 26, 2011 at 2:12 PM, Dan Dumont
> <dd...@us.ibm.com>
> >> >> >wrote:
> >> >> >> >
> >> >> >> > > As mentioned by Paul before you can define:
> >> >> >> > >
> >> >> >> > > function(){
> >> >> >> > >   FooClass.prototype.method = function() { }
> >> >> >> > >  FooClass.prototype.method2 = function() { }
> >> >> >> > > }();
> >> >> >> > >
> >> >> >> > > to get a local scope.
> >> >> >> > >
> >> >> >> > > I think this makes it easier to audit what must be included
> in an
> >> >> >> export.
> >> >> >> > > And when you come up for air soon, maybe we can talk about
> AMD
> >> >> >format
> >> >> >> and
> >> >> >> > > what that brings to the table.  :)
> >> >> >> > >
> >> >> >> > >
> >> >> >> > >
> >> >> >> > > From:   John Hjelmstad <fa...@google.com>
> >> >> >> > > To:     dev@shindig.apache.org,
> >> >> >> > > Date:   07/26/2011 04:43 PM
> >> >> >> > > Subject:        Re: javascript readability..
> >> >> >> > >
> >> >> >> > >
> >> >> >> > >
> >> >> >> > > I still prefer status quo, as it reads more like a proper
> class
> >> to
> >> >> me,
> >> >> >> > > while
> >> >> >> > > being less verbose and centralizing the exported method
> >> definitions
> >> >> in
> >> >> >> a
> >> >> >> > > single place.
> >> >> >> > >
> >> >> >> > > As well, this question's corollary is whether to convert all
> >> >> >> instantiable
> >> >> >> > > objects to the form:
> >> >> >> > >
> >> >> >> > > FooClass.prototype.method = function() { }
> >> >> >> > > FooClass.prototype.method2 = function() { }
> >> >> >> > >
> >> >> >> > > ...from:
> >> >> >> > > FooClass = function() {
> >> >> >> > >  // private state
> >> >> >> > >  function method() { }
> >> >> >> > >  function method2() { }
> >> >> >> > >  return {
> >> >> >> > >    method: method,
> >> >> >> > >    method2: method2
> >> >> >> > >  };
> >> >> >> > > };
> >> >> >> > >
> >> >> >> > > On this note, I'm conflicted. I like having actual private
> state,
> >> >> but
> >> >> >> > > prototype-style is more efficient.
> >> >> >> > >
> >> >> >> > > Enough people have complained over time about each of the
> >> existing
> >> >> >> idioms
> >> >> >> > > though that I suppose I could go the other direction, if it's
> >> >> causing
> >> >> >> > > development trouble.
> >> >> >> > >
> >> >> >> > > --j
> >> >> >> > >
> >> >> >> > > On Tue, Jul 26, 2011 at 6:17 AM, Ryan J Baxter <
> >> rjbaxter@us.ibm.com
> >> >> >
> >> >> >> > > wrote:
> >> >> >> > >
> >> >> >> > > > +1 As well, I think its easier to read.
> >> >> >> > > >
> >> >> >> > > > -Ryan
> >> >> >> > > >
> >> >> >> > > > Email: rjbaxter@us.ibm.com
> >> >> >> > > > Phone: 978-899-3041
> >> >> >> > > > developerWorks Profile
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > > From:   Dan Dumont/Westford/IBM@Lotus
> >> >> >> > > > To:     dev@shindig.apache.org,
> >> >> >> > > > Date:   07/26/2011 09:00 AM
> >> >> >> > > > Subject:        Re: javascript readability..
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > > +1
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > > From:   Paul Lindner <li...@inuus.com>
> >> >> >> > > > To:     dev@shindig.apache.org,
> >> >> >> > > > Date:   07/26/2011 02:51 AM
> >> >> >> > > > Subject:        javascript readability..
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > > Hi,
> >> >> >> > > >
> >> >> >> > > > I'm curious to know what people think about some of the
> idioms
> >> in
> >> >> the
> >> >> >> > JS
> >> >> >> > > > code you find in shindig.  There's an awful lot of stuff
> like
> >> >> this:
> >> >> >> > > >
> >> >> >> > > > shindig.foo = function(){
> >> >> >> > > >  //...
> >> >> >> > > >  var myFunction = function() {
> >> >> >> > > >     }
> >> >> >> > > >
> >> >> >> > > >  return {'foo': myFunction,
> >> >> >> > > >            'bar': function() {
> >> >> >> > > >               return 'bar';
> >> >> >> > > >            }};
> >> >> >> > > > }();
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > > Just search for @member to see the various places.
> >> >> >> > > >
> >> >> >> > > > What would people think if we moved to fully defined names
> for
> >> >> >> > > > function/method definitions instead?
> >> >> >> > > >
> >> >> >> > > > You could still wrap this inside a closure if you wanted
> local
> >> >> scope:
> >> >> >> > > >
> >> >> >> > > > function() {
> >> >> >> > > >  shindig.foo.foo = function() {
> >> >> >> > > >     ...
> >> >> >> > > >  }
> >> >> >> > > >  shindig.foo.bar = function() {
> >> >> >> > > >     ...
> >> >> >> > > >  }
> >> >> >> > > > }();
> >> >> >> > > >
> >> >> >> > > > --
> >> >> >> > > > Paul Lindner -- lindner@inuus.com --
> linkedin.com/in/plindner
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > > >
> >> >> >> > >
> >> >> >> > >
> >> >> >> > >
> >> >> >> > >
> >> >> >> >
> >> >> >>
> >> >>
> >>
> >
>
>
>
>
>

Re: javascript readability..

Posted by Ryan J Baxter <rj...@us.ibm.com>.
+1, once the feature is ready of course.

-Ryan

Email: rjbaxter@us.ibm.com
Phone: 978-899-3041
developerWorks Profile



From:   Henry Saputra <he...@gmail.com>
To:     dev@shindig.apache.org, 
Date:   08/01/2011 09:13 PM
Subject:        Re: javascript readability..



I think a wiki entry for this exportJs feature would greatly help
Shindig community to understand more about design and the impl chosen.

- Henry

On Mon, Aug 1, 2011 at 5:54 PM, John Hjelmstad <fa...@google.com> wrote:
> Hey Jesse:
>
> We haven't loudly advertised exportJs() yet since we've been adding a 
final
> piece of functionality to it for deferred symbol binding, and because
> Shindig (on account of it being still by default on JDK 1.5 if nothing 
else)
> doesn't use closure compiled JS by default yet.
>
> For context, deferred symbol binding applies to features consisting of
> methods that return nothing synchronously. Synthetic example:
>
> // namespace setup here
> gadgets.foo.doSomething = function(key, value, callback) {
>  // do something with key and value
>  callback(somethingComputed);
> };
>
> Deferred symbol binding allows us to emit a tiny JS loader "stub" that 
just
> enqueues arguments to a method with this name. That stub -- actually the
> async JS loader -- then loads the payload, which when loaded executes 
the
> real method.
>
> This allows fast integration of code via:
> <script src="http://myserver.com/gadgets/js/foofeature.js"></script>
> <script>
>  gadgets.foo.doSomething('myKey', 'myValue', function(data) { /* 
myCallback
> */ });
> </script>
>
> ...for syntactic convenience while maintaining asynchronous loading
> semantics for latency purposes (ie. not blocking the page load).
>
> The functionality overall is activated by the flag supportDefer="true" 
in
> feature.xml, and server-side configuration for same. Without it, the 
above
> syntax is not activated and things work as before.
>
> I implemented a version of this with both deferred and full symbol 
binding
> in exportJs() but found a few shortcomings with the approach. we're
> rejiggering it today. I'd hold off for a short time while we do so to 
avoid
> merge conflicts. The relevant JS CL is: 
https://reviews.apache.org/r/1237/
>
> Cheers,
> John
> PS. Time will tell whether I regret it, but thanks for the props on the
> method overall :) It's hard to measure precisely how valuable the 
technique
> is since much of its value is preventative, ie. A) disallowing use of 
helper
> methods as if they were supported APIs, and B) prevents symbol
> clashes/occlusion with arbitrary contexts in which "our" JS is imported 
--
> hopefully all while allowing a coding style that "feels" as if none of 
this
> edifice exists.
>
> On Fri, Jul 29, 2011 at 7:09 AM, Ciancetta, Jesse E. 
<jc...@mitre.org>wrote:
>
>> Hey John,
>>
>> I hadn’t seen the exportJs support before (I haven’t done any work with
>> features in a long time) -- that does look very similar!  (and as an 
aside
>> -- hats off to whoever came up with that scheme to be able to closure
>> compile JS in isolation but still have fully qualified symbols 
available in
>> the global space -- its absolutely brilliant)
>>
>> I wrote a quick test gadget which required feature exportjs and did 
some
>> testing -- and it comes pretty close to doing everything we'd need 
already,
>> so I don’t see any reason why it couldn’t be augmented to handle all 
the
>> cases my helper function does.  Then it'd just be a matter of making it 
part
>> of the core feature set so it would be available for use in any 
features
>> that wanted to take advantage of it.
>>
>> So I guess that comes back to Paul's original question though -- if 
enough
>> people preferred the first style Paul proposed I'd be happy to take a 
crack
>> at augmenting exportJs to support this use case.  So we'd end up with 
JS
>> that looked something like this:
>>
>> //could be from foo-utils.js
>> exportJs("shindig.util", (function() {
>>     var privateData = "this is private";
>>
>>    var privateFunction = function() {
>>        console.log(privateData);
>>    };
>>
>>    var calculateFoo = function() {
>>        privateFunction();
>>    };
>>
>>    var doAlotOfFoo = function() {
>>        //do alot of foo
>>    };
>>
>>    return {
>>        calculateFoo: calculateFoo,
>>        doAlotOfFoo: doAlotOfFoo
>>    };
>> })());
>>
>> //could be from bar-utils.js
>> exportJs("shindig.util", (function() {
>>     var privateFunction = function() {
>>        console.log("calculateBar called");
>>    };
>>
>>    var calculateBar = function() {
>>        privateFunction();
>>    };
>>
>>    return {
>>        publicData: "this is public",
>>        calculateBar: calculateBar
>>    };
>> })());
>>
>> exportJs("shindig.some.emptyNamespace", {});
>> shindig.some.emptyNamespace.xyz = "ABC";
>>
>> --Jesse
>>
>> >-----Original Message-----
>> >From: John Hjelmstad [mailto:fargo@google.com]
>> >Sent: Thursday, July 28, 2011 5:58 PM
>> >To: dev@shindig.apache.org
>> >Subject: Re: javascript readability..
>> >
>> >Hey Jesse,
>> >
>> >Interesting idea here -- this sounds suspiciously akin to the
>> functionality
>> >already present in exportJs(...) used for exporting symbols. This 
method
>> >upserts the namespace in much the same way as your helper method does.
>> >Thoughts on whether we could reuse or augment that?
>> >
>> >-j
>> >
>> >On Thu, Jul 28, 2011 at 7:52 AM, Ciancetta, Jesse E. <jcian@mitre.org
>> >wrote:
>> >
>> >> I agree with John -- I also prefer the first style Paul presented 
(which
>> I
>> >> believe is also the most prevalent style in Shindig currently).
>> >>
>> >> With respect to the issues that Michael raised about building up a
>> >> namespace from across different files -- this got me thinking about 
a
>> little
>> >> namespace utility a colleague of mine wrote a while back.  That 
utility
>> just
>> >> took a target namespace like "shindig.util.foo", created an empty 
object
>> in
>> >> it (without clobbering any parts of the target namespace that may 
have
>> >> already existed) and returned it -- so you could then do something 
like
>> >> shindig.util.foo.x = ... directly without needing to create each 
piece
>> of
>> >> the namespace manually.
>> >>
>> >> And with some (well, a lot) of tweaking I was able to turn that 
function
>> >> into a more general purpose namespacing function that takes an 
optional
>> >> object to place into the target namespace -- and if the target 
namespace
>> >> already exists it takes the properties of the optional object and
>> appends
>> >> them to the existing namespace.
>> >>
>> >> So I think if enough people preferred the first style Paul 
presented,
>> >> something like this could be used to work around the issues Michael
>> raised.
>> >>  Here is the function and some sample usages (with the caveat that I
>> haven’t
>> >> actually used this for anything real so there could be some bugs in 
it):
>> >>
>> >> var shindig = shindig || (function() {
>> >>    var namespace = function(targetNamespace, optObject) {
>> >>        //get a reference to the global window object
>> >>        var object = window;
>> >>
>> >>        //if no object was provided to put into the namespace create 
an
>> >> empty one
>> >>        optObject = optObject || {};
>> >>
>> >>        //split the namespace into its parts
>> >>        var namespaces = targetNamespace.split(".");
>> >>
>> >>        //for each part of the namespace
>> >>        for (var i = 0; i < namespaces.length; i++) {
>> >>            //see if this part is already defined
>> >>            if (typeof object[namespaces[i]] === "undefined") {
>> >>                //if its not defined already -- put an object into it
>> >>                //if we're at the end of the targetNamespace, put the 
new
>> >> object into it,
>> >>                //otherwise drop in an empty object as a placeholder
>> >>                object[namespaces[i]] = (i + 1) == namespaces.length 
?
>> >> optObject : {};
>> >>            } else {
>> >>                //there is already something here -- see if we're at 
the
>> end
>> >> of the targetNamespace
>> >>                if ((i + 1) == namespaces.length) {
>> >>                    //make sure its an object we can append to
>> >>                    if (typeof object[namespaces[i]] === "object") {
>> >>                        //go ahead and add all the public properties 
on
>> >> optObject to the target namespace
>> >>                        for (var property in optObject) {
>> >>                            object[namespaces[i]][property] =
>> >> optObject[property];
>> >>                        }
>> >>                    } else {
>> >>                        throw "Cannot append new properties to object 
of
>> >> type " + typeof object[namespaces[i]];
>> >>                    }
>> >>                }
>> >>            }
>> >>
>> >>            object = object[namespaces[i]];
>> >>        }
>> >>
>> >>        return object;
>> >>    };
>> >>
>> >>    return {
>> >>        namespace: namespace
>> >>    };
>> >> })();
>> >>
>> >> //could be from foo-utils.js
>> >> shindig.namespace("shindig.util", (function() {
>> >>    var privateData = "this is private";
>> >>
>> >>    var privateFunction = function() {
>> >>        console.log(privateData);
>> >>    };
>> >>
>> >>    var calculateFoo = function() {
>> >>        privateFunction();
>> >>    };
>> >>
>> >>    var doAlotOfFoo = function() {
>> >>        //do alot of foo
>> >>    };
>> >>
>> >>    return {
>> >>        calculateFoo: calculateFoo,
>> >>        doAlotOfFoo: doAlotOfFoo
>> >>    };
>> >> })());
>> >>
>> >> //could be from bar-utils.js
>> >> shindig.namespace("shindig.util", (function() {
>> >>    var privateFunction = function() {
>> >>        console.log("calculateBar called");
>> >>    };
>> >>
>> >>    var calculateBar = function() {
>> >>        privateFunction();
>> >>    };
>> >>
>> >>    return {
>> >>        publicData: "this is public",
>> >>        calculateBar: calculateBar
>> >>    };
>> >> })());
>> >>
>> >> shindig.namespace("shindig.some.emptyNamespace");
>> >> shindig.some.emptyNamespace.xyz = "ABC";
>> >>
>> >> >-----Original Message-----
>> >> >From: Michael Hermanto [mailto:mhermanto@gmail.com]
>> >> >Sent: Tuesday, July 26, 2011 6:15 PM
>> >> >To: dev@shindig.apache.org
>> >> >Subject: Re: javascript readability..
>> >> >
>> >> >What didn't work for me with --
>> >> >   shindig.foo = function() {
>> >> >     return { 'bar': ... };
>> >> >   }();
>> >> >... is that methods in the same namespace have to be all
>> >> >defined/implemented
>> >> >in one file.
>> >> >
>> >> >ie: it's fine if all gadgets.rpc.* is implemented in a file rpc.js, 
but
>> >> not
>> >> >fine when gadgets.util.* are implemented across different
>> files/features
>> >> >across core.util.dom, core.util.string, etc. When feature core.util
>> pulls
>> >> >all these files in, it will effectively stomp all the
>> previously-defined
>> >> >core.util.*.
>> >> >
>> >> >The tendency has been to make libraries smaller and more focussed 
to
>> >what
>> >> >they do, ie: this means breaking up features into sub-features. To 
do
>> so,
>> >> I
>> >> >had to convert more-focussed core.util.[dom|string|...] to
>> fully-defined
>> >> >names. Unless the above style (with shindig.foo) doesn't have this
>> >> >limitation (ie: can incrementally define more methods on top what 
has
>> >been
>> >> >defined), I personally prefer the fully-defined names, for 
consistency.
>> >> >
>> >> >
>> >> >
>> >> >2011/7/26 ๏̯͡๏ Jasvir Nagra <ja...@google.com>
>> >> >
>> >> >> I don't have a strong preference either way although it's nice 
when
>> >> >> reviewing code to have all the exported things exported once when
>> they
>> >> >> share
>> >> >> a scope full of private helpers and other state.  It also helps
>> convey
>> >> when
>> >> >> the setup of a particular part of the object graph is done.
>> >> >> Eg.
>> >> >>
>> >> >> shindig.foo = (function() {
>> >> >>  // ... all the helper functions and shared state ...
>> >> >>  ...
>> >> >>  return { bar: bar, baz: baz };
>> >> >> }();
>> >> >> // at this point I know from convention that shindig.foo is done
>> being
>> >> >> setup
>> >> >> and will have just "bar" and "baz"
>> >> >>
>> >> >> vs.
>> >> >>
>> >> >> shindig.foo.bar = function() { ... }
>> >> >> /// ... a lot of code later
>> >> >> shindig.foo.baz = function() { ... }
>> >> >>
>> >> >> If the amount of code between shindig.foo and the return is long, 
I'd
>> >> >> suggest another alternative that I think has the advantage of 
both:
>> >> >>
>> >> >> (function() {
>> >> >>  // ... all the helper functions and shared state ...
>> >> >>
>> >> >>  shindig.foo = {
>> >> >>    bar: bar,
>> >> >>    baz: baz
>> >> >>  }
>> >> >> })();
>> >> >>
>> >> >> On Tue, Jul 26, 2011 at 2:19 PM, John Hjelmstad 
<fa...@google.com>
>> >> >wrote:
>> >> >>
>> >> >> > With the model we're using with exportJs, you actually can't as
>> easily
>> >> do
>> >> >> > that or wrap "singleton"/namespaced items, unless you .
>> exportJs(...)
>> >> is
>> >> >> > injected after the closure.
>> >> >> >
>> >> >> > function() {
>> >> >> >  foo.bar.baz = function() { }
>> >> >> > }();
>> >> >> > exportJs("foo.bar", [foo,foo.bar], {baz:"baz"});
>> >> >> >
>> >> >> > Of course, you can if you also update the style guide to 
prepend
>> >> window:
>> >> >> >
>> >> >> > function() {
>> >> >> >  window.foo.bar.baz = function() { }
>> >> >> > }();
>> >> >> >
>> >> >> > ...though that requirement seems a little awkward and verbose 
to
>> me.
>> >> >> >
>> >> >> > --j
>> >> >> >
>> >> >> > On Tue, Jul 26, 2011 at 2:12 PM, Dan Dumont 
<dd...@us.ibm.com>
>> >> >wrote:
>> >> >> >
>> >> >> > > As mentioned by Paul before you can define:
>> >> >> > >
>> >> >> > > function(){
>> >> >> > >   FooClass.prototype.method = function() { }
>> >> >> > >  FooClass.prototype.method2 = function() { }
>> >> >> > > }();
>> >> >> > >
>> >> >> > > to get a local scope.
>> >> >> > >
>> >> >> > > I think this makes it easier to audit what must be included 
in an
>> >> >> export.
>> >> >> > > And when you come up for air soon, maybe we can talk about 
AMD
>> >> >format
>> >> >> and
>> >> >> > > what that brings to the table.  :)
>> >> >> > >
>> >> >> > >
>> >> >> > >
>> >> >> > > From:   John Hjelmstad <fa...@google.com>
>> >> >> > > To:     dev@shindig.apache.org,
>> >> >> > > Date:   07/26/2011 04:43 PM
>> >> >> > > Subject:        Re: javascript readability..
>> >> >> > >
>> >> >> > >
>> >> >> > >
>> >> >> > > I still prefer status quo, as it reads more like a proper 
class
>> to
>> >> me,
>> >> >> > > while
>> >> >> > > being less verbose and centralizing the exported method
>> definitions
>> >> in
>> >> >> a
>> >> >> > > single place.
>> >> >> > >
>> >> >> > > As well, this question's corollary is whether to convert all
>> >> >> instantiable
>> >> >> > > objects to the form:
>> >> >> > >
>> >> >> > > FooClass.prototype.method = function() { }
>> >> >> > > FooClass.prototype.method2 = function() { }
>> >> >> > >
>> >> >> > > ...from:
>> >> >> > > FooClass = function() {
>> >> >> > >  // private state
>> >> >> > >  function method() { }
>> >> >> > >  function method2() { }
>> >> >> > >  return {
>> >> >> > >    method: method,
>> >> >> > >    method2: method2
>> >> >> > >  };
>> >> >> > > };
>> >> >> > >
>> >> >> > > On this note, I'm conflicted. I like having actual private 
state,
>> >> but
>> >> >> > > prototype-style is more efficient.
>> >> >> > >
>> >> >> > > Enough people have complained over time about each of the
>> existing
>> >> >> idioms
>> >> >> > > though that I suppose I could go the other direction, if it's
>> >> causing
>> >> >> > > development trouble.
>> >> >> > >
>> >> >> > > --j
>> >> >> > >
>> >> >> > > On Tue, Jul 26, 2011 at 6:17 AM, Ryan J Baxter <
>> rjbaxter@us.ibm.com
>> >> >
>> >> >> > > wrote:
>> >> >> > >
>> >> >> > > > +1 As well, I think its easier to read.
>> >> >> > > >
>> >> >> > > > -Ryan
>> >> >> > > >
>> >> >> > > > Email: rjbaxter@us.ibm.com
>> >> >> > > > Phone: 978-899-3041
>> >> >> > > > developerWorks Profile
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > From:   Dan Dumont/Westford/IBM@Lotus
>> >> >> > > > To:     dev@shindig.apache.org,
>> >> >> > > > Date:   07/26/2011 09:00 AM
>> >> >> > > > Subject:        Re: javascript readability..
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > +1
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > From:   Paul Lindner <li...@inuus.com>
>> >> >> > > > To:     dev@shindig.apache.org,
>> >> >> > > > Date:   07/26/2011 02:51 AM
>> >> >> > > > Subject:        javascript readability..
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > Hi,
>> >> >> > > >
>> >> >> > > > I'm curious to know what people think about some of the 
idioms
>> in
>> >> the
>> >> >> > JS
>> >> >> > > > code you find in shindig.  There's an awful lot of stuff 
like
>> >> this:
>> >> >> > > >
>> >> >> > > > shindig.foo = function(){
>> >> >> > > >  //...
>> >> >> > > >  var myFunction = function() {
>> >> >> > > >     }
>> >> >> > > >
>> >> >> > > >  return {'foo': myFunction,
>> >> >> > > >            'bar': function() {
>> >> >> > > >               return 'bar';
>> >> >> > > >            }};
>> >> >> > > > }();
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > Just search for @member to see the various places.
>> >> >> > > >
>> >> >> > > > What would people think if we moved to fully defined names 
for
>> >> >> > > > function/method definitions instead?
>> >> >> > > >
>> >> >> > > > You could still wrap this inside a closure if you wanted 
local
>> >> scope:
>> >> >> > > >
>> >> >> > > > function() {
>> >> >> > > >  shindig.foo.foo = function() {
>> >> >> > > >     ...
>> >> >> > > >  }
>> >> >> > > >  shindig.foo.bar = function() {
>> >> >> > > >     ...
>> >> >> > > >  }
>> >> >> > > > }();
>> >> >> > > >
>> >> >> > > > --
>> >> >> > > > Paul Lindner -- lindner@inuus.com -- 
linkedin.com/in/plindner
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > >
>> >> >> > >
>> >> >> > >
>> >> >> > >
>> >> >> >
>> >> >>
>> >>
>>
>





Re: javascript readability..

Posted by Henry Saputra <he...@gmail.com>.
I think a wiki entry for this exportJs feature would greatly help
Shindig community to understand more about design and the impl chosen.

- Henry

On Mon, Aug 1, 2011 at 5:54 PM, John Hjelmstad <fa...@google.com> wrote:
> Hey Jesse:
>
> We haven't loudly advertised exportJs() yet since we've been adding a final
> piece of functionality to it for deferred symbol binding, and because
> Shindig (on account of it being still by default on JDK 1.5 if nothing else)
> doesn't use closure compiled JS by default yet.
>
> For context, deferred symbol binding applies to features consisting of
> methods that return nothing synchronously. Synthetic example:
>
> // namespace setup here
> gadgets.foo.doSomething = function(key, value, callback) {
>  // do something with key and value
>  callback(somethingComputed);
> };
>
> Deferred symbol binding allows us to emit a tiny JS loader "stub" that just
> enqueues arguments to a method with this name. That stub -- actually the
> async JS loader -- then loads the payload, which when loaded executes the
> real method.
>
> This allows fast integration of code via:
> <script src="http://myserver.com/gadgets/js/foofeature.js"></script>
> <script>
>  gadgets.foo.doSomething('myKey', 'myValue', function(data) { /* myCallback
> */ });
> </script>
>
> ...for syntactic convenience while maintaining asynchronous loading
> semantics for latency purposes (ie. not blocking the page load).
>
> The functionality overall is activated by the flag supportDefer="true" in
> feature.xml, and server-side configuration for same. Without it, the above
> syntax is not activated and things work as before.
>
> I implemented a version of this with both deferred and full symbol binding
> in exportJs() but found a few shortcomings with the approach. we're
> rejiggering it today. I'd hold off for a short time while we do so to avoid
> merge conflicts. The relevant JS CL is: https://reviews.apache.org/r/1237/
>
> Cheers,
> John
> PS. Time will tell whether I regret it, but thanks for the props on the
> method overall :) It's hard to measure precisely how valuable the technique
> is since much of its value is preventative, ie. A) disallowing use of helper
> methods as if they were supported APIs, and B) prevents symbol
> clashes/occlusion with arbitrary contexts in which "our" JS is imported --
> hopefully all while allowing a coding style that "feels" as if none of this
> edifice exists.
>
> On Fri, Jul 29, 2011 at 7:09 AM, Ciancetta, Jesse E. <jc...@mitre.org>wrote:
>
>> Hey John,
>>
>> I hadn’t seen the exportJs support before (I haven’t done any work with
>> features in a long time) -- that does look very similar!  (and as an aside
>> -- hats off to whoever came up with that scheme to be able to closure
>> compile JS in isolation but still have fully qualified symbols available in
>> the global space -- its absolutely brilliant)
>>
>> I wrote a quick test gadget which required feature exportjs and did some
>> testing -- and it comes pretty close to doing everything we'd need already,
>> so I don’t see any reason why it couldn’t be augmented to handle all the
>> cases my helper function does.  Then it'd just be a matter of making it part
>> of the core feature set so it would be available for use in any features
>> that wanted to take advantage of it.
>>
>> So I guess that comes back to Paul's original question though -- if enough
>> people preferred the first style Paul proposed I'd be happy to take a crack
>> at augmenting exportJs to support this use case.  So we'd end up with JS
>> that looked something like this:
>>
>> //could be from foo-utils.js
>> exportJs("shindig.util", (function() {
>>     var privateData = "this is private";
>>
>>    var privateFunction = function() {
>>        console.log(privateData);
>>    };
>>
>>    var calculateFoo = function() {
>>        privateFunction();
>>    };
>>
>>    var doAlotOfFoo = function() {
>>        //do alot of foo
>>    };
>>
>>    return {
>>        calculateFoo: calculateFoo,
>>        doAlotOfFoo: doAlotOfFoo
>>    };
>> })());
>>
>> //could be from bar-utils.js
>> exportJs("shindig.util", (function() {
>>     var privateFunction = function() {
>>        console.log("calculateBar called");
>>    };
>>
>>    var calculateBar = function() {
>>        privateFunction();
>>    };
>>
>>    return {
>>        publicData: "this is public",
>>        calculateBar: calculateBar
>>    };
>> })());
>>
>> exportJs("shindig.some.emptyNamespace", {});
>> shindig.some.emptyNamespace.xyz = "ABC";
>>
>> --Jesse
>>
>> >-----Original Message-----
>> >From: John Hjelmstad [mailto:fargo@google.com]
>> >Sent: Thursday, July 28, 2011 5:58 PM
>> >To: dev@shindig.apache.org
>> >Subject: Re: javascript readability..
>> >
>> >Hey Jesse,
>> >
>> >Interesting idea here -- this sounds suspiciously akin to the
>> functionality
>> >already present in exportJs(...) used for exporting symbols. This method
>> >upserts the namespace in much the same way as your helper method does.
>> >Thoughts on whether we could reuse or augment that?
>> >
>> >-j
>> >
>> >On Thu, Jul 28, 2011 at 7:52 AM, Ciancetta, Jesse E. <jcian@mitre.org
>> >wrote:
>> >
>> >> I agree with John -- I also prefer the first style Paul presented (which
>> I
>> >> believe is also the most prevalent style in Shindig currently).
>> >>
>> >> With respect to the issues that Michael raised about building up a
>> >> namespace from across different files -- this got me thinking about a
>> little
>> >> namespace utility a colleague of mine wrote a while back.  That utility
>> just
>> >> took a target namespace like "shindig.util.foo", created an empty object
>> in
>> >> it (without clobbering any parts of the target namespace that may have
>> >> already existed) and returned it -- so you could then do something like
>> >> shindig.util.foo.x = ... directly without needing to create each piece
>> of
>> >> the namespace manually.
>> >>
>> >> And with some (well, a lot) of tweaking I was able to turn that function
>> >> into a more general purpose namespacing function that takes an optional
>> >> object to place into the target namespace -- and if the target namespace
>> >> already exists it takes the properties of the optional object and
>> appends
>> >> them to the existing namespace.
>> >>
>> >> So I think if enough people preferred the first style Paul presented,
>> >> something like this could be used to work around the issues Michael
>> raised.
>> >>  Here is the function and some sample usages (with the caveat that I
>> haven’t
>> >> actually used this for anything real so there could be some bugs in it):
>> >>
>> >> var shindig = shindig || (function() {
>> >>    var namespace = function(targetNamespace, optObject) {
>> >>        //get a reference to the global window object
>> >>        var object = window;
>> >>
>> >>        //if no object was provided to put into the namespace create an
>> >> empty one
>> >>        optObject = optObject || {};
>> >>
>> >>        //split the namespace into its parts
>> >>        var namespaces = targetNamespace.split(".");
>> >>
>> >>        //for each part of the namespace
>> >>        for (var i = 0; i < namespaces.length; i++) {
>> >>            //see if this part is already defined
>> >>            if (typeof object[namespaces[i]] === "undefined") {
>> >>                //if its not defined already -- put an object into it
>> >>                //if we're at the end of the targetNamespace, put the new
>> >> object into it,
>> >>                //otherwise drop in an empty object as a placeholder
>> >>                object[namespaces[i]] = (i + 1) == namespaces.length ?
>> >> optObject : {};
>> >>            } else {
>> >>                //there is already something here -- see if we're at the
>> end
>> >> of the targetNamespace
>> >>                if ((i + 1) == namespaces.length) {
>> >>                    //make sure its an object we can append to
>> >>                    if (typeof object[namespaces[i]] === "object") {
>> >>                        //go ahead and add all the public properties on
>> >> optObject to the target namespace
>> >>                        for (var property in optObject) {
>> >>                            object[namespaces[i]][property] =
>> >> optObject[property];
>> >>                        }
>> >>                    } else {
>> >>                        throw "Cannot append new properties to object of
>> >> type " + typeof object[namespaces[i]];
>> >>                    }
>> >>                }
>> >>            }
>> >>
>> >>            object = object[namespaces[i]];
>> >>        }
>> >>
>> >>        return object;
>> >>    };
>> >>
>> >>    return {
>> >>        namespace: namespace
>> >>    };
>> >> })();
>> >>
>> >> //could be from foo-utils.js
>> >> shindig.namespace("shindig.util", (function() {
>> >>    var privateData = "this is private";
>> >>
>> >>    var privateFunction = function() {
>> >>        console.log(privateData);
>> >>    };
>> >>
>> >>    var calculateFoo = function() {
>> >>        privateFunction();
>> >>    };
>> >>
>> >>    var doAlotOfFoo = function() {
>> >>        //do alot of foo
>> >>    };
>> >>
>> >>    return {
>> >>        calculateFoo: calculateFoo,
>> >>        doAlotOfFoo: doAlotOfFoo
>> >>    };
>> >> })());
>> >>
>> >> //could be from bar-utils.js
>> >> shindig.namespace("shindig.util", (function() {
>> >>    var privateFunction = function() {
>> >>        console.log("calculateBar called");
>> >>    };
>> >>
>> >>    var calculateBar = function() {
>> >>        privateFunction();
>> >>    };
>> >>
>> >>    return {
>> >>        publicData: "this is public",
>> >>        calculateBar: calculateBar
>> >>    };
>> >> })());
>> >>
>> >> shindig.namespace("shindig.some.emptyNamespace");
>> >> shindig.some.emptyNamespace.xyz = "ABC";
>> >>
>> >> >-----Original Message-----
>> >> >From: Michael Hermanto [mailto:mhermanto@gmail.com]
>> >> >Sent: Tuesday, July 26, 2011 6:15 PM
>> >> >To: dev@shindig.apache.org
>> >> >Subject: Re: javascript readability..
>> >> >
>> >> >What didn't work for me with --
>> >> >   shindig.foo = function() {
>> >> >     return { 'bar': ... };
>> >> >   }();
>> >> >... is that methods in the same namespace have to be all
>> >> >defined/implemented
>> >> >in one file.
>> >> >
>> >> >ie: it's fine if all gadgets.rpc.* is implemented in a file rpc.js, but
>> >> not
>> >> >fine when gadgets.util.* are implemented across different
>> files/features
>> >> >across core.util.dom, core.util.string, etc. When feature core.util
>> pulls
>> >> >all these files in, it will effectively stomp all the
>> previously-defined
>> >> >core.util.*.
>> >> >
>> >> >The tendency has been to make libraries smaller and more focussed to
>> >what
>> >> >they do, ie: this means breaking up features into sub-features. To do
>> so,
>> >> I
>> >> >had to convert more-focussed core.util.[dom|string|...] to
>> fully-defined
>> >> >names. Unless the above style (with shindig.foo) doesn't have this
>> >> >limitation (ie: can incrementally define more methods on top what has
>> >been
>> >> >defined), I personally prefer the fully-defined names, for consistency.
>> >> >
>> >> >
>> >> >
>> >> >2011/7/26 ๏̯͡๏ Jasvir Nagra <ja...@google.com>
>> >> >
>> >> >> I don't have a strong preference either way although it's nice when
>> >> >> reviewing code to have all the exported things exported once when
>> they
>> >> >> share
>> >> >> a scope full of private helpers and other state.  It also helps
>> convey
>> >> when
>> >> >> the setup of a particular part of the object graph is done.
>> >> >> Eg.
>> >> >>
>> >> >> shindig.foo = (function() {
>> >> >>  // ... all the helper functions and shared state ...
>> >> >>  ...
>> >> >>  return { bar: bar, baz: baz };
>> >> >> }();
>> >> >> // at this point I know from convention that shindig.foo is done
>> being
>> >> >> setup
>> >> >> and will have just "bar" and "baz"
>> >> >>
>> >> >> vs.
>> >> >>
>> >> >> shindig.foo.bar = function() { ... }
>> >> >> /// ... a lot of code later
>> >> >> shindig.foo.baz = function() { ... }
>> >> >>
>> >> >> If the amount of code between shindig.foo and the return is long, I'd
>> >> >> suggest another alternative that I think has the advantage of both:
>> >> >>
>> >> >> (function() {
>> >> >>  // ... all the helper functions and shared state ...
>> >> >>
>> >> >>  shindig.foo = {
>> >> >>    bar: bar,
>> >> >>    baz: baz
>> >> >>  }
>> >> >> })();
>> >> >>
>> >> >> On Tue, Jul 26, 2011 at 2:19 PM, John Hjelmstad <fa...@google.com>
>> >> >wrote:
>> >> >>
>> >> >> > With the model we're using with exportJs, you actually can't as
>> easily
>> >> do
>> >> >> > that or wrap "singleton"/namespaced items, unless you .
>> exportJs(...)
>> >> is
>> >> >> > injected after the closure.
>> >> >> >
>> >> >> > function() {
>> >> >> >  foo.bar.baz = function() { }
>> >> >> > }();
>> >> >> > exportJs("foo.bar", [foo,foo.bar], {baz:"baz"});
>> >> >> >
>> >> >> > Of course, you can if you also update the style guide to prepend
>> >> window:
>> >> >> >
>> >> >> > function() {
>> >> >> >  window.foo.bar.baz = function() { }
>> >> >> > }();
>> >> >> >
>> >> >> > ...though that requirement seems a little awkward and verbose to
>> me.
>> >> >> >
>> >> >> > --j
>> >> >> >
>> >> >> > On Tue, Jul 26, 2011 at 2:12 PM, Dan Dumont <dd...@us.ibm.com>
>> >> >wrote:
>> >> >> >
>> >> >> > > As mentioned by Paul before you can define:
>> >> >> > >
>> >> >> > > function(){
>> >> >> > >   FooClass.prototype.method = function() { }
>> >> >> > >  FooClass.prototype.method2 = function() { }
>> >> >> > > }();
>> >> >> > >
>> >> >> > > to get a local scope.
>> >> >> > >
>> >> >> > > I think this makes it easier to audit what must be included in an
>> >> >> export.
>> >> >> > > And when you come up for air soon, maybe we can talk about AMD
>> >> >format
>> >> >> and
>> >> >> > > what that brings to the table.  :)
>> >> >> > >
>> >> >> > >
>> >> >> > >
>> >> >> > > From:   John Hjelmstad <fa...@google.com>
>> >> >> > > To:     dev@shindig.apache.org,
>> >> >> > > Date:   07/26/2011 04:43 PM
>> >> >> > > Subject:        Re: javascript readability..
>> >> >> > >
>> >> >> > >
>> >> >> > >
>> >> >> > > I still prefer status quo, as it reads more like a proper class
>> to
>> >> me,
>> >> >> > > while
>> >> >> > > being less verbose and centralizing the exported method
>> definitions
>> >> in
>> >> >> a
>> >> >> > > single place.
>> >> >> > >
>> >> >> > > As well, this question's corollary is whether to convert all
>> >> >> instantiable
>> >> >> > > objects to the form:
>> >> >> > >
>> >> >> > > FooClass.prototype.method = function() { }
>> >> >> > > FooClass.prototype.method2 = function() { }
>> >> >> > >
>> >> >> > > ...from:
>> >> >> > > FooClass = function() {
>> >> >> > >  // private state
>> >> >> > >  function method() { }
>> >> >> > >  function method2() { }
>> >> >> > >  return {
>> >> >> > >    method: method,
>> >> >> > >    method2: method2
>> >> >> > >  };
>> >> >> > > };
>> >> >> > >
>> >> >> > > On this note, I'm conflicted. I like having actual private state,
>> >> but
>> >> >> > > prototype-style is more efficient.
>> >> >> > >
>> >> >> > > Enough people have complained over time about each of the
>> existing
>> >> >> idioms
>> >> >> > > though that I suppose I could go the other direction, if it's
>> >> causing
>> >> >> > > development trouble.
>> >> >> > >
>> >> >> > > --j
>> >> >> > >
>> >> >> > > On Tue, Jul 26, 2011 at 6:17 AM, Ryan J Baxter <
>> rjbaxter@us.ibm.com
>> >> >
>> >> >> > > wrote:
>> >> >> > >
>> >> >> > > > +1 As well, I think its easier to read.
>> >> >> > > >
>> >> >> > > > -Ryan
>> >> >> > > >
>> >> >> > > > Email: rjbaxter@us.ibm.com
>> >> >> > > > Phone: 978-899-3041
>> >> >> > > > developerWorks Profile
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > From:   Dan Dumont/Westford/IBM@Lotus
>> >> >> > > > To:     dev@shindig.apache.org,
>> >> >> > > > Date:   07/26/2011 09:00 AM
>> >> >> > > > Subject:        Re: javascript readability..
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > +1
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > From:   Paul Lindner <li...@inuus.com>
>> >> >> > > > To:     dev@shindig.apache.org,
>> >> >> > > > Date:   07/26/2011 02:51 AM
>> >> >> > > > Subject:        javascript readability..
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > Hi,
>> >> >> > > >
>> >> >> > > > I'm curious to know what people think about some of the idioms
>> in
>> >> the
>> >> >> > JS
>> >> >> > > > code you find in shindig.  There's an awful lot of stuff like
>> >> this:
>> >> >> > > >
>> >> >> > > > shindig.foo = function(){
>> >> >> > > >  //...
>> >> >> > > >  var myFunction = function() {
>> >> >> > > >     }
>> >> >> > > >
>> >> >> > > >  return {'foo': myFunction,
>> >> >> > > >            'bar': function() {
>> >> >> > > >               return 'bar';
>> >> >> > > >            }};
>> >> >> > > > }();
>> >> >> > > >
>> >> >> > > >
>> >> >> > > > Just search for @member to see the various places.
>> >> >> > > >
>> >> >> > > > What would people think if we moved to fully defined names for
>> >> >> > > > function/method definitions instead?
>> >> >> > > >
>> >> >> > > > You could still wrap this inside a closure if you wanted local
>> >> scope:
>> >> >> > > >
>> >> >> > > > function() {
>> >> >> > > >  shindig.foo.foo = function() {
>> >> >> > > >     ...
>> >> >> > > >  }
>> >> >> > > >  shindig.foo.bar = function() {
>> >> >> > > >     ...
>> >> >> > > >  }
>> >> >> > > > }();
>> >> >> > > >
>> >> >> > > > --
>> >> >> > > > Paul Lindner -- lindner@inuus.com -- linkedin.com/in/plindner
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > > >
>> >> >> > >
>> >> >> > >
>> >> >> > >
>> >> >> > >
>> >> >> >
>> >> >>
>> >>
>>
>