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.

550d0153dbeee2fcaede98f906e55d02?s=128

Nicolás Bevacqua

December 05, 2017
Tweet

Transcript

  1. Modular Design

  2. ponyfoo.com @nzgb

  3. ponyfoo.com/books

  4. A Brief History of JavaScript Modularity

  5. <script>

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

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

  8. <script> <script> <script> <script>

  9. RequireJS AngularJS Dependency injection

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

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

    return sum(a, a) } }] )
  12. Over-engineered. Verbose. But good enough

  13. NodeJS CommonJS

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

    sum(a, a) } CommonJS
  15. Browserify

  16. Babel Webpack Rollup

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

    { return sum(a, a) }
  18. GCC Babel Rollup Prepack

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

    console.log(3)
  20. <script type='module'>

  21. But why?

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

  23. Containing Complexity

  24. None
  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
  26. Interfaces

  27. Breaking Down Complexity

  28. Aspect, or Flow?

  29. Portability

  30. Composability

  31. Composability

  32. Modular Design Essentials

  33. Single Responsibility Principle

  34. API First

  35. Revealing Pattern

  36. Consistency (across modules)

  37. Ambiguity

  38. Be conservative in what you do, be liberal in what

    you accept from others. — Postel's Law (from TCP)
  39. None
  40. Simplicity

  41. Interface Testing

  42. Interface Documentation

  43. Abstraction

  44. The Holy Grail!

  45. Oh no.

  46. Premature Abstraction

  47. The Right Abstraction

  48. Refactoring Complex Code

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

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

  51. () => a && (b ? c : d) ||

    e if (a) { return b ? c : d } return e
  52. Guard Clauses

  53. if (apiKey) { if (apiSecret) { // happy path }

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

    { throw new Error('missing secret') } // happy path
  55. Extract Function

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

    <span> { labelText } </span> ) }
  57. const optionalLabel = renderLabel({ labelText }) function renderLabel({ labelText })

    { if (!labelText) { return null } return <span>{ labelText }</span> }
  58. When all else fails … Slice Function

  59. Thanks! @nzgb