Andrew Tetlaw wrote:
OK trying to say this as tactfully as possible, because it's not
I welcome feedback. Javascript can be a difficult language to develop in
so I am always looking for ways to improve things.
[...snip info about prototype's use of globals...]
This can only create a huge mess as everyone tries to muck around
treading on each others global namespace claims.
Yes namespace really can be a problem in Javascript. I have encountered
the problem first-hand.
I propose that all contributors of Prototype based user scripts create
their on namespaced objects and leave the global namespace to
Prototype. I'd go a little further and suggest for sanity's sake we
also leave any namespace created by Prototype well alone too.
The problem seems to me an issue of convenience vs compatibility. Java
uses the organization name (us.afaik.blah.blah.blah) to organize the
namespace. So if we went that route I could define an object called:
us.afaik.effects.Element.Rotate
This would ensure separation of namespaces but isn't very convenience to
work with. Also, Javascript is unique in that everything must be
downloaded to the client. This means we want to avoid unnecessary code
if possible.
To me if you look even deeper there is also another harm in creating
ridged namespaces as in Java. I find there to be a synergy in being able
to share namespaces from separate projects. I see the issue as needing
balance. Sharing namespace across projects encourages good OO code in
some cases. Othertimes it just causes problems. Instead of doing:
(new us.afaik.util.String('<img src="foo.gif" />')).preloadImgs()
or handing it in a procedural manor:
us.afaik.util.String.preloadImgs('<img src="foo.gif" />');
I can just write clean OO code that does:
'<img src="foo.gif" />'.preloadImgs();
I see this as a good use of adding to the built-in objects. It allows
any code that is working with my library to easily preload any images
defined in a string. They don't have to interact with a special string
object (the Java way) and they don't have to use procedural code. They
just call an method on an object.
But like everything it must be done in moderation. To me the test is are
you doing something that another developer would expect? Take for example:
String.prototype.replace = function() { return ''; }
This is bad! Although for some odd reason it may be what you need it
will not be what other applications expect. On the other hand:
String.prototype.trim = function() {
return this.replace(/^\s+/, '').replace(/\s+$/, '')
}
This is good! Because it allows a programmer to call a trim() method on
any string object (no matter how that object was created) which does
what a programmer expects. Even if another library defines a trim method
it may be different in implementation but the basic concept will be the
same.
In both cases we defined a method on a built-in object. The differences
is in how we used that power. The first case we did something that a
developer would not expect, while the second did something a developer
would expect. The same thing applies to building on existing objects in
Prototype (or any other library). Assume that we build our extensions in
a way that is obvious we will avoid problems while still getting great
synergy.
The other consideration to make is the scope of the project. A project
like Prototype or Script.aculo.us has to be more careful because it is
complex and used in a wide variety of environments. On the other hand my
stupid object is a simple 123 lines of code. If you do encounter a
conflict it is small enough to maintain a simple patch that avoids the
conflict. I also welcome any changes that might need to be made to avoid
conflicts with an existing library.
This image rotation script, while useful, I would not be confident in
using because it, adds to the Prototype Element object, it adds to the
Prototype object, it adds an image cache to the String object (???).
I said previously that adding to core objects and objects in other
libraries is a balance. Did I make the right choices? Probably not
completely but I can fix anything that pops up.
In general I feel that the code I added to existing objects is in the
spirit of those objects (Prototype.ImageTag matches Prototype.ScriptTag,
String.extractImgs matches String.extractScripts, etc.). Even the
"Rotate" property added to the Element object to store my object is
reasonable (what else would rotate mean?). But I don't begrudge anybody
for thinking it is too liberal. Just a design choice.
Just my two cents. I welcome comments from others.
Eric
_______________________________________________
Rails-spinoffs mailing list
[email protected]
http://lists.rubyonrails.org/mailman/listinfo/rails-spinoffs