OCM made simple

Warning OCM use and abuse of almost all other deepjs core tools. So OCM should only be studied when you're feeling confortable with them.

OCM means Object Capability Model (or here Object Capability Manager).

To fully understand what is it : imagine that you want a method that do something different depending on certains variables.

Let's compare...

Classical approach
var user = null;
var myFunc = function(){
	if(user)
		return "hello "+user.name;
	return "hello. please login."
}
deep.log(myFunc()); // => output "hello. please login."
user = { name:"John" };
deep.log(myFunc()); // => output "hello John.": 
OCM approach
var user = null;
var myFunc = deep.ocm({
	"public":function(){
		return "hello. please login.";
	},
	"user":function(){
		return "hello "+user.name;
	}
});
deep.log(myFunc("public")()); // => output "hello. please login."
user = { name:"John" };
deep.log(myFunc("user")()); // => output "hello John.": 

Keep in mind that OCM, here (in deepjs), means Object Capabilities Manager.

Its aim is to provide facilities to manage objects capabilities depending on certain flags.

Lets call those flags 'modes'.

When you design your object through such manager, this manager holds the different models/aspects of your object, associated to their own mode(s).So a manager is just a set of object/method/identities/capacities/aspects associated to particular modes.

The place where manager keeps those models is called here 'inner layer'. (it's safely holded in local closure).

Ok. Now, compared to first conditionnal example : you didn't gain to much and you need to manage a second variable (i.e. the 'mode').

We agree...

But imagine now that you need to add another mode, as 'admin'.

With the conditionnal example : you will need to modifiy your code and do something like :
var user = null;
var myFunc = function(){
	if(!user)
		return "hello. please login.";
	else if(user.admin)
		return "hello admin";
	else
		return "hello " + user.name;
}
user = { name:"John", admin:true };
//...
deep.log(myFunc()); 		// => output "hello admin":

(i.e. you need to dive into conditionnal branching design).

With OCM : you simply do this :
var user = null;
var myFunc = deep.ocm({
	"public":function(){
		return "hello. please login.";
	},
	"user":function(){
		return "hello "+user.name;
	},
	"admin":function(){
		return "hello admin";
	}
});
user = { name:"John" };
//...
deep.log(myFunc('admin')()); // => output "hello admin"

You could start to see which benefits OCM gives : code stills clear and separated, and you could easily add or modify mode(s). Each time you need to refactor or add more capabilities/aspects, you never need to change all conditionnal checks in all related functions.

You only need to define particular mode(s).

Now, you're asking you : Ok, it seems to be cool. but...
  • what if you have common code used by different modes?
  • it's not really modular, and could be error prone, if you need to always provides the modes to the manager
  • what if you want to use method or objects without needing to know if it's an OCManager or current modes?
  • How could you make the difference?
  • etc.

Ok. Lots of questions...

So let's continue.

Sharing code between modes

As you work with deepjs and aspects, you could obviously use internal inheritance and backgrounds/flatten to manage common behaviours (or datas) between ocm modes.

var myManager = deep.ocm({
	mode1:{
		test:1
	},
	mode2:{
		_backgrounds:["this::../mode1"],
		title:"hello world"
	},
	mode3:{
		_backgrounds:["this::../mode2"],
		description:"mode 3 description"
	}
});
myManager.flatten(); // seek after and apply any backgrounds in inner layer (see deep.flatten docs)
//...
deep.log("mode1 : ", myManager("mode1"));	// output : mode1 : Object { test=1}
deep.log("mode2 : ", myManager("mode2"));	// output : mode2 : Object { test=1, title="hello world"}
deep.log("mode3 : ", myManager("mode3"));	// mode3 : Object { test=1, title="hello world", description="mode 3 description"}