Monday, 29 July 2013

Javascript: explicit arguments or config object? When to use which?

G'day:
Just to go off on a tangent... I'm doing Javascript this week, so the puzzling stuff I encounter will probably be JS rather than CFML.

Whilst I know a decent amount about CFML, my JS is... limited. I know enough to get into trouble... I know enough to know when I'm in trouble... but not necessarily enough to get me back out of trouble again.

I'm defining a Javascript "class" (if one will allow them to be called that), eg:

// Person.js
Person = function(){
    // init stuff
}
Person.prototype.getFullName = function(){
    // doing stuff
}
// people.js
me = new Person();
document.write(me.getFullName());

No worries.

Now, I need to pass some argument values into the "constructor" function when I create a new instance of MyClass. I could do this one of two ways (that I'm aware of):

Firstly, one can specify and pass specific arguments:

// Person.js
Person = function(firstName, lastName){
    this.firstName = firstName; 
    this.lastName = lastName; 
}
Person.prototype.getFullName = function(){
    return this.firstName + " " + this.lastName;
}
// people.js
rugbyPlayer        = new Person("Zinzan", "Brooke");
cricketPlayer    = new Person("Shane", "Bond");

console.log(rugbyPlayer.getFullName());
console.log(cricketPlayer.getFullName());

This makes the Person.js file clearer in that one sees the argument names and know exactly what one is doing within init(), but the calling code is more obscure, as one doesn't know what the arguments actually are (although in this example, it's pretty clear).

Or one can pass a config object sort of arrangement:

// Person.js
Person = function(config){
    this.config = config;
}
Person.prototype.getFullName = function(){
    return this.config.firstName + " " + this.config.lastName;
}
// people.js
netballPlayer = new Person({
    firstName: "Irene",
    lastName: "van Dyk"
});
hockeyPlayer = new Person({
    firstName: "Mandy",
    lastName: "Smith"
});

console.log(netballPlayer.getFullName());
console.log(hockeyPlayer.getFullName());

In this example, the init() code is pretty vague, but the calling code is more clear as to what's being passed as what.

Coming from CFML, I err towards the former because specifying arguments (a parallel to <cfargument> tags) seems good and proper, and using the config object approach seems lazy to me.

However I do know that the config object approach certainly is rather popular at the moment / these days.

Now I don't give a rat's arse what's popular, because "popular" just means "liked by hoi polloi", and in general the hoi polloi wouldn't know their arsehole from their elbow. Also I like to sit and play devil's advocate with any new trend, rather than just adopting it. Like juror #8 in 12 Angry Men, I like to automatically challenge ideas whether I agree with them or not, just in case it coerces considerations that I didn't already know out of the woodwork.

But I do like to do things "the best way" (where "best" != "most popular"), and I'm a bit flummoxed as to what is the measure of "the best way" here. I suspect there's a balance to be struck, and this keys on what constitutes "config", and whether everything one passes into the constructor of an object as a matter of course constitutes "config". Or whether sometimes having explicit arguments is "better".

So I don't know how to make an informed decision as to what approach to take here, or whether one is preferably in some situations, and the other preferable in others, or sometimes it's either/or.

One thing I do know... I sure as hell like how CFML gives us so many options / combinations of how to define a method's arguments, and then how to pass them. CFML is cool sometimes.

Anyway... give over... what do you think about all this explicit args / config thing?

Cheers.

--
Adam