Addition of a global namespace function?

Alex Russell alex at dojotoolkit.org
Thu Dec 3 12:01:00 PST 2009


On Dec 3, 2009, at 10:37 AM, Mike Samuel wrote:

> Mark,
> 
> Thanks for responding in such detail.
> I have responded inline, but to summarize what I think I've understood so far:
> (1) This is a proposal for an added function, without any proposed
> syntactic sugar
> (2) The function can be implemented as a library function as in your blog post
> (3) The goal is to reduce the chance of unintentional namespace
> collisions by code that is aware of the namespace function.
> (4) It is not a goal to prevent namespace collisions between code
> written before the namespace function and code written after.
> Specifically, if legacy code did "com = 'foo'" then namespacing would
> be broken for all subsequent code.

Personally, I don't think this is sufficient to solve the largest set of problems that users encounter with the language. Specifically, if entering a namespace does not prevent global pollution (i.e., omitting "var" still pollutes), then it seems to me like the proposal is something of a missed opportunity.

> cheers,
> mike
> 
> 
> 2009/12/2 Mark A. Ziesemer <online at mark.ziesemer.com>:
>> On Wed, Dec 2, 2009 at 5:26 PM, Mike Samuel <mikesamuel at gmail.com> wrote:
>> 
>>> What is the goal of namespaces?
>>> To prevent one module from (unintentionally|intentionally|both)
>>> clobbering an API exported by another module?
>> 
>> I'm not sure using "modules" is the correct term in this context.
>> However, the goal of JavaScript "namespacing" as I see it is to
>> prevent one section of code from unintentionally clobbering another
>> section of code, due to naming collisions.  This could be combinations
>> of code from one or more developers, organizations, or products.
> 
> I was using the term module just to mean an addressable piece of code
> that is loaded by a single invocation of a loader such as <script> or
> eval.  I don't think we disagree over anything but nomenclature.
> 
>> Imagine a typical, modern web page.  Consider http://www.mozilla.org.
>> It appears quite clean with only 4 *.js files loaded: mozilla.org.js,
>> jquery-1.3.2.min.js, jquery-ui-1.7.2.custom.min.js, and urchin.js
>> (older version of Google analytics).  The first 3 are already very
>> well behaved, actually following the exact standard I'm proposing with
>> nested namespaces, including:
>> 
>> jQuery
>> jQuery.ui
>> jQuery.ui.mouse
>> jQuery.event
>> (many other jQuery objects)
>> org.mozilla.carousel
>> org.mozilla.strings
>> org.mozilla.augmentCommunityHovers
>> org.mozilla.init
>> org.mozilla.tabSwitch
>> (other org.mozilla.*)
>> 
>> I'd actually prefer that "jQuery" was "com.jquery", but it is
>> certainly an effort towards namespacing.  For both jQuery.* and
>> org.mozilla.*, my proposed namespace function could be used to help
>> create these nested objects.  Currently, each script needs to find a
>> way to do this itself, or depend upon another library that provides an
>> appropriate namespacing function.  Mozilla's is:
>> 
>> /**
>>  * Namespace
>>  */
>> if (typeof org == 'undefined') {
>>    var org = {};
>> }
>> 
>> org.mozilla = function() { /* ... */ }
>> 
>> With my proposed addition, this would simply be:
>> 
>> namespace("org").mozilla = function() { /* ... */ }
>> 
>> or even shorter:
>> 
>> namespace("org.mozilla").init = function() { /* ... */ }
>> 
>> urchin.js, on the other hand, could certainly use some better
>> namespacing.  The only convention used is that everything begins with
>> "_u".  There's no standard or anything else to discourage any other of
>> many, many other JavaScript developers to also develop a common
>> library that is prefixed with "_u".  Furthermore, as this method of
>> "namespacing" is not using nested objects, it is contributing towards
>> global namespace pollution
>> (http://www.yuiblog.com/blog/2006/06/01/global-domination/ ,
>> http://blogger.ziesemer.com/2007/10/respecting-javascript-global-namespace.html
>> ).
> 
> So is it your argument that both (prefixing and dotted path
> namespacing) are conventions that address the same problem, but that
> the java-esque package name convention is a better convention?
> 
> 
>> http://mankz.com/code/GlobalCheck.htm shows Google Urchin as having 76
>> global variables, with 73 in the current version hosted at
>> mozilla.org.  Fortunately, Google seems to have paid attention to
>> this, as their newer version (ga.js) places everything as a child of
>> "_gat" (Google AnalyTics?).  Again, I would have preferred something
>> like "com.google.analytics", but this is definitely a significant
>> improvement from before.  ga.js is quite obfuscated, but it is clear
>> that they are also using nested objects to achieve proper namespacing.
>>  As part of this, they are surely having to create these nestings
>> someplace themselves, and could also benefit from the global namespace
>> function that I am proposing.
> 
> Have you quantified the cost of each module carrying their own
> namespace creating code?
> The bit in your blog about the minified form of the namespace function
> suggest that it is low.
> And if the function is in the minimized code, then can't minifiers do
> a better job since they can do whole program analysis to use an
> identifier smaller than the 9 character namespace, whereas if
> "namespace" where externally defined, the 9 character name could not
> be shortened.
> 
>> This is not only an issue with web pages, but other products where
>> JavaScript may be mashed together.  This includes - but is not limited
>> to - Mozilla Firefox and its extensions, as mentioned in the
>> previously linked
>> https://addons.mozilla.org/en-US/developers/docs/policies/reviews .
>> 
>>> What is a namespace?
>>> An object that can be consistently addressed by a dotted path after first read?
>>> A chain of property names starting from a container that should always
>>> return the same result after first read?
>> 
>> For a general definition of a namespace, I'll defer to Wikipedia:
>> http://en.wikipedia.org/wiki/Namespace_%28computer_science%29 .  (This
>> also happens to list a number of drawbacks against using the "prefix
>> namespacing" approach as a work-around, mentioned at
>> http://peter.michaux.ca/articles/javascript-namespacing .)
> 
> Thanks for the link.  I was interested more in how you define it in
> terms of JavaScript primitives than in how the concept is applied
> generally.
> 
>> In JavaScript, it seems that I and many others (including the above
>> examples of mozilla.org, jQuery, and Google Analytics) agree that
>> namespacing is best accomplished using nested objects, or a "dotted
>> path" as you mentioned.  There just isn't anything (yet) built-in to
>> the language to support this beneficial practice.
> 
> Since we are talking about language extensions, we need not be limited
> by the approaches that are easy in ES3.
> We can consider approaches that use other language primitives (like
> lexical scopes in Ihab's module proposal) to address the same goals as
> namespace.
> 
>> I would contend that namespaces are, and should be dynamic - so that
>> they do not always have to return the same result after the first
>> read.  I'm not saying that doing so is a bad practice, but I don't see
> 
> Let me make sure I understand.
> Let's say you have a file foo.js that inroduces one API element
> com.ziesemer.foo.  There are two namespaces:
>  com
>  com.ziesemer
> as a result of
>  namespace('com.ziesemer').foo = ...;
> 
> com.ziesemer.foo is not a namespace, since it is not created as a
> result of the namespace function, right?
> 
> So for namespaces to be dynamic, means it would be OK for com.ziesemer
> to be implemented in terms of a getter -- e.g. to allow lazy loading?
> 
> 
>> any reason to introduce artificial limitations to prevent doing so.
> 
> There are more clients for javascript programmers than just
> programmers and interpreters.  There are debugging tools, minifiers,
> IDE auto-completers, documentation generators, etc.
> 
>> Also, as being discussed, a namespace in JavaScript really isn't
>> anything special - it is one or more objects.  "com.example.x.y.z"
>> could hold a value, as well as acting as a namespace for other child
>> namespaces or values.  Again, I'm not stating that this is a good
>> practice, but I don't see a need to prevent it.
> 
> 
> 
> 
>>> Why is namespace not in a namespace?
>> 
>> Because the namespace function should be one of few that are "truly
>> global", along with the likes of "eval", and global objects such as
> 
> I'm not sure I understand what "truly global" means.
> Array and String are defined globally, but are accessible by code that
> has no global references:
>    [].constructor, and (function () { return this.constructor }).call('')
> I don't think namespace is global in the same way.  And I think that
> fact can be used to argue that, where it not for
> backwards-compatibility, they need not be global.
> Array and String are always defined because they can't be defined as
> library code.  But namespace obviously isn't currently defined that
> way and can be implemented as library code.
> 
> 
>> "Array" and "String".  (Other global functions include
>> (encode/decode)URI(Component), is(Finite/NaN), and parse(Float/Int).
>> It could be argued that these should belong in a namespace, e.g.
>> Math.* for the later ones.)
> 
>> The namespace function should also be used to create the namespace
>> that the namespace function would reside in - which quickly turns into
>> a paradox.
> 
> Lots of systems require bootstrapping.  In java, there is no paradox
> when it comes to which ClassLoader loaded the Class or ClassLoader
> classes?
> 
> 
> 
>>> From your blog:
>>> 
>>> In what sense are namespaces object-oriented?  As I understand the
>>> term, object-orientation is a way of organizing a program around
>>> objects that exchange messages.  There's nothing in this proposal that
>>> deals with messaging or objects -- it seems to be a hierarchical
>>> addressing scheme.
>> 
>> Maybe a better way to state this is that the proposed method of
>> namespacing in JavaScript makes use of its OO support, namely objects
>> supporting child properties and methods.
> 
> Ok, so it's OO because it uses objects, instead of functional because
> it uses lexical scoping.
> It is also imperative because it modifies the local environment using
> side-effects visible to code in the same module instead of
> declarative.
> 
> 
>>> When you talk about namespace aliasing, should namespaces be treated
>>> as first class?  If namespaces are aliasable, should they be marked
>>> unconfigurable to prevent property deletion or is that up to the
>>> namespace user?
> 
>> Again, namespacing isn't anything "new", and is already being widely
>> used as shown in examples above.  I'm just proposing the addition of a
>> global namespace function to make creating new namespaces easier and
>> standardized.
> 
> I appreciate that you're trying to codify existing practice.  I'm
> trying to help clarify the proposal by asking these questions.  Lot's
> of existing practices (JSON handling and getElementsByClassName come
> to mind) have many subtle variants, so codifying is not a simple
> matter of stamping approval on a concensus -- you still have to tease
> out goals, enumerate candidates, discuss tradeoffs, understand legacy
> code, etc.
> 
>> The way they are currently being implemented is just through nested
>> objects.  I'd say that objects already are (or should be) considered
>> "first class" in JavaScript, so namespaces should be as well.
> 
> This seems like a non-sequitur.
> 
> If two pieces of code do
>    namespace('com.ziesemer') = ...
> 
>    namespace('com.jquery') = ...
> isn't the com object a shared concern?  Why is it "just an object"?
> 
> Wouldn't it be problematic for code to do something like (using the .info TLD):
>  var info = loadUserInfo();
> 
>  namespace('info.ziesemer').foo = ...;
> If the first module creates an object, then the second will not modify
> it.  But the second is problematic in this case precisely because it
> assumes things about info that are not true.  If it is just an object,
> instead of "an object that other packages can safely add properties to
> without changing the meaning of namespace respecting programs" then
> namespacing is broken.
> 
> (I think in Rhino it's not just an object.  If there's any com package
> on the classpath, it's actually an immutable java package item that
> allows Rhino to get at java classes.)
> 
> 
>> I would say that namespaces should definitely not be marked
>> "unconfigurable".  A good JavaScript library, if it has nothing else
>> to do and no more purpose, should actually remove itself from memory,
>> and allow itself to be garbage collected.  I don't see any reason to
>> introduce any barriers to allowing this.
> 
> How would this be done in practice?
> How would a library know when to unload itself?
> If another approach to managing namespace collisions were to do this
> better, would it be an argument against the OO namespacing approach?
> 
>>> When you talk about using the "with" statement with namespaces, what
>>> problem are you trying to solve?  Is this meant to act as a poor-man's
>>> java import?
>>> Are you aware of the forward-compatibility problems that "with"
>>> entails, and the effect it has on tools like YUI compressor, closure
>>> compiler, etc.?
>> 
>> I wasn't trying to solve any problem.  I only mentioned this as an
>> alternative, to show the benefits that the nested-object approach has
>> for namespacing.  I agree, the "with" statement probably causes more
>> problems than it helps.  (
>> http://www.yuiblog.com/blog/2006/04/11/with-statement-considered-harmful/
>> )  While I didn't show an actual example on my blog post, I did
>> mention that the previous example would be better done within another
>> function.
>> 
>> Here is correcting that.  This:
>> 
>> with(com.ziesemer.myPackage){
>>  name = 'Mark';
>>  location = 'Wausau, WI';
>>  alertHello();
>> }
>> 
>> would better be accomplished as something like:
>> 
>> (function(){
>>  var czmp = com.ziesemer.myPackage;
>>  czmp.name = 'Mark';
>>  czmp.location = 'Wausau, WI';
>>  czmp.alertHello();
>> })();
> 
> Do we agree that the ability to use `with` with OO namespaces is not a
> feature of the proposal.
> 
> 
>>> You mention java packages, which provide namespacing, and information
>>> hiding.  Is it a goal for this scheme to extend to support information
>>> hiding as well?  If so, how?
>> 
>> I would not easily agree that Java packages provide information hiding
> 
> I was referring to the fact that package-private affects access
> control (incl reflection unless the VM invoker turns it off).  For
> that to be inviolable, you need to combine that with jar sealing.
> 
>> - though the definition of the term "hiding" is up for dispute.  Java
>> namespaces allow for organization, and help to prevent naming
>> collisions.  Java adds some extra features based on these namespaces,
>> such as package access protection.  There would be nothing to prevent
>> JavaScript from adding something similar someday.
> 
> Java packages provide for many things.  I am trying to understand via
> your analogy which you see this as providing.  As far as I can tell,
> java packages provide:
>  (1) access control via package private and JAR sealing
>  (2) hierarchical addressing of classes
>  (3) some degree of namespace separation, though separation can also
> be achieved by using multiple classloaders
> 
>> I guess I would consider the "private" and "protected" keywords more
>> suited to "hiding" things than packages.  Even then, these keywords
> 
> They both do that.  The presence of the keyword "private" in C++ does
> not mean that the word "friend" does not affect access control.  In
> the same way both java packages in combination with the access level
> keywords specify access control for the language.
> 
>> are seldom misunderstood, and should never be used for "security".  A
>> little reflection can go a long way!
> 
> I disagree with this.  Reflection does not work around the access
> control rules unless the VM invoker explicitly opts out.  See Joe-E as
> an example of security based on access running a subset of Java with
> reflection enabled.  http://code.google.com/p/joe-e/
> 
>>> cheers,
>>> mike
>> 
>> (I've used the term "JavaScript" throughout this reply.  Really, I
>> think JavaScript and ECMAScript could have been used interchangeably.)
>> 
>> --
>> Mark A. Ziesemer
>> www.ziesemer.com
>> 
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss

--
Alex Russell
slightlyoff at google.com
alex at dojotoolkit.org BE03 E88D EABB 2116 CC49 8259 CF78 E242 59C3 9723



More information about the es-discuss mailing list