README.mdView |
---|
| 1 … | +layout: true |
| 2 … | + |
| 3 … | +<footer>dinosaur.is</footer> |
| 4 … | + |
| 5 … | +--- |
| 6 … | +class: center |
| 7 … | + |
1 | 8 … | # luddite.js |
2 | 9 … | |
| 10 … | +<img src="./white-rabbit.jpg" /> |
| 11 … | + |
| 12 … | + |
| 13 … | + |
| 14 … | +??? |
| 15 … | + |
3 | 16 … | --- |
4 | 17 … | |
5 | 18 … | ## hey [CampJS](http://campjs.com) |
6 | 19 … | |
7 | | -i'm [Mikey (@ahdinosaur)](http://dinosaur.is) from [Enspiral](http://enspiral.com) |
| 20 … | +i'm [Mikey](http://dinosaur.is) from [Enspiral](https://enspiral.com) & [Root Systems](https://www.rootsystems.nz) |
8 | 21 … | |
9 | 22 … | <div class="row"> |
10 | 23 … | <a href="http://dinosaur.is.com"> |
11 | 24 … | <img alt="Mikey's avatar" src="./avatar.png" width="200" /> |
12 | 25 … | </a> |
13 | 26 … | <a href="http://enspiral.com"> |
14 | 27 … | <img alt="Enspiral logo" src="./enspiral.png" width="200" /> |
15 | 28 … | </a> |
| 29 … | + <a href="http://dinosaur.is"> |
| 30 … | + <img alt="Root Systems logo" src="./root-systems.jpg" width="200" /> |
| 31 … | + </a> |
16 | 32 … | </div> |
17 | 33 … | |
18 | | -slides are available at <http://dinosaur.is/campjs-viii-ludditejs>. |
| 34 … | +slides are available at: |
19 | 35 … | |
| 36 … | +<http://dinosaur.is/campjs-viii-ludditejs> |
| 37 … | + |
20 | 38 … | ??? |
21 | 39 … | |
22 | 40 … | - second time presenting at a conference. |
| 41 … | +- i'll try to be upfront and honest, apologies in advance if i disguise any opinions as facts |
23 | 42 … | - i might say negative things about some JavaScript patterns, but i use those patterns too |
24 | | - - yes i'm bitter about some things, i'll try to be honest |
25 | | -- everyone in the JavaScript community is doing a wonderful job |
26 | | -- apologies in advance if i disguise any opinions as facts |
| 43 … | +- in general everyone in the JavaScript community is doing a wonderful job, i appreciate your work |
27 | 44 … | |
28 | | ---- |
| 45 … | +### let's adventure |
29 | 46 … | |
30 | | -## what? |
| 47 … | +#### to the silly wonderland of luddite.js |
31 | 48 … | |
32 | | -luddite.js |
| 49 … | +<img src="./rabbit-hole.jpg" height='400' class="center" /> |
33 | 50 … | |
| 51 … | + |
| 52 … | + |
34 | 53 … | ??? |
35 | 54 … | |
36 | | -so... |
| 55 … | +an ambiguous utopia |
37 | 56 … | |
| 57 … | + |
38 | 58 … | --- |
| 59 … | +class: info |
39 | 60 … | |
40 | 61 … | ## Luddite? |
41 | 62 … | |
42 | 63 … | the [Luddites](https://en.wikipedia.org/wiki/Luddite) was a political movement against _automated centralized technology_. |
43 | 64 … | |
44 | | -<div style='display: flex; justify-content: center'> |
45 | | - <img src="./luddite.jpg" height='400' /> |
46 | | -</div> |
| 65 … | +<img src="./luddite.jpg" height='300' class="center" /> |
47 | 66 … | |
48 | 67 … | ??? |
49 | 68 … | |
50 | 69 … | - many Luddites were skilled machine operators in the textile industry |
51 | 70 … | - they wanted machines to make high-quality goods, run by workers who had gone through an apprenticeship and got paid decent wages |
|
52 | 71 … | - they attacked centralized factories who used automated machines operated by unskilled labor |
53 | 72 … | - they used fictious characters to make their story ring |
54 | | - - see Ned Ludd, the made-up leader |
| 73 … | + - see Ned Ludd, the made-up leader, who lived in Sherwood Forest |
55 | 74 … | |
56 | 75 … | --- |
| 76 … | +class: info |
57 | 77 … | |
58 | 78 … | ## luddite.js? |
59 | 79 … | |
60 | 80 … | **luddite.js** is a (made-up) meme for _simple decentralized JavaScript_. |
61 | 81 … | |
62 | 82 … | - decentralized userland ecosystems |
63 | | - - not centralized core committees |
64 | 83 … | - simple patterns based on function signatures |
65 | | - - not trendy libraries that lock you in |
66 | 84 … | |
67 | 85 … | ??? |
68 | 86 … | |
| 87 … | +- not centralized core committees |
| 88 … | +- not trendy libraries that lock you in |
69 | 89 … | - gonna lead you on a journey through the luddite way to do things |
70 | 90 … | - a study of functional JavaScript patterns that have evolved in userland |
71 | 91 … | |
72 | 92 … | --- |
| 93 … | +class: center, info |
73 | 94 … | |
74 | | -## decent userland |
| 95 … | +## decentralized userland ecosystems |
75 | 96 … | |
| 97 … | +--- |
| 98 … | +class: info |
| 99 … | + |
76 | 100 … | what if i told you... |
77 | 101 … | |
| 102 … | +<img src="./morpheus-cat.png" height="400" /> |
| 103 … | + |
78 | 104 … | that anyone can create a _standard_? |
79 | 105 … | |
80 | | -<img src="./morpheus-cat.png" height="500" class="center" /> |
81 | | - |
82 | 106 … | ??? |
83 | 107 … | |
| 108 … | +- not everyone needs to agree with you |
84 | 109 … | - no corporate sponsorship necessary |
85 | 110 … | |
86 | 111 … | --- |
| 112 … | +class: info |
87 | 113 … | |
88 | | -## what is a standard? |
| 114 … | +### what is a standard? |
89 | 115 … | |
90 | 116 … | anything that enough people use is a "standard" |
91 | 117 … | |
92 | 118 … | example: ["standard style"](https://github.com/feross/standard) |
105 | 131 … | - back-end: express |
106 | 132 … | - anything "best practice" |
107 | 133 … | |
108 | 134 … | --- |
| 135 … | +class: info |
109 | 136 … | |
110 | | -## what is a _luddite.js_ standard? |
| 137 … | +### what is a _luddite.js_ standard? |
111 | 138 … | |
112 | 139 … | a standard based on a function signature |
113 | 140 … | |
114 | 141 … | example: [Redux](https://redux.js.org) reducers |
118 | 145 … | ``` |
119 | 146 … | |
120 | 147 … | ??? |
121 | 148 … | |
122 | | -- standard function signature |
123 | 149 … | - what other standards based on function signatures can you think of? |
124 | 150 … | - express / connect: (req, res, next) |
125 | 151 … | |
126 | 152 … | --- |
| 153 … | +class: info |
127 | 154 … | |
128 | | -## why is this important? |
| 155 … | +### why is this important? |
129 | 156 … | |
130 | | -- easy to use and test |
| 157 … | +- easy to test |
131 | 158 … | - accessible for anyone to participate |
132 | 159 … | - no module lock-in |
133 | 160 … | |
134 | 161 … | ??? |
137 | 164 … | - you don't need anyone's approval to write a "function specification" |
138 | 165 … | - you can swap libraries that are compatible with the "function specification" |
139 | 166 … | |
140 | 167 … | --- |
| 168 … | +class: center, info |
141 | 169 … | |
142 | | -## simple functional |
| 170 … | +## simple patterns based on function signatures |
143 | 171 … | |
| 172 … | +--- |
| 173 … | +class: info |
| 174 … | + |
144 | 175 … | what if i told you... |
145 | 176 … | |
146 | | -that you only needed _plain functions and objects_? |
| 177 … | +<img src="./morpheus-cat.png" height="400" /> |
147 | 178 … | |
| 179 … | +that you only needed _functions and objects_? |
| 180 … | + |
148 | 181 … | ??? |
149 | 182 … | |
150 | 183 … | - no fancy syntax necessary |
151 | 184 … | - less language clutter |
152 | 185 … | - how can we apply this pattern to the full stack? |
153 | 186 … | |
154 | 187 … | --- |
| 188 … | +class: success |
155 | 189 … | |
156 | | -## just a function |
| 190 … | +### just a function |
157 | 191 … | |
158 | 192 … | ```js |
159 | 193 … | function fn (options) { return value } |
160 | 194 … | ``` |
163 | 197 … | const fn = (...args) => ({ [key]: value }) |
164 | 198 … | ``` |
165 | 199 … | |
166 | 200 … | --- |
| 201 … | +class: info |
167 | 202 … | |
168 | | -## sync function signals |
| 203 … | +### sync function signals |
169 | 204 … | |
170 | 205 … | with a sync function, there are two possible signals: |
171 | 206 … | |
172 | 207 … | 1. value: `return value` |
186 | 221 … | } |
187 | 222 … | ``` |
188 | 223 … | |
189 | 224 … | --- |
| 225 … | +class: center, info |
190 | 226 … | |
191 | | -## es modules |
| 227 … | +## modules |
192 | 228 … | |
| 229 … | +--- |
| 230 … | +class: danger |
| 231 … | + |
| 232 … | +### es modules |
| 233 … | + |
193 | 234 … | ```js |
194 | 235 … | import thing from 'module' |
195 | 236 … | |
196 | 237 … | export default thing |
215 | 256 … | - breaks CommonJS code with default |
216 | 257 … | - yes, i'm bitter about this, i've lost many hours debugging broken code, only to realize the module author published a patch version that broke the CommonJS exports |
217 | 258 … | |
218 | 259 … | --- |
| 260 … | +class: success |
219 | 261 … | |
220 | | -## or node modules |
| 262 … | +### node modules |
221 | 263 … | |
222 | 264 … | also known as "CommonJS" |
223 | 265 … | |
224 | 266 … | ```js |
242 | 284 … | - run code in JavaScript interpreter |
243 | 285 … | - capture result of `module.exports` variable |
244 | 286 … | - when i started using Node.js from Python, `require`-as-a-function is what excited me the most |
245 | 287 … | - so yes, i'm somewhat bitter that now JavaScript is adopting the same syntax as Python |
| 288 … | +--- |
| 289 … | +class: center, info |
246 | 290 … | |
| 291 … | +## dom elements |
| 292 … | + |
247 | 293 … | --- |
| 294 … | +class: danger |
248 | 295 … | |
249 | | -## jsx |
| 296 … | +### jsx |
250 | 297 … | |
251 | 298 … | ```js |
252 | 299 … | import React from 'react' |
253 | 300 … | |
274 | 321 … | - "why can't i use `if () { first } else { second }`? |
275 | 322 … | - can only use expressions, not statements |
276 | 323 … | |
277 | 324 … | --- |
| 325 … | +class: success |
278 | 326 … | |
279 | | -## or hyperscript |
| 327 … | +### hyperscript |
280 | 328 … | |
281 | 329 … | ```js |
282 | 330 … | const h = require('react-hyperscript') |
283 | 331 … | |
296 | 344 … | |
297 | 345 … | - `React.createElement` is basically a strict hyperscript without the class/id sugar |
298 | 346 … | |
299 | 347 … | --- |
| 348 … | +class: success |
300 | 349 … | |
301 | | -## or hyperx |
| 350 … | +### hyperx |
302 | 351 … | |
303 | 352 … | ```js |
304 | 353 … | const hyperx = require('hyperx') |
305 | 354 … | const React = require('react') |
324 | 373 … | |
325 | 374 … | - similar to JSX, but uses existing language features: tagged template string |
326 | 375 … | |
327 | 376 … | --- |
| 377 … | +class: center, info |
328 | 378 … | |
329 | | -## promise |
| 379 … | +## eventual value |
330 | 380 … | |
331 | | -a "promise" is an eventual value |
| 381 … | +--- |
| 382 … | +class: danger |
332 | 383 … | |
| 384 … | +### promise |
| 385 … | + |
333 | 386 … | ```js |
334 | 387 … | const promise = new Promise((resolve, reject) => { |
335 | 388 … | // do stuff... |
336 | 389 … | resolve(value) |
338 | 391 … | reject(error) |
339 | 392 … | } |
340 | 393 … | ``` |
341 | 394 … | |
| 395 … | +```js |
| 396 … | +promise |
| 397 … | + .then(value => console.log(value)) |
| 398 … | + .catch(err => console.error(value)) |
| 399 … | +``` |
| 400 … | + |
342 | 401 … | ??? |
343 | 402 … | |
344 | 403 … | ```js |
345 | 404 … | module.exports = fetchCats |
351 | 410 … | }) |
352 | 411 … | ``` |
353 | 412 … | |
354 | 413 … | --- |
| 414 … | +class: success |
355 | 415 … | |
356 | | -## continuable |
| 416 … | +### continuable |
357 | 417 … | |
358 | 418 … | a "continuable" is a function that takes a single argument, a node-style error-first callback |
359 | 419 … | |
360 | 420 … | ```js |
389 | 449 … | }) |
390 | 450 … | ``` |
391 | 451 … | |
392 | 452 … | --- |
| 453 … | +class: info |
393 | 454 … | |
394 | | -## async errors |
| 455 … | +### async errors |
395 | 456 … | |
396 | 457 … | with a node-style error-first callback, there are three possible signals: |
397 | 458 … | |
398 | 459 … | 1. value: `cb(null, value)` |
405 | 466 … | - promises wrap all your handlers in a `try` / `catch`, so even if you have a different opinion about error handling, promises will force it's opinion on you |
406 | 467 … | - yes, i'm bitter about this, i've lost many hours trying to figure out where my errors went |
407 | 468 … | |
408 | 469 … | --- |
| 470 … | +class: center, info |
409 | 471 … | |
410 | | -## pull streams |
| 472 … | +## reactive values |
411 | 473 … | |
| 474 … | +--- |
| 475 … | +class: danger |
| 476 … | + |
| 477 … | +### es observables |
| 478 … | + |
| 479 … | +https://tc39.github.io/proposal-observable/ |
| 480 … | + |
| 481 … | +??? |
| 482 … | + |
| 483 … | +too much detail to explain here |
| 484 … | + |
| 485 … | +- https://github.com/tc39/proposal-observable |
| 486 … | + |
| 487 … | +--- |
| 488 … | +class: success |
| 489 … | + |
| 490 … | +### observ-ables |
| 491 … | + |
| 492 … | +reactive values using only functions! |
| 493 … | + |
| 494 … | +> - `thing()` gets the value |
| 495 … | +> - `thing.set(...)` sets the value |
| 496 … | +> - `thing(function (value) { ... })` listens to the value. |
| 497 … | + |
| 498 … | +??? |
| 499 … | + |
| 500 … | +- [`observ`](https://github.com/Raynos/observ) |
| 501 … | +- [`observable`](https://github.com/dominictarr/observable) |
| 502 … | +- [`push-stream`](https://github.com/ahdinosaur/push-stream) |
| 503 … | +- [`mutant`](https://github.com/mmckegg/mutant) |
| 504 … | + |
| 505 … | +--- |
| 506 … | +class: center, info |
| 507 … | + |
| 508 … | +## values over time |
| 509 … | + |
| 510 … | +--- |
| 511 … | +class: danger |
| 512 … | + |
| 513 … | +### node streams |
| 514 … | + |
| 515 … | +https://nodejs.org/api/stream.html |
| 516 … | + |
| 517 … | +??? |
| 518 … | + |
| 519 … | +- https://github.com/substack/stream-handbook |
| 520 … | +- https://github.com/workshopper/stream-adventure |
| 521 … | + |
| 522 … | +--- |
| 523 … | +class: danger |
| 524 … | + |
| 525 … | +### whatwg streams |
| 526 … | + |
| 527 … | +https://streams.spec.whatwg.org/ |
| 528 … | + |
| 529 … | +??? |
| 530 … | + |
| 531 … | +- https://github.com/whatwg/streams |
| 532 … | + |
| 533 … | +--- |
| 534 … | +class: success |
| 535 … | + |
| 536 … | +### pull streams |
| 537 … | + |
412 | 538 … | async streams using only functions! |
413 | 539 … | |
414 | 540 … | ```js |
415 | 541 … | pull(source(), through(), sink()) |
419 | 545 … | - unbuffered by default |
420 | 546 … | - pipeline error propogation |
421 | 547 … | - source and sink back-pressure |
422 | 548 … | |
423 | | - |
424 | 549 … | ??? |
425 | 550 … | |
| 551 … | +pull streams could be its own talk, going to be a quick intro |
| 552 … | + |
426 | 553 … | - [history of streams](http://dominictarr.com/post/145135293917/history-of-streams) |
427 | 554 … | - [pull stream examples](https://github.com/dominictarr/pull-stream-examples) |
428 | 555 … | - [pull streams intro](http://dominictarr.com/post/149248845122/pull-streams-pull-streams-are-a-very-simple) |
429 | 556 … | - [pull stream](https://pull-stream.github.io/) |
430 | 557 … | - [pull stream workshop](https://github.com/pull-stream/pull-stream-workshop) |
431 | 558 … | |
432 | | -compare with |
| 559 … | +--- |
| 560 … | +class: success |
433 | 561 … | |
434 | | -- node streams: |
435 | | - - https://nodejs.org/api/stream.html |
436 | | - - https://github.com/substack/stream-handbook |
437 | | - - https://github.com/workshopper/stream-adventure |
438 | | -- wg-stream |
439 | | - - https://streams.spec.whatwg.org/ |
440 | | - - https://github.com/whatwg/streams |
| 562 … | +##### source usage |
441 | 563 … | |
| 564 … | +```js |
| 565 … | +const source = values([0, 1, 2, 3]) |
| 566 … | + |
| 567 … | +source(null, (err, value) { |
| 568 … | + console.log('first value:', value) |
| 569 … | +}) |
| 570 … | +// first value: 0 |
| 571 … | +``` |
| 572 … | + |
442 | 573 … | --- |
| 574 … | +class: success |
443 | 575 … | |
444 | | -### source |
| 576 … | +##### source example |
445 | 577 … | |
446 | | -example: |
447 | | - |
448 | 578 … | ```js |
449 | 579 … | function values (array) { |
450 | 580 … | var i = 0 |
451 | 581 … | return (abort, callback) => { |
458 | 588 … | } |
459 | 589 … | } |
460 | 590 … | ``` |
461 | 591 … | |
462 | | -usage: |
463 | | - |
464 | | -```js |
465 | | -const source = values([0, 1, 2, 3]) |
466 | | - |
467 | | -source(null, (err, value) { |
468 | | - console.log('first value:', value) |
469 | | -}) |
470 | | -// first value: 0 |
471 | | -``` |
472 | | - |
473 | 592 … | ??? |
474 | 593 … | |
475 | 594 … | - look ma, just functions! |
476 | 595 … | - yes, we are using callbacks even for synchronous results |
477 | 596 … | - much faster this way, no reason to delay til next tick |
478 | 597 … | |
479 | 598 … | --- |
| 599 … | +class: success |
480 | 600 … | |
481 | | -### sink |
| 601 … | +#### sink usage |
482 | 602 … | |
483 | | -example: |
| 603 … | +```js |
| 604 … | +const source = values([0, 1, 2, 3]) |
484 | 605 … | |
| 606 … | +log(source) |
| 607 … | +// 0 |
| 608 … | +// 1 |
| 609 … | +// 2 |
| 610 … | +// 3 |
| 611 … | +``` |
| 612 … | + |
| 613 … | +--- |
| 614 … | +class: success |
| 615 … | + |
| 616 … | +#### sink example |
| 617 … | + |
485 | 618 … | ```js |
486 | 619 … | function log (read) { |
487 | 620 … | read(null, function next (err, data) { |
488 | 621 … | if (err) return console.log(err) |
492 | 625 … | }) |
493 | 626 … | } |
494 | 627 … | ``` |
495 | 628 … | |
496 | | -usage: |
497 | | - |
498 | | -```js |
499 | | -const source = values([0, 1, 2, 3]) |
500 | | - |
501 | | -log(source) |
502 | | -// 0 |
503 | | -// 1 |
504 | | -// 2 |
505 | | -// 3 |
506 | | -``` |
507 | | - |
508 | 629 … | ??? |
509 | 630 … | |
510 | 631 … | with continuables: |
511 | 632 … | |
522 | 643 … | } |
523 | 644 … | ``` |
524 | 645 … | |
525 | 646 … | --- |
| 647 … | +class: success |
526 | 648 … | |
527 | | -### through |
| 649 … | +#### through usage |
528 | 650 … | |
529 | | -example: |
| 651 … | +```js |
| 652 … | +const source = values([0, 1, 2, 3]) |
| 653 … | +const double = map(x => x * 2) |
530 | 654 … | |
| 655 … | +log(double(source)) |
| 656 … | +``` |
| 657 … | + |
| 658 … | +--- |
| 659 … | +class: success |
| 660 … | + |
| 661 … | +#### through example |
| 662 … | + |
531 | 663 … | ```js |
532 | 664 … | function map (mapper) { |
533 | 665 … | // a sink function: accept a source |
534 | 666 … | return function (read) { |
544 | 676 … | } |
545 | 677 … | } |
546 | 678 … | ``` |
547 | 679 … | |
548 | | -usage: |
| 680 … | +--- |
| 681 … | +class: success |
549 | 682 … | |
550 | | -```js |
551 | | -const source = values([0, 1, 2, 3]) |
552 | | -const double = map(x => x * 2) |
| 683 … | +#### wild pull streams |
553 | 684 … | |
554 | | -log(double(source)) |
555 | | -``` |
| 685 … | +ecosystem of modules: [pull-stream.github.io](https://pull-stream.github.io) |
556 | 686 … | |
557 | | ---- |
558 | | - |
559 | | -### real pull streams |
560 | | - |
561 | 687 … | ``` |
562 | | -const pull = require('pull-stream') |
563 | | - |
| 688 … | +// parse a csv file |
564 | 689 … | pull( |
565 | | - pull.values([0, 1, 2, 3]), |
566 | | - pull.map(x => x * 2), |
567 | | - pull.log() |
| 690 … | + File(filename), |
| 691 … | + CSV(), |
| 692 … | + pull.drain(console.log) |
568 | 693 … | ) |
| 694 … | + |
| 695 … | +function CSV () { |
| 696 … | + return pull( |
| 697 … | + Split(), // defaults to '\n' |
| 698 … | + pull.map(function (line) { |
| 699 … | + return line.split(',') |
| 700 … | + }) |
| 701 … | + ) |
| 702 … | +} |
569 | 703 … | ``` |
570 | 704 … | |
571 | 705 … | ??? |
572 | 706 … | |
573 | | -- check out the ecosystem of modules at [pull-stream.github.io](https://pull-stream.github.io) |
| 707 … | +obviously you don't want to re-implement simple streams from scratch all the time |
574 | 708 … | |
575 | 709 … | --- |
| 710 … | +class: info |
576 | 711 … | |
577 | | -### pull stream errors |
| 712 … | +#### pull stream errors |
578 | 713 … | |
579 | 714 … | with a pull stream source callback, there are four possible signals: |
580 | 715 … | |
581 | 716 … | 1. value: `cb(null, value)` |
587 | 722 … | |
588 | 723 … | - both the source and sink can signal back-pressure ("hey i'm busy") by not calling the respective callback |
589 | 724 … | |
590 | 725 … | --- |
| 726 … | +class: center, info |
591 | 727 … | |
592 | | -## luddite.js benefits |
| 728 … | +## why should you be a JavaScript luddite? |
593 | 729 … | |
594 | 730 … | --- |
| 731 … | +class: success |
595 | 732 … | |
596 | 733 … | ### better performance |
597 | 734 … | |
598 | 735 … | software performance is less about gaining muscle, more about losing weight |
599 | 736 … | |
| 737 … | +??? |
| 738 … | + |
| 739 … | +- code runs faster when it does less |
| 740 … | +- if you don't use fancy syntax (jsx, etc), you don't need fancy build steps |
| 741 … | + |
600 | 742 … | --- |
| 743 … | +class: success |
601 | 744 … | |
602 | 745 … | ### easier to describe |
603 | 746 … | |
604 | 747 … | specification is a function signature, not a complex state machine |
605 | 748 … | |
| 749 … | +??? |
| 750 … | + |
| 751 … | +- clear inputs and outputs |
| 752 … | +- no hidden state to manage |
| 753 … | + |
606 | 754 … | --- |
| 755 … | +class: success |
607 | 756 … | |
608 | 757 … | ### easier to understand |
609 | 758 … | |
610 | 759 … | less "snippet-driven development" |
623 | 772 … | - https://alistapart.com/column/douglas-engelbart |
624 | 773 … | - http://www.dougengelbart.org/pubs/augment-3906.html |
625 | 774 … | - http://99percentinvisible.org/episode/of-mice-and-men/ |
626 | 775 … | |
| 776 … | + |
| 777 … | + His system, called NLS, showed actual instances of, or precursors to, hypertext, shared screen collaboration, multiple windows, on-screen video teleconferencing, and the mouse as an input device. |
| 778 … | + |
| 779 … | + He intended to boost collective intelligence and enable knowledge workers to think in powerful new ways, to collectively solve urgent global problems. |
| 780 … | + |
| 781 … | +> The pendulum has swung about as far as it can toward the consumerization of computing technology, in which everything should be immediately intuitive and nothing should require learning, training, or practice. Engelbart’s vision was on the opposite end of that pendulum swing—he believed that the power of these tools came with inherent complexity. |
| 782 … | + |
627 | 783 … | --- |
| 784 … | +class: center, info |
628 | 785 … | |
629 | 786 … | ## stories |
630 | 787 … | |
631 | 788 … | --- |
| 789 … | +class: warning |
632 | 790 … | |
633 | 791 … | ### story: catstack |
634 | 792 … | |
635 | 793 … | build a framework from scratch, alone |
636 | 794 … | |
637 | | -<img src="./catstack.jpg" height="450" class="center" /> |
| 795 … | +<img src="./catstack.jpg" height="350" class="center" /> |
638 | 796 … | |
639 | 797 … | ??? |
640 | 798 … | |
641 | | -reinvent all the wheels! |
| 799 … | +reinvent every wheel possible! |
642 | 800 … | |
643 | 801 … | https://github.com/root-systems/catstack |
644 | 802 … | |
| 803 … | +i did it, but it was unsustainable, unable to transfer context to team |
| 804 … | + |
645 | 805 … | - ui views |
646 | 806 … | - hyps |
647 | 807 … | - hyper-fela |
648 | 808 … | - ui state |
665 | 825 … | - module system |
666 | 826 … | - command-line tasks |
667 | 827 … | |
668 | 828 … | --- |
| 829 … | +class: warning |
669 | 830 … | |
670 | 831 … | ### learning: |
671 | 832 … | |
672 | 833 … | yay, reinventing wheels for fun and learning |
679 | 840 … | |
680 | 841 … | - no better way to learn how systems work than by building them from scratch |
681 | 842 … | - own your dependencies, don't consume them for granted |
682 | 843 … | - provide consistent flavoring across subsystems |
| 844 … | +- marginally better than other libraries |
683 | 845 … | |
684 | 846 … | cons |
685 | 847 … | |
686 | 848 … | - easy to become isolated |
687 | 849 … | - if you aren't enough to become popular, you're alone |
688 | 850 … | - spreads you thin |
689 | | - - hard to work on what you want, because you have to fix something else |
| 851 … | + - hard to work on what you can do best, because you have to spend limited resources on your marginally better stack |
690 | 852 … | - easy to rabbit hole |
691 | 853 … | - probably miss the long tail: i18n, accessibility, tests |
692 | 854 … | - always doing maintenance |
693 | 855 … | |
694 | 856 … | --- |
| 857 … | +class: info |
695 | 858 … | |
696 | 859 … | ### revised: dogstack |
697 | 860 … | |
698 | 861 … | choose your battles |
699 | 862 … | |
700 | | -<img src="./dogstack.jpg" height="450" class="center" /> |
| 863 … | +<img src="./dogstack.jpg" height="350" class="center" /> |
701 | 864 … | |
702 | 865 … | ??? |
703 | 866 … | |
| 867 … | +focus on what you do best |
| 868 … | + |
| 869 … | +delegates parts where you are only marginally better |
| 870 … | + |
704 | 871 … | http://dogstack.js.org/ |
705 | 872 … | |
706 | 873 … | --- |
| 874 … | +class: success |
707 | 875 … | |
708 | 876 … | ### story: patch ecosystem |
709 | 877 … | |
710 | | -bring-your-own-framework potluck |
| 878 … | +bring-your-own-JavaScript potluck |
711 | 879 … | |
712 | | -<img src="./patchwork.png" height="400" class="center" /> |
| 880 … | +<img src="./patchwork.png" height="350" class="center" /> |
713 | 881 … | |
714 | 882 … | ??? |
715 | 883 … | |
716 | | -build an app with others, bring-your-own framework |
| 884 … | +build an app with others, bring your own JavaScript opinions |
717 | 885 … | |
718 | 886 … | references: |
719 | 887 … | |
720 | 888 … | - https://github.com/ssbc/patchcore |
722 | 890 … | - https://github.com/ssbc/patchbay |
723 | 891 … | - https://github.com/ssbc/patchlite |
724 | 892 … | |
725 | 893 … | --- |
| 894 … | +class: success, center |
726 | 895 … | |
727 | | -### learning: somebody should... |
| 896 … | +#### offline social media |
728 | 897 … | |
729 | | -> if you see something that needs doing, it's your job to do |
| 898 … | +<img src="./patchwork-screenshot.jpg" height="500" class="center" /> |
730 | 899 … | |
| 900 … | +--- |
| 901 … | +class: success, center |
| 902 … | + |
| 903 … | +#### git projects |
| 904 … | + |
| 905 … | +<img src="./git-ssb-screenshot.png" height="450" class="center" /> |
| 906 … | + |
| 907 … | +--- |
| 908 … | +class: success |
| 909 … | + |
| 910 … | +### learning: mad science works! |
| 911 … | + |
| 912 … | +follow your passion |
| 913 … | + |
| 914 … | +find others who share your passion |
| 915 … | + |
731 | 916 … | ??? |
732 | 917 … | |
733 | | -- collaborate with active listening and empathy |
| 918 … | +- somebody should: if you see something that needs doing, it's your job to do |
| 919 … | +- find ways to collaborate with active listening and empathy |
734 | 920 … | - mad science: find something worth doing, do it, publish, repeat |
735 | 921 … | |
736 | 922 … | --- |
| 923 … | +class: center, info |
737 | 924 … | |
738 | 925 … | ## conclusion |
739 | 926 … | |
740 | 927 … | --- |
| 928 … | +class: info |
741 | 929 … | |
742 | 930 … | ### so what |
743 | 931 … | |
744 | 932 … | everyone has opinions. |
746 | 934 … | this one is mine. :3 |
747 | 935 … | |
748 | 936 … | ??? |
749 | 937 … | |
| 938 … | +as my Mom always says: |
| 939 … | + |
| 940 … | +> it's not about being right, it's about being successful |
| 941 … | + |
750 | 942 … | takaways |
751 | | - |
752 | 943 … | - izs pants post: https://groups.google.com/forum/#!msg/nodejs/MWaivVTirPY/0pnRjKsggkIJ |
753 | 944 … | - everyone has opinions, be aware of yours' and others' |
754 | 945 … | - when you come over to someone's house, be polite and respect their opinions |
755 | 946 … | - don't force your opinions on others |
756 | 947 … | - share what you're passionate about |
757 | 948 … | - avoid persuading anyone that your way is better |
758 | 949 … | - the luddite.js way is just another opinion, not better or worse than yours |
759 | 950 … | |
| 951 … | +## aids |
| 952 … | + |
| 953 … | +- [eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) |
| 954 … | +- [mad science method](https://github.com/ahdinosaur/mad-science-handbook/blob/master/collaboration.md#the-mad-science-cycle) |
| 955 … | +- [do-ocracy](https://communitywiki.org/wiki/DoOcracy) |
| 956 … | +- marathon: keep a slow & steady pace one step at a time |
| 957 … | +- if you see a job that needs doing, it's your job to do (do-ocrarcy) |
| 958 … | +- too much sugar is bad for your health (simple interfaces) |
| 959 … | + |
| 960 … | +## blocks |
| 961 … | + |
| 962 … | +- cave method: try to design or implement the _perfect_ system before sharing it |
| 963 … | +- [design by committee](https://en.wikipedia.org/wiki/Design_by_committee) |
| 964 … | +- sprint: hype, mania, and burn-out |
| 965 … | +- [waterfall design](https://en.wikipedia.org/wiki/Waterfall_model) |
| 966 … | + |
| 967 … | +--- |
| 968 … | +class: info |
| 969 … | + |
760 | 970 … | ### all the "standards" |
761 | 971 … | |
762 | 972 … | make up your own "standards"! |
763 | 973 … | |
764 | 974 … | you have just as much a right to make the next JavaScript standard as anyone else. |
765 | 975 … | |
| 976 … | +??? |
| 977 … | + |
| 978 … | +at the end of the day, standards are just somebody's opinion. |
| 979 … | + |
766 | 980 … | --- |
| 981 … | +class: info |
767 | 982 … | |
| 983 … | +## questions? |
| 984 … | + |
| 985 … | +--- |
| 986 … | +class: success |
| 987 … | + |
768 | 988 … | ## thanks! |
769 | 989 … | |
770 | | -<3 |
| 990 … | +i appreciate the gift of your attention. ♥ |
771 | 991 … | |
772 | | -https://dinosaur.is |
| 992 … | +<img src="./follow_your_dreams.png" height="300" class="center" /> |
| 993 … | + |
| 994 … | + |
| 995 … | + |
| 996 … | +??? |
| 997 … | + |
| 998 … | +## references |
| 999 … | + |
| 1000 … | +- [es2040](https://github.com/ahdinosaur/es2040) |
| 1001 … | +- [Art of Node](https://github.com/maxogden/art-of-node) |
| 1002 … | +- [Art of I/O](http://ioschool.is/art-of-io/sessions/0/?notes=true) |
| 1003 … | +- [Tiny Guide to Non Fancy Node](https://github.com/yoshuawuyts/tiny-guide-to-non-fancy-node) |
| 1004 … | + |
| 1005 … | +## luddite.js apps |
| 1006 … | + |
| 1007 … | +- https://webtorrent.io/ |
| 1008 … | +- http://standardjs.com/ |
| 1009 … | +- https://peermaps.github.io/ |
| 1010 … | +- http://loopjs.com/ |
| 1011 … | +- https://scuttlebutt.nz/ |
| 1012 … | +- https://choo.io/ |