Picture of Kev Adsett
Extend and Mutate
by Kev Adsett - Tuesday, 8 October 2013, 9:14 AM
 

Following on from the previous discussion about OOP principles in Adapt, Fabien, Gavin McMaster (a fellow programmer at Kineo) and myself have now developed an OOP framework which I am optimistic about.

I understand there is some concern in the community about the flaky nature of using 'super' in JavaScript. This concern is well-founded; infinite recursion, loss of scope, single-level inheritance - these are all hurdles that need jumping for anyone wanting to achieve a semblance of OOP principles in JavaScript. 

I am confident that we've managed to successfully jump those hurdles in a way that: 

  • Is easy for any developer to implement
  • Creates a robust plugin-ready architecture
  • Greatly reduces code duplication

I have conducted some unit tests, attached here, and am very interested in hearing if anyone else has some ideas of what they'd want to see tested.

 

When would we use this?

It's important to note that there are two mechanics at work here: extend and mutate. While very similar, these two functions serve different purposes.

Extend

This is used in a way that will be familiar to those used to working in an Object-oriented language. You can define an object, and then extend that object to create 'child' objects, which inherit methods and properties from their parent. They are able to override parent methods, but have access to those methods by simply calling _super(). Parameters can be passed in to the function call as per normal. 

This would be used both in the core and potentially in plugins too.

An example inheritance chain in Adapt's core:

AbstractView > ComponentView > QuestionView > MCQView > GMCQView

Mutate

This is similar to extend, but instead of creating a new object which inherits from a 'super' object, you can, in a non-destructive and non-invasive way, modify an object without completely rewriting it. The makes it perfect for creating plugins which need to modify some element of the core behaviour without ever needing to touch the core code.

Using the example above, a plugin could 'mutate' ComponentView, and all the child objects will then inherit any mutated functions and properites.

AbstractView > ComponentView---MutatedComponentView > Question > MCQ etc

The great thing about this is that mutated object functions can call their original, non-mutated counterparts by calling _original().

An example plugin which mutates one of the core objects is the 'triggered' plugin. This overrides ComponentView's "initialise" and "render" functions. Instead of writing those out in full and adding new functionality, it simply calls this._original() and then adds the new code in the lines which follow.

It'd be good to get some feedback on this. To run the unit tests attached, simply launch testing/mutate_extend/tests.html

Picture of Chris Jones
Re: Extend and Mutate
by Chris Jones - Tuesday, 8 October 2013, 10:10 AM
 

Hi Kev,

Just a heads up on test.js, that you attached...

When you are asserting an expectation in an "it" func, use expect.js to assert the condition otherwise the test just shows as passing even if its not.

For example:

it("should extend successfully", function(){
var testView2 = testView.extend({});
var test = new testView2();
return test != undefined;
});

should be something like:

it("should extend successfully", function(){
var testView2 = testView.extend({});
var test = new testView2();
expect(test).to.not.be(undefined);
});

See https://github.com/LearnBoost/expect.js/ for more assertions.

 

 

Picture of Kev Adsett
Re: Extend and Mutate
by Kev Adsett - Tuesday, 8 October 2013, 10:49 AM
 

Hi Chris, thanks for your reply. I have to admit I'm brand new to unit tests so help on that score is always welcome! 

I've rewritten the unit tests with that in mind (attached).

Picture of Chris Jones
Re: Extend and Mutate
by Chris Jones - Tuesday, 8 October 2013, 1:02 PM
 

No probs, unit testing can be a powerful tool when used right, but it can be tricky to get the hang of. Especially with so many different frameworks out there.