Skip to content

Instantly share code, notes, and snippets.

@Usse
Forked from leonyu/coding-styles.md
Created May 17, 2016 13:47
Show Gist options
  • Save Usse/441143e8ea95a29983dbfa7ebb174e45 to your computer and use it in GitHub Desktop.
Save Usse/441143e8ea95a29983dbfa7ebb174e45 to your computer and use it in GitHub Desktop.

These examples are presented in an attempt to show how each coding styles attempts to or does not attempt to isolate side-effects. There are only 2 semantic elements in a barebone "Hello World" implementation:

  • Invocation of console.log
  • Declaration of HELLO_WORLD

Since every coding style can abstract away data into a parameter or variable, there is no point for us to show that. All implementations assume HELLO_WORLD is a constant that is always inlined. This way it reduces the variations we need to present. (To make an anology, if we were to implement incrementByOne, would we need to inline the number 1 or pass it in as parameter?)

CAVEAT/LIMITATION: All implementations also assume console is static. In case of OOP inheritance, Console is assumed to be extendable. In case of functional programming, console.log is asumed to be a function that can be passed around without further modification.

Declarative

const HelloWorld = (<div>{HELLO_WORLD}</div>);
// usage
ReactDOM.render(HelloWorld, document.getElementById('app'));

Imperative

Procedural

Direct invocation

// no implementation
// usage
console.log(HELLO_WORLD);

Subroutine

Subroutine does not return value.

function printHelloWorld() {
  console.log(HELLO_WORLD);
}
// usage
printHelloWorld();

Context-passing

This is a technique often used to emulate OOP when OOP is not available such as in languages C and Bash. It is also often used when OOP is not practical, for example when recreating the object is an overhead.

function helloWorld(ctx) {
  ctx.log(HELLO_WORLD);
}
// usage
helloWorld(console);

Static-typed object-oriented

Static

Static method
class HelloWorld {
  static print() {
    console.log(HELLO_WORLD);
  }
}
// usage
HelloWorld.print();
Static invocation from method
class HelloWorld {
  print() {
    console.log(HELLO_WORLD);
  }
}
// usage
new HelloWorld().print()

Inheritance

Classical Inheritance

// following code would not work as Console is not publically initializable
class HelloWorld extends Console {
  print() {
    this.log(HELLO_WORLD);
  }
}
// usage
new HelloWorld().print();

Prototypical inheritance

let myConsole = Object.create(console);
myConsole.print = function () {
  this.log(HELLO_WORLD);
};
// usage
myConsole.print();

Old-school class pattern

// following code would not work as Console is not publically initializable
function HelloWorld() {
}
HelloWorld.prototype = new Console();
HelloWorld.prototype.print = function () {
  this.log(HELLO_WORLD);
};
// usage
new HelloWorld().print();

Injection-based

constructor injection

class HelloWorld {
  constructor(console) {
    this.console = console;
  }
  print() {
    this.console.log(HELLO_WORLD);
  }
}
// usage
new HelloWorld(console).print();

Parameter Injection

class HelloWorld {
  print(console) {
    console.log(HELLO_WORLD);
  }
}
// usage
new HelloWorld().print(console);

Autowired Injection

class HelloWorld {
  $console;
  print(console) {
    this.$console.log(HELLO_WORLD);
  }
}
// usage
Singleton.get(HelloWorld).print(console);

Factory

Constructor Injection

function createHelloWorld(f) {
  return {
    print() {
        f.log(HELLO_WORLD);
    }
  }
}
// usage
createHelloWorld(console).print();

Parameter Injection

function createHelloWorld() {
  return {
    print(console) {
      console.log(HELLO_WORLD);
    }
  };
}
// usage
createHelloWorld().print(console);

IIFE / old-school module pattern

const HelloWorld = (function createHelloWorld() {
  return {
    print(console) {
      console.log(HELLO_WORLD);
    }
  };
})();
// usage
HelloWorld.print(console);

Dynamic-typed object-oriented

Mixin

Static invocation
const HelloWorldMixin = {
  printHelloWorld() {
    console.log(HELLO_WORLD);
  }
};
// usage
const obj = Object.assign({}, HelloWorldMixin);
obj.printHelloWorld();
Parameter injection
const HelloWorldMixin = {
  printHelloWorld(console) {
    console.log(HELLO_WORLD);
  }
};
// usage
const obj = Object.assign({}, HelloWorldMixin);
obj.printHelloWorld(console);

Monkey-pactching

Monkey-pactching with mixins
const HelloWorldMixin = {
  printHelloWorld() {
    console.log(HELLO_WORLD);
  }
};
// usage
Object.assign(console, HelloWorldMixin);
console.printHelloWorld();
Monkey-pactching with method
console.printHelloWorld = function() {
   this.log(HELLO_WORLD);
}
// usage
console.printHelloWorld();

Functional programming

Eager Eval

Side-effect on usage

function helloWorld() {
  return HELLO_WORLD;
}
// usage
console.log(helloWorld());

Side-effect on binding

function helloWorld(console) {
  return console.log(HELLO_WORLD);
}
// usage
helloWorld(console);

Lazy Eval

early binding

function helloWorld(f) {
  return () => f.log(HELLO_WORLD);
}
// usage
helloWorld(console)();
Late Binding
function helloWorld() {
  return (f) => f.log(HELLO_WORLD);
}
// usage
helloWorld()(console);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment