Programming Paradigms in Javascript

Gwen Faraday

  • Project Lead the Way
  • freeCodeCamp
  • @gwen_faraday
  • gwenfaraday@gmail.com

Why am I interested in paradigms?

"The ratio of time spent reading (code) versus writing is well over 10 to 1."

- Robert C. Martin

What is a paradigm?

  • A model
  • In programming:
    • code organization
    • reusability
    • testing
    • memory considerations

Paradigms in Javascript

  • Imperative (Proceedural)
  • Functional (FP)
  • Object Oriented (OOP)

Imperative

(Proceedural)

Line by line execution

var start = Date.now() + '';
var fs = require('fs-extra');
var execSync = require('child_process').execSync;

var build = '../scout-app-build/win32/Scout-App/';
var bowerJSON = fs.readJsonSync('bower.json');
var manifest = fs.readJsonSync('package.json');
delete manifest.devDependencies;

// Clean build folder
fs.removeSync(build + 'License');
fs.removeSync(build + 'bower_components');
fs.removeSync(build + 'node_modules');
var timeClean = Date.now() + '';
console.log('Cleaning build folder - ' + timer(timeClean, start));

// Copy files over
fs.writeJsonSync(build + 'package.json', manifest);
fs.writeJsonSync(build + 'bower.json', bowerJSON);
fs.copySync('scout-files/index.html', build + 'scout-files/index.html');

// Zip package
var zipExe = 'node_modules/7zip-bin-win/' + process.arch + '/7za.exe';
var buildInput = '../scout-app-build/win32/Scout-App';
var outputZip = '../scout-app-build/WIN_Scout-App_' + manifest.version + '.zip';
fs.removeSync(outputZip);
execSync(zipExe + ' a -bd -tzip -mx=9 -y ' + outputZip + ' ' + buildInput);
var timeZip = Date.now() + '';
console.log('Zipped Package        - ' + timer(timeZip, timeNS));

// Total Time
var end = Date.now() + '';
console.log('-------------------------------------');
console.log('Total Build Time      - ' + timer(end, start)

Advantages with Imperative:

  • Easy to Start With
  • Easy to Reason About
  • Makes sense for small projects

Problems with Imperative:

  • Hard to Read, Maintain
  • Easy to make memory errors
  • Unit Testing is Impractical

Functional

Functional Paradigm:

  • Function composition
  • Immutability - Don't mutate state
  • Pure functions - No side effects
  • Recursion/Tail Calls

Pure Functions

  • Given the same inputs, always returns the same output
  • Has no side-effects
Pure Function:

function doSomething(val){
    var newVal = val + 10;
    return newVal;
}
________________________________________________________
Impure Function:

var x = 10;
function doSomething(){
    x = x + 10;
    console.log("testing")
}

Higher Order Functions

function isBigEnough(value) {
  return value >= 10;
}
[12, 5, 8, 130, 44].filter(isBigEnough);

"The first rule of functions is that they should be small."

- Robert C. Martin

Function composition

function sum(x, y){
    return x + y;
}
function mult(x, y){
    return x * y;
}
function multAndSum(x, y, z){
    return sum(mult(x, y), z);
}
sum(mult(3, 4), 5);
multAndSum(3,4,5)

Avoid mutating state

var state = { name: "Bob", age: 26 };
function updateClient(state, action){
    switch (action.type) {
        case 'UPDATE_NAME':
            return {
                ...state,
                name: action.name
            }
        case 'UPDATE_AGE':
            return {
                ...state,
                age: action.age
            }
    };
};
var newState = updateClient(state, {type: 'UPDATE_NAME', name: "Carl"})

Avoid mutating state, cont...

const a = 10;
a = 11; //error

const arr = [1, 2, 3];
arr[0] = 5; //No error

var b = Object.freeze([10, 11, 12]);
b[0] = 13; //error

var c = {};
Object.defineProperty( c, "name", {
  value: "Gwen",
  writable: false
});
c.name = "Rose"; //error

Memoization/Caching

function expensiveFunction(n){
    var x = 2; var y = 3; var z = 0;
    for (var i = 0; i < n; i++){
        for (var j = 0; j < n; j++){
            z = x * y;
        }
    }
    return z + n;
}

function cacheSomething(funct){
    return function innerFcn(n){
        if (!localStorage.getItem(n)){
            localStorage.setItem(n, funct(n));
        }
        return localStorage.getItem(n);
    }
}
Live Sample Code

Recursion - #1

function retryProcess(){
    processFiles()
        .then(function(val){
            console.log('success');
        })
        .catch(function(err){
            console.log("error: " + err)
            retryProcess();
        })
}

Recursion - #2

// New Optimized Recursion:

function countdown(value) {
    if (value > 0) {
        console.log(value);
        return countdown(value - 1);
    } else {
        return value;
    }
};
countdown(10);

Closures

function someClosure(a){
    return function (b){
        return a + b; // a == 10
    }
}
var add = someClosure(10);
add(5); // 15

Advantages with Functional:

  • Multi-Core Friendly
  • Easy to Reason About
  • Easier Navigation through Code
  • Debugging/Testing

Problems with Functional:

  • Can use more memory
  • Performance can take a little bit of a hit
  • Learning curve can be a bit steeper

Object Oriented

"ECMAScript is an object‑oriented programming language..."

-- EcmaScript Standard --

Everything is an Object!

typeof /s/ === 'object'
Function instanceof Object
Error instanceof Object
typeof new Date() === 'object'
typeof [] === 'object'

OOP Characteristics:

  • Encapsulation
  • Inheritance
  • Polymorphism

Encapsulation

Inheritance

function Rectangle(length, width){
  this.length = length;
  this.width = width;
}
Rectangle.prototype.getArea = function(){
  return this.length * this.width;
}
Rectangle.prototype.toString = function(){
  return `[Rectangle ${this.length} x ${this.width}]`;
}

function Square(size){
  this.length = size;
  this.width = size;
}
Square.prototype = new Rectangle();

Square.prototype.toString = function(){
  return `[Square ${this.length} x ${this.width}]`;
}

var square = new Square(20);
var rect = new Rectangle(10, 5);

square.getArea() // 400
rect.getArea() // 50

ES2015 Classes

class Rectangle {
    constructor(length, width){
        this.length = length;
        this.width = width;
    }
    getArea(){
        return this.length * this.width;
    }
}
class Square extends Rectangle {
    constructor(size){
        super();
        this.length = size;
        this.width = size;
    }
}
var rect = new Rectangle(10, 5);
var square = new Square(10);

Game Time!

So, why has there been an emphasis on FP instead of OOP in JavaScript?

"The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle."

- Joe Armstrong

OOP Can Work with FP

People to Follow

  • Rich Hickey - Creator of Clojure
  • Robert C. Martin - Author of "Clean Code"
  • Kyle Simpson - Opinionated JS Expert

Gwen Faraday

Made with Slides.com