Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Modular Design

Modular Design

We go over the history of modularity in JavaScript, the reasons why modularity is appealing when developing large JavaScript applications, and then dive deep into the fundamentals of how to effectively develop modular applications. We cover topics like abstractions, refactoring, testing, and interface design in the context of the JavaScript language.

Nicolás Bevacqua

December 05, 2017
Tweet

More Decks by Nicolás Bevacqua

Other Decks in Programming

Transcript

  1. Modular
    Design

    View Slide

  2. ponyfoo.com
    @nzgb

    View Slide

  3. ponyfoo.com/books

    View Slide

  4. A Brief History
    of JavaScript
    Modularity

    View Slide

  5. <br/>

    View Slide

  6. ~function(){
    // …
    }()

    View Slide

  7. var i = (function(){
    return {
    hello: 'world'
    }
    })()

    View Slide

  8. <br/><script><br/><script><br/><script><br/>

    View Slide

  9. RequireJS
    AngularJS
    Dependency
    injection

    View Slide

  10. RequireJS
    define(['./sum'], function (sum) {
    return function double(a) {
    return sum(a, a)
    }
    })

    View Slide

  11. AngularJS
    angular.factory('double',
    ['sum', function (sum) {
    return function double(a) {
    return sum(a, a)
    }
    }]
    )

    View Slide

  12. Over-engineered.
    Verbose.
    But good enough

    View Slide

  13. NodeJS
    CommonJS

    View Slide

  14. const sum = require('./sum')
    module.exports = function double(a) {
    return sum(a, a)
    }
    CommonJS

    View Slide

  15. Browserify

    View Slide

  16. Babel
    Webpack
    Rollup

    View Slide

  17. ES Modules
    import sum from './sum'
    export default function double(a) {
    return sum(a, a)
    }

    View Slide

  18. GCC
    Babel
    Rollup
    Prepack

    View Slide

  19. Prepack
    [1, 2, 3].forEach(n => {
    console.log(n)
    })
    console.log(1)
    console.log(2)
    console.log(3)

    View Slide

  20. type='module'>

    View Slide

  21. But why?

    View Slide

  22. No clashing
    (raison d'être for CSS-in-JS)

    View Slide

  23. Containing
    Complexity

    View Slide

  24. View Slide

  25. It's all about containing complexity.
    Think of your modules as lego blocks.
    You don't necessarily care about the
    details of how each block is made.
    All you need to know is how to use the
    lego blocks to build your lego castle.
    — @sindresorhus

    View Slide

  26. Interfaces

    View Slide

  27. Breaking
    Down
    Complexity

    View Slide

  28. Aspect,
    or Flow?

    View Slide

  29. Portability

    View Slide

  30. Composability

    View Slide

  31. Composability

    View Slide

  32. Modular
    Design
    Essentials

    View Slide

  33. Single
    Responsibility
    Principle

    View Slide

  34. API
    First

    View Slide

  35. Revealing
    Pattern

    View Slide

  36. Consistency
    (across modules)

    View Slide

  37. Ambiguity

    View Slide

  38. Be conservative in
    what you do, be
    liberal in what you
    accept from others.
    — Postel's Law (from TCP)

    View Slide

  39. View Slide

  40. Simplicity

    View Slide

  41. Interface
    Testing

    View Slide

  42. Interface
    Documentation

    View Slide

  43. Abstraction

    View Slide

  44. The
    Holy
    Grail!

    View Slide

  45. Oh no.

    View Slide

  46. Premature
    Abstraction

    View Slide

  47. The
    Right
    Abstraction

    View Slide

  48. Refactoring
    Complex
    Code

    View Slide

  49. Less
    Clever*
    Code.
    (way less.)
    *

    View Slide

  50. Use
    More*
    Variables!
    (way more.)
    *

    View Slide

  51. () => a && (b ? c : d) || e
    if (a) {
    return b ? c : d
    }
    return e

    View Slide

  52. Guard
    Clauses

    View Slide

  53. if (apiKey) {
    if (apiSecret) {
    // happy path
    } else {
    throw new Error('missing secret')
    }
    } else {
    throw new Error('missing key')
    }

    View Slide

  54. if (!apiKey) {
    throw new Error('missing key')
    }
    if (!apiSecret) {
    throw new Error('missing secret')
    }
    // happy path

    View Slide

  55. Extract
    Function

    View Slide

  56. let optionalLabel = null
    if (labelText) {
    optionalLabel = (

    { labelText }

    )
    }

    View Slide

  57. const optionalLabel =
    renderLabel({
    labelText
    })
    function renderLabel({ labelText }) {
    if (!labelText) {
    return null
    }
    return { labelText }
    }

    View Slide

  58. When all else fails …
    Slice
    Function

    View Slide

  59. Thanks!
    @nzgb

    View Slide