- Notifications
You must be signed in to change notification settings - Fork7
Traits, Talents & Annotations for NodeJS.
License
CocktailJS/cocktail
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Cocktail is a small but yet powerful library with very simple principles:
- Reuse code
- Keep it simple
Cocktail explores three mechanisms to share/reuse/mix code:
- Extends: OOP inheritance implemented in Javascript.
- Traits: Traits are composable behavior units that can be added to a Class.
- Talents: Same idea as Traits but applied to instances of a Class.
Cocktail has only one public methodcocktail.mix()
but it relies onannotations
to tag some meta-data that describe the mix.
Annotations are simple meta-data Cocktail uses to perform some tasks over the given mix. They become part of the process but usually they are not kept in the result of a mix.
varcocktail=require('cocktail'),MyClass=function(){};cocktail.mix(MyClass,{'@properties':{name:'default name'}});
In the example above we created a "Class" namedMyClass, and we use the@properties
annotation to create the propertyname and the correspondingsetName andgetName methods.
As it was mentioned before, annotations are meta-data, which means that they are not part ofMyClass or its prototype.
Using cocktail to define a class is easy and elegant.
varcocktail=require('cocktail');cocktail.mix({'@exports':module,'@as':'class','@properties':{name:'default name'},constructor:function(name){this.setName(name);},sayHello:function(){return'Hello, my name is '+this.getName();}});
In this example our class definition uses@exports
to tell the mix we want to export the result in themodule.exports
and@as
tells it is a class.
Traits areComposable Units of Behaviour (You can read more fromthis paper).Basically, a Trait is a Class, but a special type of Class that has only behaviour (methods) and no state.Traits are an alternative to reuse behaviour in a more predictable manner. They are more robust thanMixins, orMultiple Inheritance since name collisions must be solved by the developer beforehand. If you compose your classwith one or more Traits and you have a method defined in more than one place, your program will fail giving no magic ruleor any kind of precedence definition.
Enumerable.js
varcocktail=require('cocktail');cocktail.mix({'@exports':module,'@as':'class','@requires':['getItems'],first:function(){varitems=this.getItems();returnitems[0]||null;},last:function(){varitems=this.getItems(),l=items.length;returnitems[l-1];}});
The class above is a Trait declaration for an Enumerable functionality.In this case we only definedfirst
andlast
methods to retrieve thecorresponding elements from an array retrieved bygetItems
methods.
List.js
varcocktail=require('cocktail'),Enumerable=require('./Enumerable');cocktail.mix({'@exports':module,'@as':'class','@traits':[Enumerable],'@properties':{items:undefined},'@static':{/* factory method*/create:function(options){varList=this;returnnewList(options);}},constructor:function(options){this.items=options.items||[];}});
The List class uses the Enumerable Trait, the getItems is defined by the@properties
annotation.
index.js
varList=require('./List'),myArr=['one','two','three'],myList;myList=List.create({items:myArr});console.log(myList.first());// 'one'console.log(myList.last());// 'three'
Talents are very similar to Traits, in fact a Trait can be applied as a Talent in CocktailJS.The main difference is that a Talent can be applied to anobject ormodule.So we can define a Talent as aDynamically Composable Unit of Reuse(you can read more fromthis paper).
Using theEnumerable example, we can use a Trait as a Talent.
index.js
varcocktail=require('cocktail'),enumerable=require('./Enumerable'),myArr;myArr=['one','two','three'];cocktail.mix(myArr,{'@talents':[enumerable],/* glue code for enumerable talent*/getItems:function(){returnthis;}});console.log(myArr.first());// 'one'console.log(myArr.last());// 'three'
We can also create a new Talent to define the getItems method for an Array to retrive the current instance.
ArrayAsItems.js
varcocktail=require('cocktail');cocktail.mix({'@exports':module,'@as':'class',getItems:function(){returnthis;}});
And then use it with Enumerable:
varcocktail=require('cocktail'),enumerable=require('./Enumerable'),arrayAsItems=require('./ArrayAsItems');varmyArr=['one','two','three'];cocktail.mix(myArr,{'@talents':[enumerable,arrayAsItems]});console.log(myArr.first());// 'one'console.log(myArr.last());// 'three'
- Install the module with:
npm install cocktail
or add cocktail to yourpackage.json
and thennpm install
- Start playing by just adding a
var cocktail = require('cocktail')
in your file.
Guides can be found atCocktailJS Guides
The latest documentation is published atCocktailJS Documentation
A Cocktail playground can be found incocktail recipes repo.
In lieu of a formal styleguide, take care to maintain the existing coding style. Add unit tests for any new or changed functionality.
Add your unit and/or integration tests and execute
$ npm test
$npm run unit
$npm run integration
$ npm run lint
Runnpm test
to check lint and execute tests
$ npm test
$ npm run coverage
seeCHANGELOG
Copyright (c) 2013 - 2016 Maximiliano Fierro
Licensed under the MIT license.
About
Traits, Talents & Annotations for NodeJS.