Skip to content

Instantly share code, notes, and snippets.

@mateuszsokola
Created July 28, 2017 11:26
Show Gist options
  • Save mateuszsokola/439c1b4c87ee9dbde40cc623fd7c5c98 to your computer and use it in GitHub Desktop.
Save mateuszsokola/439c1b4c87ee9dbde40cc623fd7c5c98 to your computer and use it in GitHub Desktop.
Composition

Composition

There are two kinds of composition - object composition and function composition:

  • object composition - way of combining simple objects into complex ones.
  • function composition - way of combining simple functions to build more complicated ones.

Why composition is better than inheritance?

It doesn't encourage developers to build large object heritage, so applications aren't complex like enterprise Java apps. We limit the future predition to minimum.

Why composition isn't always the best way of building software?

The Functional Programming (FP) is deeply dived in computer science. It means to develop great project using FP, the company needs to hire very good programmers, very likely post-grads from Math subjects / univerisities. It's much harder than the Object-oriented programming (OOP), because the OOP abstract applied math of the programming, so the barrier of knowledge is much lower (in the OOP).

It's important to understand who's going to build the application in the long-run? If company has access only to junior devs, probably the OOP will be a better option than FP.

// Imagine situation in the restaurant, as a waiter i want to print a bill for my customer.
// In Europe on every bill needs to contain paid tax and total sum.
//
// As an application designer I decided to cents to store pricepoints. Cents are more universal,
// some currencies aren't separated between cents and dollars like japanese yens.
//
// I designed to two factories:
// * billable - funcitons related to suming up the bill, tax calculation etc.
// * converter - functions related to money converting...
//
/**
* Returns the composition of two functions,
* where each function consumes the return value of the function that follows.
*
* @param {function} f
* @param {function} g
*/
const compose = (f, g) => (state) => f(g(state));
/**
* Set of methods related to the bill
*/
const billable = () => ({
sum: (state) => state
.map(item => item.price)
.reduce((acc, price) => acc + price, 0),
calculateTax: (state) => state
.reduce((acc, {price, taxPercent}) => acc + Math.round(price * taxPercent), 0)
})
/**
* Set of methods related to money convertion
*/
const converter = () => ({
centsToDollar: (cents) => (cents / 100).toLocaleString('pl-PL', {
style: 'currency',
currency: 'EUR'
})
})
// Items on customer's bill
const itemsOnCheck = [
{
name: 'fries',
price: 599,
taxPercent: 0.1 // 10%
}, {
name: 'burger',
price: 1599,
taxPercent: 0.1
}, {
name: 'coca-cola',
price: 599,
taxPercent: 0.2
}
]
// object composition
const check = Object.assign({}, billable(), converter());
// function composition
console.log('tax: ', compose(check.centsToDollar, check.calculateTax)(itemsOnCheck));
console.log('sum: ', compose(check.centsToDollar, check.sum)(itemsOnCheck));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment