- From: Charles Jolley <charles@sproutit.com>
- Date: Fri, 6 Nov 2009 09:57:53 -0800
- To: Maciej Stachowiak <mjs@apple.com>
- Cc: David-Sarah Hopwood <david-sarah@jacaranda.org>, public-script-coord@w3.org, es-discuss@mozilla.org
> I think the disadvantage of this design is that it puts all the > mutation methods on immutable instances, where they are serve no > purpose other than to throw when called. I think it is cleaner > design for the immutable interface to lack mutation methods, rather > than have mutation methods that always fail. I think designs where > part of the normal workflow puts an object in a state where some > methods always throw is poor OO design. Well, let me argue this for a second... Well designed systems often have objects with an internal state. Features become available or unavailable on that object based on the state. If you try to use a feature while the object is in the wrong state, the object should throw an error. This is good API. It makes it clear to the developer when they try to use the object in the wrong way. The API I'm arguing for envisions the Data object having some internal state [i.e. isEditable] and a part of the API is available or not depending on that state. Additionally, JavaScript often uses the duck-typing pattern [i.e. ignore the "inheritance" of an object and just check its capabilities before acting on it]. This pattern vastly simplifies JS code as you don't have to shuffle references around so often and can reduce memory allocs. That said, I will acknowledge there are many cases where methods that throw are often indicative of bad OO design. I see this mostly in C++ and Java where devs define abstract base classes with lots of methods that do nothing but throw. This is the opposite of what we want. It's ugly and leads to code bloat. In this case though, I would argue that a few if() statements at the front of a primitive or two would actually reduce the amount of code in regular running applications and means you only need to implement one object. > > It's true that ECMAScript has not historically had mutable/immutable > pairs of types, but this is a common pattern in other languages, > such as Objective-C (NSString vs. NSMutableString), Java (String vs. > StringBuilder), various recent Lisp dialects (where there are often > both mutable and immutable lists) and arguably event C++ (const > string and string expose different sets of method). Most of the examples you give here, are statically-types [to various degrees] class-based languages where inheritance chains are integral to the design. This is not the case with JavaScript. The two-class pattern is more important in those cases than it is here. > That being said, I can see how there is some value to aligning with > the evolving ECMAScript pattern. Personally I think of Object.freeze > as a tool for building new types that are meant to be immutable, or > for exporting partially restricted facade interfaces, not as > something one should be doing to random objects in the course of > normal programming. Allow me to withdraw my previous suggestion of freeze(). It's not the right tool for this job. The general pattern though is well established for freeze(), seal() and extensible. I think it would work well here too. -Charles PS. I'm happy to have data object support at all; this isn't really critical to the feature IMO just an argument about which API would be most useful to developers. I think both proposed models would be acceptable.
Received on Friday, 6 November 2009 17:58:39 UTC