# What’s a Configuration Object, and Why Bother Using It?

##### Tutorial Details
• Difficulty: Beginner
• Platform: Flash
• Language: AS3
• Software used: Any editor
• Estimated Completion Time: 20 minutes

It’s a pain to have to change the parameters of a function; you have to change every other call to that function in order to avoid errors. But you can get around this by using just one parameter: a configuration object.

## What It Looks Like

Here’s a silly example of a function for creating a robot:

function generateRobot(arms:int, personality:String):Robot {
var robot:Robot = new Robot();

for (var i:int = 0; i < arms; i++) {
//create arm and add it to robot
}

if (personality == "evil") {
robot.commands = "Destroy mankind.";
}
else {
}
return robot;
}

generateRobot(2, "evil");


Now, here’s the same example, using a configuration object:

function generateRobot(conf:Object):Robot {
var robot:Robot = new Robot();

for (var i:int = 0; i < conf.arms; i++) {
//create arm and add it to robot
}

if (conf.personality == "evil") {
robot.commands = "Destroy mankind.";
}
else {
}
return robot;
}

generateRobot({arms:2, personality:"evil"});


I’ve highlighted the lines that require changing; you can see that there’s not much difference.

## Why Bother?

So if there’s hardly any difference, why would we bother doing it the second way? After all, it actually makes the function a little harder to use; whereas before our IDE would be able to give us this information about the parameters the function expected:

…now it can only give us this:

Suppose you want to add a couple more parameters: one specifying the material to use and another to specify what color its laser should be. That’s not too hard, in either case:

function generateRobot(arms:int, personality:String, material:String, laserColor:String):Robot {
var robot:Robot = new Robot();

for (var i:int = 0; i < arms; i++) {
//create arm and add it to robot
}

if (personality == "evil") {
robot.commands = "Destroy mankind.";
}
else {
}

switch (material) {
case "wood":
//wooden robot
break;
case "steel":
default:
//steel robot
break;
}

robot.laser = new Laser();
robot.laser.color = laserColor;

return robot;
}

generateRobot(2, "evil", "steel", "red");

function generateRobot(conf:Object):Robot {
var robot:Robot = new Robot();

for (var i:int = 0; i < conf.arms; i++) {
//create arm and add it to robot
}

if (conf.personality == "evil") {
robot.commands = "Destroy mankind.";
}
else {
}

switch (conf.material) {
case "wood":
//wooden robot
break;
case "steel":
default:
//steel robot
break;
}

robot.laser = new Laser();
robot.laser.color = conf.laserColor;

return robot;
}

generateRobot({arms:2, personality:"evil", material:"steel", laserColor:"red"});


So far, still not much of a difference. What if you want your robots to all have red lasers by default? Simple again. Without a configuration object, you just need to change the method signature (the function line), and then you can remove the last argument from the function call:

function generateRobot(arms:int, personality:String, material:String, laserColor:String = "red"):Robot {
//this is all the same
}

generateRobot(2, true, "steel");    //I removed the last argument


With a configuration object, it’s a little trickier – though not much:

function generateRobot(conf:Object):Robot {
if (!conf.laserColor) {
conf.laserColor = "red";
}

var robot:Robot = new Robot();

for (var i:int = 0; i < conf.arms; i++) {
//create arm and add it to robot
}

if (conf.personality == "evil") {
robot.commands = "Destroy mankind.";
}
else {
}

switch (conf.material) {
case "wood":
//wooden robot
break;
case "steel":
default:
//steel robot
break;
}

robot.laser = new Laser();
robot.laser.color = conf.laserColor;

return robot;
}

generateRobot({arms:2, personality:"evil", material:"steel"});   //I removed the last argument


Okay. Now suppose you find that you’re setting almost all of your robots to be evil (I mean, why not?), so it’s actually kind of a pain to write “evil” as a parameter every time. Naturally, you want to set “evil” as the default – but you don’t want to set a default material.

The only way you can do this, with a regular set of function parameters, is to switch the order of the personality and material parameters:

function generateRobot(arms:int, material:String, personality:String = "evil", laserColor:String = "red"):Robot {


Ah, but now you have to switch the order of the arguments round on every single function call!

generateRobot(2, "evil", "steel");    //no longer works


A configuration object doesn’t give you this problem. Check it out:

function generateRobot(conf:Object):Robot {
if (!conf.laserColor) {
conf.laserColor = "red";
}
if (!conf.personality) {
conf.personality = "evil"
}

//this is all the same
}

generateRobot({arms:2, material:"steel"});  //no "personality" parameter? no problem!


Neat! All your old generateRobot() function calls will continue to work, but you can create new calls that don’t bother specifying personality.

You can even decide to get rid of the personality parameter altogether:

function generateRobot(conf:Object):Robot {
if (!conf.laserColor) {
conf.laserColor = "red";
}
if (!conf.personality) {
conf.personality = "evil"
}

var robot:Robot = new Robot();

for (var i:int = 0; i < conf.arms; i++) {
//create arm and add it to robot
}

robot.commands = "Destroy mankind.";

switch (conf.material) {
case "wood":
//wooden robot
break;
case "steel":
default:
//steel robot
break;
}

robot.laser = new Laser();
robot.laser.color = conf.laserColor;

return robot;
}


The above version of the function doesn’t refer to conf.personality at all – but you won’t get an error if you still have calls like this:

generateRobot({arms:2, personality:"evil", material:"steel"});


Of course, you might get a few confused users if you have calls like this:

generateRobot({arms:2, personality:"good", material:"steel"});


…since all robots are now evil. But at least the code will compile.

For the same reason, you can change the order of the arguments without it mattering at all, and even add in new parameters that don’t do anything yet:

generateRobot({material:"steel", laserColor:"green", arms:2, voice:"Mr. T"});


## Making It Easier to Set Defaults

The code for setting the defaults is easy to understand so far, but is going to be very annoying to extend if we need to have lots of parameters:

	if (!conf.laserColor) {
conf.laserColor = "red";
}
if (!conf.personality) {
conf.personality = "evil"
}


Let’s write some more general code to cope with it:

	var defaults:Object = {
laserColor:red,
personality: "evil"
}

for (var key:String in defaults){
if (!conf[key]) {
conf[key] = defaults[key];
}
}


That for loop may be a little confusing, so I’ll break it down. First, look at this:

	for (var key:String in defaults){
trace(key);
}


This is a for...in loop, which will output the names of the keys inside the default object:

laserColor
personality


Next, look at this line:

trace(defaults["laserColor"]);


This will output red – it’s the same as writing trace(defaults.laserColor).

Following on from that, look at this example:

var example:Object = { demo: "test" };
trace(example["demo"]);
trace(example["foo"]);


What do you think this will output?

Well, example["demo"] is the same as example.demo, which equals "test". But example.foo does not exist, so example["foo"] will return null. This means that !example["foo"] (note the exclamation mark) will be equivalent to true.

Put that all together, and you should be able to understand why this code works:

	var defaults:Object = {
laserColor:red,
personality: "evil"
}

for (var key:String in defaults){
if (!conf[key]) {
conf[key] = defaults[key];
}
}


Give me a shout in the comments if you need a hand!

### I Want More!

For an even quicker version, try this:

function generateRobot(conf:Object = null):Robot {
var conf:Object = conf || {};
var defaults:Object = {
laserColor:red,
personality: "evil"
}

for (var key:String in defaults){
conf[key] = conf[key] || defaults[key];
}


The change in Line 1 (and new Line 2) means that even the conf object itself is optional, so you can just call generateRobot(). (Of course, you’ll need to change the code to deal with the values that don’t currently have defaults.)

As I mentioned above, the IDE can’t give you any tips about what parameters a function is expecting, if that function uses a configuration object. This is a major drawback, as it can make your code really hard to use; you have to remember which parameters go in the conf object, as well as all of their names and types.

But we can still display this information to the coder when it’s needed; we just have to do so manually, like so:

			/**
* Generate a robot, based on the parameters given.
* @param	conf	Configuration object. Expects:
* arms 		(int)		Number of arms robot should have.
* personality 	(String)	Personality of robot. Can be "evil" or "good". Defaults to "evil".
* material		(String)	What the robot should be made out of. Can be "steel" or "wood" at this time.
* laserColor	(String)	Color of the robot's laser. Defaults to "red".
* voice		(String)	Vocal stylings of robot. Currently not implemented.
* @return	The finished robot.
*/
function generateRobot(conf:Object):Robot {
//
}


Now, if I start to write a call to this function in FlashDevelop (my IDE of choice), I see this:

Sure, it’s a bit of a pain to keep this manually updated, but in many cases it’s worth it.

## Conclusion

I’m not claiming that you should use a configuration object for every single function you create from now on; just think of it as another useful tool in your arsenal.

Personally, I find it a particularly useful pattern whenever I’m building the first draft of some set of classes that all need to work together. The added flexibility of a conf gives me so much more flexibility, freeing me up to zip around all the different functions and changing how they call one another, without worrying about breaking the code by inserting or removing a parameter.

Remember the benefits:

• It’s easy to add and remove parameters (at either end).
• It’s easy to set default values.
• You don’t have to worry about the order of the parameters.

There are drawbacks to using simple objects like I have, though – especially if you do so in a project that’s past the prototyping stage. Check out the great comments below for more details!

• Johan

I think that config-objects should be used rarely. One of the strenghts with AS3 (and other compiled, typed languages) is that you’ll get notified of type errors and missing parameters during compile-time.

• http://krasimirtsonev.com Krasimir Tsonev

An interesting article indeed. What I don’t like is the idea to pass simple objects. It is much better to use Value objects. Sooner or later someone will not add comment above the method and it will be really difficult to find out what exactly you have to add or not as a property of the object. Something like that:

class RobotConfigVO {
public var arms:int
public var personality:String = “evil”;
public var material:String = “wood”;
public var laserColor:String = “red”;
public var voice:String = “”;
}

I had some very bad experience with the usage of simple objects like parameters. Very often these objects are passed between different modules and in most of the cases is difficult to follow the app’s flow.

• Jason

I’m going to have to agree with Krasimir. I’m not a big fan of 100% untyped configuration objects.

I guess a general rule for me is: Never require anything to be set by a configuration object.
If you want to use them for optional parameters, then I can see both sides of the issue, but if some value must be set every time, don’t make it part of a CO.

• http://michaeljameswilliams.com/ Michael James Williams

I was hoping someone would bring this up :)

Yes, I agree: if you use this in a project that’s moved past the prototype stage, you need to bake the types in somehow – either by using an actual class, as you have here, or by scrapping the config object altogether and using regular typed parameters.

However, if you’re trying to develop quickly, by yourself, then I find the added overhead of maintaining separate VO classes can get in the way, and slow me down almost as much as using typed parameters would. YMMV.

• http://www.theandroidgalaxy.com sharonlewis

One of the best actionscript tutorials that I had ever read, I actually understood all :D

• http://michaeljameswilliams.com/ Michael James Williams

Thanks :)

• http://pierrechamberlain.ca/blog/ Pierre Chamberlain

Nice article. I always hesitated on using generic object as Configuration objects for function calls, but I think you make a convincing point with the ASDoc. It’s not huge to maintain, plus it keeps you a bit more on the ball on how to use that method since each parameters will be fully described.

The only disputable aspect of this technique would be performance. Any type of “engine” framework / library would probably use a dedicated value-object Class to pass the parameters (if done in this comparable manner), or just with multiple method arguments. I would assume that Object or * type would run slower for large iterations of method calls compared to a known, strict data-type.

But hey! TweenLite/TweenMax uses conf-objects all over the place! :)

• miels

function generateRobot(conf:Object = {}):Robot {

won’t even compile.

• Jason

Good catch – you can’t specify default values for Objects as far as I know (other than specifying it as null). So, the workaround would be to make the default value null and handle that in your code.

• http://www.mortenclaussen.com Morten

conf:Object = {}
is the same as
conf:Object = new Object();

Just like
arr:Array = []
is the same as
arr:Array = new Array();

And you cant initialize parameters.

• http://michaeljameswilliams.com/ Michael James Williams

Ah, that was sloppy of me. I wrote = null originally, thought = {} would be even simpler, and didn’t bother to check. Sorry. I’ve updated the post.

• http://www.plugin.io Gary Paluk

I’m sorry to say it but I’m in the “DO NOT DO THIS” camp. It can easily lead to bugs, what you are proposing is to create untyped code. One of the strengths of AS3 is that we can use typed code to ensure that parameters are typed correctly and another useful function is the IDEs ability to show parameters that are available in the API. If your making the point to avoid large numbers of parameters being sent to a method call, the solution is to actually create a RobotConfiguration object that contains all the typed parameters that you would like available. This will ensure that our IDE will present us the options that we are allowed to change and is well typed. Our Robot constructor can now accept a RobotConfiguration object as its parameter.

• http://michaeljameswilliams.com/ Michael James Williams

Hey everyone, thanks for the great comments about the dangers of using a simple object with untyped properties. I went back and forth about whether to include this in the post – I’m glad you set me straight :)

I’ve updated the post to recommend future readers check out the comments to get a better idea about the possible issues.

• http://xtdstudios.com Gil Amran

You taking something good in the language, and throw it to the trash…
AS3 is typed language! And it is good for a reason!

Types are meant to make the code more safe! types (Classes and interfaces) are the contract you must fulfill to use it without problems… use Objects send a blank page. No contract…

It is a GOOD think that it does not compile if you add a parameter! This is how you know where you did not fulfill the function contract! I don’t want to find it out on run-time (Maybe find it)

Config-Object might be good for 100 lines of code projects, where order and structure doesn’t matter… But if you go to 1,000 lines and above (Easy to get there) using object as a parameter is a BIG no no!

Think of it, why are you using Classes? Interfaces? for the order and structure. Same for types.
You can also create one huge static class, with 1000 functions… But is it good?
Don’t mass it up just because you can.

Gil Amran

• http://michaeljameswilliams.com/ Michael James Williams

Yeah, I kinda screwed up here. Should have gone on to talk about interfaces, at least.

I don’t disagree with what you said – compiler errors, enforced order, strong typing; all of that is great, and types are a great strength of AS3.

However, sometimes it’s useful to break the rules. Like I said, it’s another useful tool in your arsenal, particularly handy when you’re writing a first draft, or otherwise making quick changes. And as Pierre pointed out, Greensock uses the pattern everywhere.

But I don’t deny that it has its cons.

• Gil Amran

The problem when you’re relaying on that when building a POC is that you pass this config-object to some other functions that uses it too, and maybe pass it even more, and maybe even change it…

You don’t know…
Well you wrote the code… you know!
Yea, you’ll know! BUT only in run-time.

So? What’s the problem in getting errors in run-time!?
You just don’t get to all the corners of your code in run-time (Compiler does!)

Sure you can get to all the corners of your code!? Yes. No? maybe? 50%? Yes AND No?

To some up all that I’m saying:
Don’t relay on your brine only! You have the tools! use them! don’t abuse them.

Greensock uses this to his power. He only used this pattern to get parameters from outside. He wanted to be as flexible as possible. He said “I don’t know what you give me, I don’t care, and I’ll tween it”.
If you look inside his code, you’ll see that he did’t use this pattern internally. He did it only to get external parameters to tween.
He also said “You might crash in run-time, if YOU are wrong”.

How about some Interfaces tut next time? ;-)

And I hope that I don’t sound too harsh on you!
Gil

• http://michaeljameswilliams.com/ Michael James Williams

Not harsh at all! This is all good feedback, and I appreciate it.

I think perhaps I’ve been spending too much time doing JavaScript… I’ve got a bit too used to coding without strong types :/