Last Month I Bought a Piano
Whatever is easiest
Don't know the theory
Can't teach anyone else
Is bad at writing notation
Pursuit of perfection
Learns and understands the theory
Can share their learnings
Can write beautiful notation
PLAYS MUSIC
MUSICIAN
WRITES CODE
SOFTWARE ENGINEER
With a great community
The JS community has
a problem
potential
var done = false;
var running = 0;
var errored = false;
(function replenish () {
if (done && running <= 0) {
return callback(null);
}
while (running < limit && !errored) {
var key = nextKey();
if (key === null) {
done = true;
if (running <= 0) {
callback(null);
}
return;
}
running += 1;
iterator(obj[key], key, only_once(function (err) {
running -= 1;
if (err) {
callback(err);
errored = true;
}
else {
replenish();
}
}));
}
})();
function(path, options, fn){
// support callback API
if ('function' == typeof options) {
fn = options, options = undefined;
}
if (typeof fn === 'function') {
var res
try {
res = exports.renderFile(path, options);
} catch (ex) {
return fn(ex);
}
return fn(null, res);
}
options = options || {};
options.filename = path;
return handleTemplateCache(options)(options);
};
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (/^--.+=/.test(arg)) {
// Using [\s\S] instead of . because js doesn't support the
// 'dotall' regex modifier. See:
// http://stackoverflow.com/a/1068308/13216
var m = arg.match(/^--([^=]+)=([\s\S]*)$/);
var key = m[1];
var value = m[2];
if (flags.bools[key]) {
value = value !== 'false';
}
setArg(key, value, arg);
}
else if (/^--no-.+/.test(arg)) {
var key = arg.match(/^--no-(.+)/)[1];
setArg(key, false, arg);
}
else if (/^--.+/.test(arg)) {
var key = arg.match(/^--(.+)/)[1];
var next = args[i + 1];
if (next !== undefined && !/^-/.test(next)
&& !flags.bools[key]
var xM = isX(M);
var xm = xM || isX(m);
var xp = xm || isX(p);
var anyX = xp;
if (gtlt === '=' && anyX)
gtlt = '';
if (xM) {
if (gtlt === '>' || gtlt === '<') {
// nothing is allowed
ret = '<0.0.0';
} else {
// nothing is forbidden
ret = '*';
}
} else if (gtlt && anyX) {
// replace X with 0
if (xm)
m = 0;
if (xp)
p = 0;
Development of software engineers
It works, does it need to look good?
If a lion could speak, we could not understand him
- WITTGENSTEIN
CORRECT LEARNABLE READABLE MAINTAINABLE
REUSABLE SCANNABLE DOCUMENTED
QUALITIES OF GOOD CODE
Good code is written for your team, not for yourself.
PERFORMANT? CONCISCE? COMPLEX?
To me, good code is:
DEVELOPING FOR HUMANS
- PROVIDE CONTEXT THROUGH SENSIBLE NAMING
- IMPROVE READABILITY THROUGH CLEARER SYNTAX
- COMMUNICATE INTENT THROUGH CORE CONCEPTS
- REDUCE CONFUSION BY SMARTER BRANCHING
IMPROVE READABILITY THROUGH CLEARER SYNTAX
Never use quirks
if(~'human'.indexOf('u')){
// When is this executed?
}
if(_.includes('human', 'u')){
// This is a lot clearer
}
function isReadable(){
return !!this.readable;
}
var date = +new Date()
function isReadable(){
return Boolean(this.readable);
}
var date = Date.now();
IMPROVE READABILITY THROUGH CLEARER SYNTAX
Fail fast
Avoid many nested conditions by returning as quickly as possible
function getSomething(){
if(condition) {
// Long
// function
// body
// example
if(otherCondition){
return true;
}
}
return false;
}
function getSomething(){
if(!condition){
return false;
}
// Long
// function
// body
// example
return Boolean(otherCondition);
}
IMPROVE READABILITY THROUGH CLEARER SYNTAX
Nested ternary expressions
NO
Keystrokes are cheap, comprehension is expensive
function getTQ(t) {
var q = extend(getQuery(u), {
type: t
});
return q;
}
function getTypeQuery(type, user) {
var query = extend(getQuery(user), {
type: type
});
return query;
}
NO SINGLE LETTER VARIABLES. NO ABBREVIATIONS
PROVIDE CONTEXT THROUGH SENSIBLE NAMING
Naming is hard, but important
var d = 5;
var stateList = ['good','bad'];
var open = true;
var elapsedTimeInDays = 5;
var possibleStates = ['good','bad'];
var isOpen = true;
VARIABLE NAMES SHOULD BE DESCRIPTIVE
FUNCTION NAMES SHOULD IMPLY A RETURN TYPE
function pending(){}
function orgs(){}
function states(){}
function calculatePercentage(){}
function isPending(){}
function hasOrganizations(){}
function getStates(){}
function getPercentage(){}
PROVIDE CONTEXT THROUGH SENSIBLE NAMING
COMMUNICATE INTENT THROUGH CORE CONCEPTS
Semantic is scannable
var result = [];
_.each(rums, function(rum){
if(rum.year < 1918){
result.push(rum);
}
});
_.filter(rums, function(rum){
return rum.year < 1918;
});
_.each(rums, function(rum){
if(rum.year < 1918){
rum.isDelicious = true;
}
});
_.map(rums, function(rum){
rum.isDelicious = rum.year < 1989;
return rum;
});
COMMUNICATE INTENT THROUGH CORE CONCEPTS
Consistent return types
Functions should always return the same type
function getAvailbleYears(rum){
var rumYears = {
'Angostura': [1, 5, 7 ,12],
'Havana Club': [1, 3, 4, 7]
};
return rumYears[rum];
}
function getAvailbleYears(rum){
var rumYears = {
'Angostura': [1, 5, 7 ,12],
'Havana Club': [1, 3, 4, 7]
};
return rumYears[rum] || [];
}
Array
undefined
Array
COMMUNICATE INTENT THROUGH CORE CONCEPTS
Pure functions, no side-effects
var availableRums = [{
name: 'Angostura',
age: 12
}, {
name: 'Havana Club',
age: 7
}];
function incrementAges(rums) {
availableRums.forEach(function age(rum) {
rum.age++;
});
}
var availableRums = [{
name: 'Angostura',
age: 12
}, {
name: 'Havana Club',
age: 7
}];
function incrementAges(rums) {
return availableRums.map(function age(rum) {
var agedRum = clone(rum);
agedRum.age++;
return agedRum;
});
}
REDUCE CONFUSION BY SMARTER BRANCHING
Keep flow control at the highest level possible
function submitForm(){
var data = this.getFormData();
validateForm(data);
}
function validateForm(data){
if(isValid(data)){
augmentData(data);
}
}
function augmentData(data){
data.something = 123;
makeXHRCall(data);
}
function submitForm(){
var data = this.getFormData();
if(!isValid(formData)){
return;
}
var augmentedData = augmentData(data);
makeXHRCall(data);
}
function augmentData(data){
data.something = 123;
return;
}
REDUCE CONFUSION BY SMARTER BRANCHING
Else is redundant
function isProper(sausage){
if(sausage.isMadeOfChicken()){
return false;
} else {
return true;
}
}
If you need an else in your function then your function does too much.
function isProper(sausage){
if(sausage.isMadeOfChicken()){
return false;
}
return true;
}
We never change the minds of the people who are most vocal against it, we just have to wait for them to die... can we get rid of goto now?
- DOUGLAS CROCKFORD
https://github.com/DrBoolean/mostly-adequate-guide
https://facebook.github.io/immutable-js/
https://www.youtube.com/watch?v=bo36MrBfTk4 (Crockford, the better parts)
https://github.com/Willyham/human.js
https://www.youtube.com/watch?v=65-RbBwZQdU (Vyacheslav Egorov, performance and benchmarking)
Last month I bought a piano
By Will Demaine
Last month I bought a piano
- 1,442