Learning from the Mistakes of a v1

A presentation at JSCONF.BE 2020 in June 2020 in by Sarah Dayan

Slide 1

Slide 1

Learning from the Mistakes of a v1 Sarah Dayan Software Engineer, Algolia @frontstuff_io

Slide 2

Slide 2

const price = Dinero({ amount: 5000, currency: ‘EUR’ }); const tip = price.percentage(20); const fullPrice = price.add(tip); fullPrice.toFormat(); // “€60.00” @frontstuff_io

Slide 3

Slide 3

2 400 29 years commits releases @frontstuff_io

Slide 4

Slide 4

A v2 usually marks a turning point. @frontstuff_io

Slide 5

Slide 5

Slide 6

Slide 6

🔢 It uses numbers to represent amounts @frontstuff_io

Slide 7

Slide 7

const price = Dinero({ amount: 5000, currency: ‘EUR’ }); @frontstuff_io

Slide 8

Slide 8

.1 + .2; // 0.30000000000000004 (1 + 2) / 10 // 0.3 @frontstuff_io

Slide 9

Slide 9

const price = Dinero({ // 5000 cents, or 50 euros amount: 5000, currency: ‘EUR’ }); @frontstuff_io

Slide 10

Slide 10

Number.MAX_SAFE_INTEGER; // 9007199254740991 Number.MIN_SAFE_INTEGER; // -9007199254740991 @frontstuff_io

Slide 11

Slide 11

Enter bigints. @frontstuff_io

Slide 12

Slide 12

const calculator = { add(a, b) { return a + b; }, subtract(a, b) { return a - b; }, // … }; @frontstuff_io

Slide 13

Slide 13

import { Decimal } from ‘decimal.js’; const bigDinero = createDinero({ calculator: { add: Decimal.add, subtract: Decimal.sub, // … }, }); const price = bigDinero({ amount: new Decimal(Number.MAX_SAFE_INTEGER), currency: ‘EUR’, }); @frontstuff_io

Slide 14

Slide 14

💰 It doesn’t handle different exponents @frontstuff_io

Slide 15

Slide 15

1 euro = 100 cents 1 x 10^2 = 100 @frontstuff_io

Slide 16

Slide 16

const price = Dinero({ amount: 5000, currency: ‘EUR’, }); price.toFormat(); // “€50.00” @frontstuff_io

Slide 17

Slide 17

@frontstuff_io

Slide 18

Slide 18

const price = Dinero({ amount: 1000, currency: ‘IQD’, precision: 3, }); @frontstuff_io

Slide 19

Slide 19

const IQD = { code: ‘IQD’, base: 10, exponent: 3, }; const price = Dinero({ amount: 1000, currency: IQD, }); @frontstuff_io

Slide 20

Slide 20

🔄 It expects a REST API for conversions @frontstuff_io

Slide 21

Slide 21

const options = { endpoint: ‘https://api/?base={{from}}’, propertyPath: ‘data.rates.{{to}}’, headers: { ‘user-key’: ‘xxxxxxxxx’, }, roundingMode: ‘HALF_UP’, }; Dinero({ amount: 5000, currency: ‘EUR’, }).convert(‘XBT’, options); @frontstuff_io

Slide 22

Slide 22

const price = Dinero({ amount: 5000, currency: ‘EUR’, }); price.convert(‘XBT’); @frontstuff_io

Slide 23

Slide 23

const rates = new Promise((resolve) => resolve({ XBT: 0.00012, }) ); Dinero({ amount: 5000 }) .convert(EUR, { rates }); @frontstuff_io

Slide 24

Slide 24

const rates = { rates: { XBT: 0.00012, }, }; Dinero({ amount: 5000, currency: ‘EUR’, }).convert(‘XBT’, { endpoint: new Promise((resolve) => resolve(rates) ), }); @frontstuff_io

Slide 25

Slide 25

🌎 It relies on the ECMAScript I18n API @frontstuff_io

Slide 26

Slide 26

const amount = 5; amount.toLocaleString(‘en-GB’, { style: ‘currency’, currency: ‘EUR’, }); // “€5.00” @frontstuff_io

Slide 27

Slide 27

const options = { style: ‘currency’, currency: ‘EUR’, }; amount.toLocaleString(‘en-GB’, options); // “€5.00” amount.toLocaleString(‘de-DE’, options); // “5,00 €” @frontstuff_io

Slide 28

Slide 28

const price = Dinero({ amount: 500, currency: ‘EUR’, }).setLocale(‘en-GB’); price.toFormat(); // “€5.00” @frontstuff_io

Slide 29

Slide 29

Tight coupling @frontstuff_io

Slide 30

Slide 30

Lack of flexibility @frontstuff_io

Slide 31

Slide 31

Inconsistent implementation @frontstuff_io

Slide 32

Slide 32

const price = Dinero({ amount: 500, currency: EUR, }); price.toFormat( ({ amount, currency }) => ${currency.code} ${amount}, { digits: 2, roundingMode: Math.round, } ); // “EUR 5” @frontstuff_io

Slide 33

Slide 33

function i18n({ amount, currency }) { return amount.toLocaleString(‘en-GB’, { style: ‘currency’, currency: currency.code, }); } price.toFormat(i18n, { digits: 2, roundingMode: Math.round, }); // “€5.00” @frontstuff_io

Slide 34

Slide 34

const currencySymbols = { EUR: ‘€’, USD: ‘$’, // … }; function manualI18n({ amount, currency }) { const { code } = currency; const symbol = currencySymbols[code] || code; return ${symbol}${amount.toFixed(2)}; } price.toFormat(manualI18n, { digits: 2, roundingMode: Math.round, }); // “€5.00” @frontstuff_io

Slide 35

Slide 35

🌳 You can’t tree-shake it @frontstuff_io

Slide 36

Slide 36

Slide 37

Slide 37

const price = Dinero({ amount: 500, currency: ‘EUR’, }); price.add(price).multiply(4); @frontstuff_io

Slide 38

Slide 38

const price = Dinero({ amount: 500, currency: ‘EUR’, }); multiply(add(price, price), 4); @frontstuff_io

Slide 39

Slide 39

@frontstuff_io

Slide 40

Slide 40

🐞 It’s written in JavaScript @frontstuff_io

Slide 41

Slide 41

Maintaining types by hand doesn’t scale. And it’s a pain. @frontstuff_io

Slide 42

Slide 42

Static typing is extremely helpful. @frontstuff_io

Slide 43

Slide 43

🐦 TypeScript hits two birds with one stone. @frontstuff_io

Slide 44

Slide 44

What happened? @frontstuff_io

Slide 45

Slide 45

First library @frontstuff_io

Slide 46

Slide 46

No real-world experience @frontstuff_io

Slide 47

Slide 47

Many assumptions @frontstuff_io

Slide 48

Slide 48

Scalability Flexibility Agnosticism DX @frontstuff_io

Slide 49

Slide 49

Thank you! Sarah Dayan Software Engineer, Algolia Links Why Javascript Numbers Are Weird (And How to Fix It) youtu.be/Wq2AqONg7rs Dinero.js on GitHub github.com/dinerojs @frontstuff_io

Slide 50

Slide 50