6. How do I compose things?
Find repeated patterns or duplications in your
code and refactor them into reusable parts.
7. A simple example
var obj1 = {
message: 'hello world!',
sayHi: function () {
alert(this.message);
}
};
var obj2 = {
message: 'hey!',
sayHi: function () {
alert(this.message);
}
};
obj1.sayHi(); // 'hello world!'
obj2.sayHi(); // 'hey!'
8. A simple example
var obj1 = { message: 'hello world!' };
var obj2 = { message: 'hey!' };
var alerter = {
sayHi: function () {
alert(this.message);
}
};
obj1 = _.extend(obj1, alerter);
obj2 = _.extend(obj2, alerter);
obj1.sayHi(); // 'hello world!'
obj2.sayHi(); // 'hey!'
9. ● Maximize code reuse
● Use objects without classes
● Avoid traps of single-parent inheritance
Mixins
10. Mixins in the wild
● Marionette Behaviors
● Bootstrap CSS classes
● Hapi plugins
11. Underscore.js
_.each(array, function) : Loop over each item in an array
_.map(array, function) : Reformat each item in an array
_.filter(array, function) : Make a new array containing only items that pass a test
_.reduce(array, function, start) : Calculate a single value from an array of items
13. myArray
.map(/* reformat items */)
.filter(/* pull out items you don't need */)
.reduce(/* crunch down to a single value */)
You can do this in plain JS too
14. mapped = map(..., my_array)
filtered = filter(..., mapped)
final_val = reduce(..., filtered)
And in Python
16. var myList = [
{ count: 17 },
{ count: 22 },
{ count: 3 },
{ count: 18 }
];
var sum = 0;
for (var i = 0; i < myList.length; i++) {
sum += myList[i].count;
}
Function reuse
17. Function reuse
function getCount (value) {
return value.count;
}
function noOdds (value) {
return value % 2 === 0;
}
function add (value1, value2) {
return value1 + value2;
}
18. Function reuse
var myList = [
{ count: 17 },
{ count: 22 },
{ count: 3 },
{ count: 18 }
];
var sum = _.chain(myList)
.map(getCount)
.filter(noOdds)
.reduce(add)
.value();
19. each / map / filter / reduce
function getForms (data) {
var forms = data.aggregate.all[window.location.protocol + '//' + window.location.host];
var formsOut = [];
var url = window.location.toString();
var formsToExclude = [];
for (var key in data.aggregate.exclude) {
if (new RegExp('^' + key + '$').test(url)) {
formsToExclude = formsToExclude.concat(data.aggregate.exclude[key]);
}
}
var filteredForms = [];
for (value in forms) {
if (formsToExclude.indexOf(value) === -1) {
filteredForms.push(value);
}
}
for (key in data.aggregate.include) {
if (new RegExp('^' + key + '$').test(url)) {
forms = forms.concat(data.aggregate.include[key]);
}
}
return formsOut;
}
20. each / map / filter / reduce
function getForms (data) {
var forms = data.aggregate.all[window.location.protocol + '//' + window.location.host];
var url = window.location.toString();
var formsToExclude = [];
_.each(data.aggregate.exclude, function (val, key) {
if (new RegExp('^' + key + '$').test(url)) {
formsToExclude = formsToExclude.concat(val);
}
});
forms = _.filter(forms, function (val) {
return formsToExclude.indexOf(val) === -1;
});
_.each(data.aggregate.include, function (val, key) {
if (new RegExp('^' + key + '$').test(url)) {
forms = forms.concat(val);
}
});
return forms || [];
}
21. each / map / filter / reduce
● Small, single-purpose functions
● Maintainable
● Reusable
● Easy to test
● Universally understandable
22. Web components
● HTML is perfectly composable:
<form>
<input type="text">
<button>click me</button>
</form>
● Custom elements = infinite composition possibilities!
24. "This is the Unix philosophy: Write programs
that do one thing and do it well. Write programs
to work together. Write programs to handle text
streams, because that is a universal interface."
- Doug McIlroy
The Unix Philosophy
25. A Node.js API to read in data, act on it in
chunks, then then write out to a new stream.
Node streams