Enforcing object interfaces

C

carton

Any opinions on this code as part of a general purpose framework?

I expect people will have varying opinions on the use of $ in the
property names. I did it for several reasons: 'interface' is
reserved,
I didn't want to step on 'constructor', and a 'prototype' property on
a
non-function might be confusing.

Gadget is a usage example to make it easier to follow what I'm doing.

var Gadget = createConstructor({

/*
* $inherit specifies another constructor to 'inherit' from.
* The specified constructor must be one that was returned
* by a previous call to createConstructor.
*/
$inherit: Widget,

/*
* This is a list of the methods to be exposed publicly
* on the objects.
*/
$interface: ['method1', 'method2'],

$prototype: {
method1: function() { ... },
method2: function() { ... },
method3: function() { ... },
data1: 'blah'
},

$constructor: function() {
/* Usually call Widget constructor first.
* Don't use Widget.call because that applies an interface
* wrapper that we don't use. See createConstructor below.
* The $constructor property is added as an alternative.
*/
Widget.$constructor.call(this, 'arg1', 'arg2');

/* other normal constructor stuff */
}
});

var createConstructor = function() {

/*
* createInterfaceWrapper takes a list of methods names
* and creates a function that can be applied to an
* object to create a wrapper object that only exposes
* the methods in the list. This is really the point
* of the whole exercise.
*/
function createInterfaceWrapper( methods ) {
return function( obj ) {
var wrapper = {};

for (var i=0; i < methods.length; ++i) {
var method = methods;

wrapper[method] = function(method) {
return function() {
return obj[method](arguments);
};
}(method);
}

return wrapper;
}
}

/*
* Helper function for creating a new object that
* inherits from some prototype object
*/
function inherit(obj, prototype) {
var F = function() {};
F.prototype = prototype;
var newObj = new F();

for (i in obj) {
//Do I need hasOwnProperty here?
newObj = obj;
}

return newObj;
}

return function(params) {
/* I've left out handling of default behavior for properties of
* params that might be missing
*/

params.$interface =
params.$interface.concat(params.$inherit.$interface);

var interfaceWrapper = createInterfaceWrapper(params.
$interface);

var ctor = function() {
params.$constructor.apply(this, arguments);
return interfaceWrapper(this);
};

ctor.prototype = inherit(params.$prototype,
params.$inherit.prototype);

/*
* Save $interface and $constructor for use by other
* constructors that want to 'inherit' from this one
*/
ctor.$interface = params.$interface;
ctor.$constructor = params.$constructor;

return ctor;
}
}();
 
M

MartinRinehart

carton said:
I expect people will have varying opinions on the use of $ in the
property names. I did it for several reasons: 'interface' is
reserved,

The closest thing to a general-purpose set of JavaScript conventions I
know is:

http://javascript.crockford.com/code.html

But like all conventions, it doesn't cover everything. It bans the '$'
in names, but has no provision for name/reserved word conflict
resolution. You might try using the Python convention which is to
append an underscore: interface_.
 
H

Henry

Any opinions on this code as part of a general purpose
framework?

Wouldn't it seem more sensible to determine the practicality/value of
a general purpose framework first and then, if not rejected, worry
about what code goes into it?
I expect people will have varying opinions on the use of
$ in the property names.

Are the names machine generated? If not, disregarding the specified
convention for the use of $ symbols in identifiers is not a good idea.
Professional programmers would never knowingly do that, and repeating
the mistakes of armatures, no matter how widespread, is no
justification.
I did it for several reasons: 'interface' is reserved,
I didn't want to step on 'constructor', and a 'prototype'
property on a non-function might be confusing.

How hard were you trying if you did not see obvious alternatives?
Gadget is a usage example to make it easier to follow what I'm doing.

var Gadget = createConstructor({

You have not said what this is supposed to be for; what it is intended
to achieve or which problems it is intended to solve.
 
C

carton

Wouldn't it seem more sensible to determine the practicality/value of
a general purpose framework first and then, if not rejected, worry
about what code goes into it?

If you want to start that discussion then I'm interested in your
opinion.
Are the names machine generated? If not, disregarding the specified
convention for the use of $ symbols in identifiers is not a good idea.
Professional programmers would never knowingly do that, and repeating
the mistakes of armatures, no matter how widespread, is no
justification.

If it is so important then I can change it. No need to be so
aggressive. Opinions such as this are why I'm posting this in the
first place.

You have not said what this is supposed to be for; what it is intended
to achieve or which problems it is intended to solve.

It is a helper function for creating a constructor that allows the
specification of a restricted public interface.
 
J

Joost Diepenmaat

carton said:
If it is so important then I can change it. No need to be so
aggressive. Opinions such as this are why I'm posting this in the
first place.

Opinions on $ are strong in part because it isn't just a convention,
it's part of the spec, ecma-262 section 7.6:

"This standard specifies one departure from the grammar given in the
Unicode standard: The dollar sign ($) and the underscore (_) are
permitted anywhere in an identifier. The dollar sign is intended for
use only in mechanically generated code."

It is a helper function for creating a constructor that allows the
specification of a restricted public interface.

Personally, I'm wary of attempts at creating enforced private
interfaces, mostly because they seem to serve no purpose, but also
because the only way to do that in currently widespread ES
implementations is to use closures, which seems like overkill.

The situation is more or less the same in Perl, which I happen to know
very well, and I've never seen much use for enforced private
properties/methods there either.
 
C

carton

Opinions on $ are strong in part because it isn't just a convention,
it's part of the spec, ecma-262 section 7.6:

"This standard specifies one departure from the grammar given in the
Unicode standard: The dollar sign ($) and the underscore (_) are
permitted anywhere in an identifier. The dollar sign is intended for
use only in mechanically generated code."

Thank you, I didn't realize that.
Personally, I'm wary of attempts at creating enforced private
interfaces, mostly because they seem to serve no purpose, but also
because the only way to do that in currently widespread ES
implementations is to use closures, which seems like overkill.

The situation is more or less the same in Perl, which I happen to know
very well, and I've never seen much use for enforced private
properties/methods there either.

This is the classic debate about the need to enforce the boundary
between the interface and the implementation. The only alternative is
to trust users of your objects to 'follow the rules' and not access
properties that you may want to change. For small projects perhaps it
doesn't matter but for larger projects with multiple developers I
consider enforcement a necessity.

However, considering that enforcement has a runtime overhead in
javascript it is probably worthwhile to provide a flag to enable/
disable it so we can turn it off for production releases but still
develop and run unit tests with the enforcement enabled. That should
be easy to add to my implementation.
 
J

John G Harris

Any opinions on this code as part of a general purpose framework?

I expect people will have varying opinions on the use of $ in the
property names. I did it for several reasons: 'interface' is
reserved,
I didn't want to step on 'constructor', and a 'prototype' property on
a
non-function might be confusing.

Gadget is a usage example to make it easier to follow what I'm doing.
<snip>

You're using javascript to implement a new OO language. Why?

* Helper function for creating a new object that
* inherits from some prototype object
<snip>

In other OO languages a function that creates new objects is called a
constructor, not a 'helper'.

John
 
C

carton

You're using javascript to implement a new OO language. Why?

That's a troll, but I admit I didn't properly explain my purpose up
front. See my other responses to Henry and Joost for a better
explanation of the purpose of the code.
<snip>

In other OO languages a function that creates new objects is called a
constructor, not a 'helper'.

In Javascript a constructor is a function intended to be called with
'new'. Functions that create objects but which aren't intended to be
invoked with 'new' are usually called factories. I could call this
function a factory instead of a helper, but it's just a comment so it
doesn't really matter.
 
B

Bruno Desthuilliers

carton a écrit :
(snip)
This is the classic debate about the need to enforce the boundary
between the interface and the implementation. The only alternative is
to trust users of your objects to 'follow the rules' and not access
properties that you may want to change. For small projects perhaps it
doesn't matter but for larger projects with multiple developers I
consider enforcement a necessity.

Python relies on a very simple naming convention to denote interface
from implementation, and it is proven by experience to JustWork(tm) even
on large projects with multiple developers.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,226
Members
46,815
Latest member
treekmostly22

Latest Threads

Top