The Google Map API makes extensive use of and relies on JavaScript. A recent update (to v2.64) included a change that causes any client of the Google Map API to fail if any members or methods have been added to class Object.
Specifically, the API contains code that iterates through specific instances of various objects created by Google (I've changed Google's obfuscated code to more clearly convey what it does, while intentionally hiding its location in the API):
//... for(var anElement in this.someObject){ this.doSomethingWith_(anElement); delete this.someObject[anElement]} //...This code uses a for-loop to find, do something to, and then delete every property or member of whatever it finds in this.someObject. This means, in turn, that this code breaks any OTHER code that adds members or methods to, for example, class Object (or any other ancestor of this.someObject).
I include the following in my Google API client:
Object.prototype.clazz = function() { return this.constructor; }The Google code fails when "clazz" (a function) is passed to the Google doSomethingWith_ method.
Is this Google's bug or mine?
At least some members of the Google Map API developer community are of the opinion that "system classes should not be changed. They therefore write "Yes, it's a bug -- the Google developers correctly assume any elements of this.someObject were put there by their own code, and can therefore be safely removed by their own code."
I, on the other hand, argue that the Javascript object model was intentionally created in order to allow arbitrary packages to add arbitrary members and methods to any class or instance, specifically including class Object. The purpose of my extension is to provide real metastructure to the browser-side Javascript environment.
Leaving aside the question of work-arounds (I have some ideas), what does this community say about this question?
Whose bug is this, and what if anything does it say about modularity in Javascript specifically and object-oriented environments in general?
-- TomStambaugh
It's nobody's bug. Javascript provides the flexibility for both what Tom has done & what Google has done. So, both parties are right (as far as the language is concerned) to do what they've done. Javascript doesn't provide a mechanism to resolve the conflict, so we're outside the jurisdiction of the language.
Surely it's SOMEBODY'S bug. It is definitely a bug, because something that worked no longer works.
It says that Javascript thinks it is more important to provide flexibility & isn't very concerned about modularity.
If Tom is paying Google for the use of their code, then he may ask them to change their code, & he may choose to stop doing business with them if they don't.
If Tom isn't paying Google for the use of their code (including the case of Google paying Tom to write code using their code), then he has to live with it. He can request that they change their code. He can make good arguments for why they should change their code. But this is not a bug in their code.
The code in question is the Google Map API. Google makes it available for anyone to use, free of charge. Google is very responsive about bug fixes. I'm not sure that who pays what to whom is very helpful in arriving at a recommendation.
Should Javascript allow such flexibility? If so, should Javascript provide mechanisms to mitigate this sort of conflict?
I don't think this is limited to Javascript. I'm asking a more general question. Many or most object-oriented environments allow developers to extend system classes. A number of object-oriented patterns and idioms virtually require this ability, at least if a developer wants to preserve Liskoff substitutability. As a developer, I think I'm obligated to make my code be a "good citizen" with reasonable things other developers might do, and so I think this is a bug on Google's part. I'm wondering what this community thinks. -- TomStambaugh
Surely it's SOMEBODY'S bug. It is definitely a bug, because something that worked no longer works.
It may be a bug, but it isn't somebody's bug.
The code in question is the Google Map API. Google makes it available for anyone to use, free of charge. Google is very responsive about bug fixes. I'm not sure that who pays what to whom is very helpful in arriving at a recommendation.
Sure it is. It's nobody's bug. The way out depends upon the relevant relationship between Tom & Google. If you're using Google's code for free, you make you case to Google for why you think they should change it, then you work around the fact that they are under no obligation to change.
I don't think this is limited to Javascript. I'm asking a more general question. Many or most object-oriented environments allow developers to extend system classes. A number of object-oriented patterns and idioms virtually require this ability, at least if a developer wants to preserve Liskoff substitutability. As a developer, I think I'm obligated to make my code be a "good citizen" with reasonable things other developers might do, and so I think this is a bug on Google's part. I'm wondering what this community thinks.
I think that an OO system shouldn't allow one module to delete another module's addition to system classes. I also recognize, however, that my way isn't the only way; that there is not necessarily a best way. The thing (see it as a strength or a weakness if you choose) about Javascript is that it provides so much flexibility that what is being a good citizen is far, far from black & white. Both the attitude that nobody should add to system classes & that nobody should indiscriminately delete things from system classes are fine paradigms. To know how to be a good citizen, when in a situation where a particular paradigm is not dictated by the environment, all the parties involved have to come to agreement on which paradigm should be in force. (Which is where the relationships come into it.)
Hmmm. I hope a work-around is possible. I wonder if a new paradigm is emerging from efforts like this. I'm sympathetic to the suggestion that it isn't a "bug" in the classical sense. I've always called things like this "land mines" or "timebombs". I agree with you that being a "good citizen" is neither black nor white. I think the relationships that you mention just above will be more helpful than the follow-the-money approach described earlier. If this were open-source (which the Google API is not), it would be straightforward for me to find and submit a change to the affected Google code that avoids the problem. Since it is not open-source, and heavily obfuscated, such an approach is impossible. It seems to me that a vendor who, like Google, intentionally creates a demand for a proprietary software product has a corresponding higher obligation to maintain that software product than a supplier of an open-source alternative. Google's impressive market capitalization demonstrates, in my view, that making a product free to use does not cause that product to have zero value. Similarly, making an API "free" does not make it's value (to Google) zero, and does not IMHO free the vendor from an obligation to maintain it.
I'm not sure it's relevant, but I just wanted to clarify the impact of Google's code -- the things that it indiscriminately deletes breaks *GOOGLE* code, not mine (though the difference may be academic, since the entire application goes down). In the code fragment I quoted above, the "doSomethingWith_()" method -- a Google method -- crashes because the object it encounters doesn't display the behavior the Google code expects. So it isn't that it crashes MY code, instead my extension causes the Google code to crash. This is part of why I argue that the bug is theirs: they have created code that's fragile (overly so, in my opinion) so that I have to code around their code's shortcomings.
-- TomStambaugh
Personally, I think this is Google's bug. Report it (supplying a UnitTest) and I'm sure they'll fix it. I bet this was just a hole in their test suite. If you're making a framework for a language as dynamic as JavaScript then you have to account for this kind of flexibility. -- IanOsgood