Protected Protocol

Irakli Gozalishvili rfobic at gmail.com
Mon Apr 2 08:59:51 PDT 2012


Hi David, 

Your protected work reminds me a lot of what we did with `namespcase` module in jetpack:
https://addons.mozilla.org/en-US/developers/docs/sdk/latest/packages/api-utils/namespace.html
Which I also blogged about some time ago: http://jeditoolkit.com/2012/03/15/namespaces.html#post

In contrast to this work though namespaces are not class centric and you can use more than one namespace per object. We also use weak maps to implement that.     

> I have made obvious by juxtaposing both examples that JavaScript
> requires from the programmer to choose between encapsulation and
> inheritance. Indeed, as demonstarted above, encapsulation requires a
> shared scope.
> 
> 


I totally agree that with this pain point, but hopefully private names will help this. Still I think that there are other expression problems with classes that could be elegantly solved using clojure like protocols that I have posted other day:

http://jeditoolkit.com/2012/03/21/protocol-based-polymorphism.html#post
https://mail.mozilla.org/pipermail/es-discuss/2012-March/021603.html

Unfortunately I did not got much of a feedback ;)
Cool to see others exploring this area!

Regards
--
Irakli Gozalishvili
Web: http://www.jeditoolkit.com/


On Sunday, 2012-04-01 at 15:28 , David Bruant wrote:

> Hi,
> 
> A while ago, I posted a challenge on es-discuss [1]. It was a challenge
> related to code reuse, modularity and composition. There has been an
> interesting suggestion [2] [3] which left me a bit unsatisfied since
> relying on constructor arguments while it may not be always possible to
> do that.
> What I describe as the "protected protocol" is my response to my own
> challenge.
> Before explaining it, I'd like to take a step back and discuss about the
> object oriented properties of JavaScript.
> 
> 
> Two expected properties of object-oriented languages are encapsulation
> and inheritance.
> 
> Encapsulation allows to define objects which can only be interacted with
> through a given an interface, thus hiding implementation details. In the
> long run, encapsulation makes the maintenance of components easier since
> the implementation of an object can be changed without affecting its
> clients.
> 
> Encapsulation can be implemented in JavaScript. One usual way is to do
> as follow:
> 
> function Storage(){
> var array = Array.prototype.slice.call(arguments, 0);
> 
> return {
> add: function(e){
> array.push(e);
> },
> read: function(i){
> return array[+i];
> }
> };
> }
> 
> Here, access to the array is restricted to the interface ("add" and
> "read" methods).
> 
> 
> Inheritance allows to better reuse code by specializing classes.
> This can be implemented as well, usually with this pattern:
> 
> function Storage(){
> this.array = Array.prototype.slice.call(arguments, 0);
> }
> 
> Storage.prototype = {
> add: function(e){
> this.array.push(e);
> },
> read: function(i){
> return this.array[+i];
> }
> };
> 
> 
> function StorageWithDeletion(){
> Storage.call(this); // equivalent to "super";
> }
> 
> StorageWithDeletion.prototype = Object.create(Storage.prototype);
> StorageWithDeletion.prototype.delete = function(i){
> delete this.array[+i];
> };
> 
> 
> To define a storageWithDeletion, there is no need to redefine the add
> and read method. To extend Storage, StorageWithDeletion here only needs
> access to the Storage function in the global scope (or Storage module
> when these will be deployed). This has the nice property that Storage
> and StorageWithDeletion can be defined in different files since they
> don't need to share a common function scope
> 
> I have made obvious by juxtaposing both examples that JavaScript
> requires from the programmer to choose between encapsulation and
> inheritance. Indeed, as demonstarted above, encapsulation requires a
> shared scope.
> 
> Solutions where Storage and StorageWithDeletion would be defined with a
> shared scope could be explored, but it would require to define both in
> the same file, which, I don't want to be a necessity.
> 
> The trick of the protected protocol is that encapsulation does not
> really require a shared scope, it's just the most natural way to do it
> in JavaScript.
> 
> When a method located in the prototype chain of an object is called, its
> 'this' references the object from which the method has been called.
> Programmers have naturally stored the state of an object as own (public)
> properties of the object as it's the most natural way to bind
> information to an object.
> It doesn't have to be this way, though. WeakMaps offer an
> straightforward API to bind information to an object and it is not
> necessary to share this WeakMap with the rest of the world.
> 
> 
> The protected protocol and an example of how to use it can be found at
> [4] (which is a bit different than a version I tweeted earlier [5]).
> 
> The most important part in my opinion is that the Person.js and
> ComputerSavvyPerson.js are defined in 2 different files. The only thing
> the latter needs is a reference to the constructor it inherits from
> (here, Person).
> 
> Things that are expected to be secret can be kept as such. First, a
> Person's secret doesn't leak, second, even a ComputerSavvyPerson's
> secret doesn't leak. A bit more tricky was to make that defining a new
> subclass doesn't leak secrets of the base class.
> 
> In my opinion, the boilerplate code for this to work is minimal enough,
> but I'm interesting on feedback on this aspect. Regardless, the code of
> the constructor and of the prototype methods are clean of boilerplate
> code and only require to use the "Protected(this)" convention when
> intending to work with private-to-the-inheritance-tree parts of the
> object-state.
> 
> The implementation of the 2 necessary functions take 60 lines which is
> rather reasonable.
> 
> So all the properties I expected are here. On the negative side,
> prototype object equality had to be broken for the sake of preventing
> leaks of "protected" properties, so instanceof is necessarily broken. I
> think it's not a big deal since I could reimplement one myself if really
> necessary.
> 
> It's ready for private names and these would need to be defined inside
> the "declaration code" in order for them not to leak outside.
> I intuit that assuming class syntax can be embedded in a function, I
> could wrap it and add support for the Protected convention if I want to.
> 
> Anecdotes:
> 1) In Person.js, I've been burned by non-lexical this when writing the
> code that increased the age over time. We really need functions with
> lexical this :-)
> 2) After some feedback by Brendan on Twitter, I've created a
> WeakMap.prototype.getset function following a discussion we had on
> es-discuss about setting a value when there is not already one.
> 
> 
> I'm interested in any feedback, opinions or questions you'd have.
> 
> Thanks,
> 
> David
> 
> [1] https://mail.mozilla.org/pipermail/es-discuss/2012-March/021292.html
> [2] https://mail.mozilla.org/pipermail/es-discuss/2012-March/021304.html
> [3] https://gist.github.com/2053624
> [4] https://gist.github.com/2279059
> [5]
> https://gist.github.com/c7d4947b41936680810d/a531bd4412b67dc0fed180d1d776314bf8c4747b
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org (mailto:es-discuss at mozilla.org)
> https://mail.mozilla.org/listinfo/es-discuss
> 
> 


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20120402/d5f8f0db/attachment-0001.html>


More information about the es-discuss mailing list