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

  1. PROVIDE CONTEXT THROUGH SENSIBLE NAMING
  2. IMPROVE READABILITY THROUGH CLEARER SYNTAX
  3. COMMUNICATE INTENT THROUGH CORE CONCEPTS
  4. 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