Commit cc739adf29428df8628ea59c7c691605e3a9ae71
checkpoint
Michael Williams committed on 8/5/2017, 9:01:00 AMParent: a30dc6bf64d6ab714be21520a8f4da3c9103353f
Files changed
README.md | changed |
index.html | changed |
package.json | changed |
README.md | |||
---|---|---|---|
@@ -38,13 +38,49 @@ | |||
38 | 38 … | ||
39 | 39 … | ??? | |
40 | 40 … | ||
41 | 41 … | - second time presenting at a conference. | |
42 … | +- i want to share what i am passionate about | ||
43 … | + - i might say negative things about some JavaScript patterns, but i use those patterns too | ||
44 … | + - i don't want to yuck your yum | ||
42 | 45 … | - i'll try to be upfront and honest, apologies in advance if i disguise any opinions as facts | |
43 | -- i might say negative things about some JavaScript patterns, but i use those patterns too | ||
44 | 46 … | - in general everyone in the JavaScript community is doing a wonderful job, i appreciate your work | |
45 | 47 … | ||
46 | 48 … | --- | |
49 … | +class: center, info | ||
50 … | + | ||
51 … | +## shout-out | ||
52 … | + | ||
53 … | +??? | ||
54 … | + | ||
55 … | +- when i was writing this talk a few days ago, covered in Imposter Syndrome, i realized... | ||
56 … | + - someone inspired my passion behind this talk without me realizing | ||
57 … | + | ||
58 … | +--- | ||
59 … | +class: info | ||
60 … | + | ||
61 … | +### Douglas Engelbart | ||
62 … | + | ||
63 … | +augment human intellect | ||
64 … | + | ||
65 … | +<img src="./engelbart.jpg" height="350" class="center" /> | ||
66 … | + | ||
67 … | +??? | ||
68 … | + | ||
69 … | +- i take the Douglas Engelbart approach to developer experience | ||
70 … | +- you may have heard of the Mother of all Demos, if not i highly recommend you check it out | ||
71 … | +- he intended to boost collective intelligence to solve urgent global problems | ||
72 … | +- Englebart's vision was that the power of technology came with inherent complexity | ||
73 … | +- so priority is not ease of use but powerful human computer expression | ||
74 … | +- let's evolve our JavaScript together to solve urgent global problems | ||
75 … | + | ||
76 … | +references: | ||
77 … | + | ||
78 … | +- https://alistapart.com/column/douglas-engelbart | ||
79 … | +- http://www.dougengelbart.org/pubs/augment-3906.html | ||
80 … | +- http://99percentinvisible.org/episode/of-mice-and-men/ | ||
81 … | + | ||
82 … | +--- | ||
47 | 83 … | class: center | |
48 | 84 … | ||
49 | 85 … | ### let's adventure | |
50 | 86 … | ||
@@ -63,9 +99,9 @@ | |||
63 | 99 … | class: info | |
64 | 100 … | ||
65 | 101 … | ## Luddite? | |
66 | 102 … | ||
67 | -the [Luddites](https://en.wikipedia.org/wiki/Luddite) was a political movement against _automated centralized technology_. | ||
103 … | +the [Luddites](https://en.wikipedia.org/wiki/Luddite) was a political movement against _centralized automated technology_. | ||
68 | 104 … | ||
69 | 105 … | <img src="./luddite.jpg" height='300' class="center" /> | |
70 | 106 … | ||
71 | 107 … | ??? | |
@@ -80,9 +116,9 @@ | |||
80 | 116 … | class: info | |
81 | 117 … | ||
82 | 118 … | ## luddite.js? | |
83 | 119 … | ||
84 | -**luddite.js** is a (made-up) meme for _simple decentralized JavaScript_. | ||
120 … | +**luddite.js** is a (made-up) meme for _decentralized simple JavaScript_. | ||
85 | 121 … | ||
86 | 122 … | - decentralized userland ecosystems | |
87 | 123 … | - simple patterns based on function signatures | |
88 | 124 … | ||
@@ -126,15 +162,15 @@ | |||
126 | 162 … | ``` | |
127 | 163 … | ||
128 | 164 … | ??? | |
129 | 165 … | ||
166 … | +- a standard is one opinion, shared my many | ||
130 | 167 … | - tc39 is a great team advancing the state of the art in JavaScript, | |
131 | - - but the standards produced by tc39 are only one of _many_ possible JavaScript standards. | ||
168 … | + - but the standards produced by tc39 are only one of _many_ possible JavaScript opinions | ||
169 … | +- we all have the power to create our own JavaScript opinions | ||
170 … | + - no experience necessary! | ||
132 | 171 … | - what other standards can you think of? | |
133 | - - JS syntax: babel plugins | ||
134 | - - front-end: react | ||
135 | - - back-end: express | ||
136 | - - anything "best practice" | ||
172 … | + - anything "best practice", maybe even within a small niche community | ||
137 | 173 … | ||
138 | 174 … | --- | |
139 | 175 … | class: info | |
140 | 176 … | ||
@@ -249,16 +285,12 @@ | |||
249 | 285 … | ||
250 | 286 … | ??? | |
251 | 287 … | ||
252 | 288 … | - why new syntax? | |
253 | - - there's myths that es modules do something new | ||
254 | - - something about "tree shaking" | ||
255 | - - anything possible with es modules is possible without | ||
256 | - - common shake | ||
257 | - - who knew developers were so superstitious | ||
289 … | + - there's myths that es modules make possible something new | ||
258 | 290 … | - what is happening here? | |
259 | - - confusing to beginners who don't understand the special syntax and complex implementation details | ||
260 | -- breaks CommonJS code with default | ||
291 … | + - i find this can be confusing for beginners who don't understand the special syntax and complex implementation details | ||
292 … | +- in the wild, export default breaks CommonJS code | ||
261 | 293 … | - 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 | |
262 | 294 … | ||
263 | 295 … | --- | |
264 | 296 … | class: success | |
@@ -301,20 +333,22 @@ | |||
301 | 333 … | ||
302 | 334 … | ```js | |
303 | 335 … | import React from 'react' | |
304 | 336 … | ||
305 | -export default Table | ||
306 | - | ||
307 | -function Table ({ table }) { | ||
308 | - return <table className='table'> | ||
309 | - {table.map(row => { | ||
310 | - <tr className='row'> | ||
311 | - {row.map(item => { | ||
312 | - <td className='item'>{item}</td> | ||
313 | - }) | ||
314 | - </tr> | ||
315 | - }) | ||
316 | - </table> | ||
337 … | +export default function ({ rows }) { | ||
338 … | + return ( | ||
339 … | + <Table> | ||
340 … | + {rows.map(row => | ||
341 … | + <Row> | ||
342 … | + {row.map(item => | ||
343 … | + <Item> | ||
344 … | + {item} | ||
345 … | + </Item> | ||
346 … | + )} | ||
347 … | + </Row> | ||
348 … | + )} | ||
349 … | + </Table> | ||
350 … | + ) | ||
317 | 351 … | } | |
318 | 352 … | ``` | |
319 | 353 … | ||
320 | 354 … | ??? | |
@@ -324,8 +358,21 @@ | |||
324 | 358 … | - hides that React is actually `React.createElement` function calls | |
325 | 359 … | - "why can't i use `if () { first } else { second }`? | |
326 | 360 … | - can only use expressions, not statements | |
327 | 361 … | ||
362 … | +```js | ||
363 … | +function Table ({ children }) { | ||
364 … | + return <table className='table'>{children}</table> | ||
365 … | +} | ||
366 … | + | ||
367 … | +function Row ({ children }) { | ||
368 … | + return <tr className='row'>{children}</tr> | ||
369 … | +} | ||
370 … | + | ||
371 … | +function Item ({ children }) { | ||
372 … | + return <td className='item'>{children}</td> | ||
373 … | +}) | ||
374 … | +``` | ||
328 | 375 … | --- | |
329 | 376 … | class: success | |
330 | 377 … | ||
331 | 378 … | ### hyperscript | |
@@ -335,20 +382,42 @@ | |||
335 | 382 … | ||
336 | 383 … | module.exports = Table | |
337 | 384 … | ||
338 | 385 … | function Table ({ rows ) { | |
339 | - return h('table.table', rows.map(row => { | ||
340 | - h('tr.row', row.map(item => { | ||
341 | - h('td.item', item) | ||
386 … | + return h('table', { | ||
387 … | + className: 'table' | ||
388 … | + }, rows.map(row => { | ||
389 … | + h('tr', { | ||
390 … | + className: 'row' | ||
391 … | + }, row.map(item => { | ||
392 … | + h('td', { | ||
393 … | + className: 'item' | ||
394 … | + }, Item(item)) | ||
342 | 395 … | }) | |
343 | 396 … | }) | |
344 | 397 … | } | |
398 … | + | ||
345 | 399 … | ``` | |
346 | 400 … | ||
347 | 401 … | ??? | |
348 | 402 … | ||
349 | -- `React.createElement` is basically a strict hyperscript without the class/id sugar | ||
403 … | +- `React.createElement` is basically a strict hyperscript | ||
404 … | +- syntax can be confusing at first | ||
350 | 405 … | ||
406 … | +```js | ||
407 … | +function Table ({ children }) { | ||
408 … | + return <table className='table'>{children}</table> | ||
409 … | +} | ||
410 … | + | ||
411 … | +function Row ({ children }) { | ||
412 … | + return <tr className='row'>{children}</tr> | ||
413 … | +} | ||
414 … | + | ||
415 … | +function Item ({ children }) { | ||
416 … | + return <td className='item'>{children}</td> | ||
417 … | +}) | ||
418 … | +``` | ||
419 … | + | ||
351 | 420 … | --- | |
352 | 421 … | class: success | |
353 | 422 … | ||
354 | 423 … | ### hyperx | |
@@ -421,16 +490,23 @@ | |||
421 | 490 … | ||
422 | 491 … | a "continuable" is a function that takes a single argument, a node-style error-first callback | |
423 | 492 … | ||
424 | 493 … | ```js | |
425 | -const continuable = (cb) => { | ||
494 … | +const continuable = (callback) => { | ||
426 | 495 … | // do stuff... | |
427 | - cb(null, data) | ||
496 … | + callback(null, value) | ||
428 | 497 … | // oh no! | |
429 | - cb(error) | ||
498 … | + callback(error) | ||
430 | 499 … | } | |
431 | 500 … | ``` | |
432 | 501 … | ||
502 … | +```js | ||
503 … | +continuable((err, value) => { | ||
504 … | + if (err) console.error(err) | ||
505 … | + else console.log(value) | ||
506 … | +}) | ||
507 … | +``` | ||
508 … | + | ||
433 | 509 … | ??? | |
434 | 510 … | ||
435 | 511 … | a continuable is the callback version of a promise | |
436 | 512 … | ||
@@ -446,10 +522,10 @@ | |||
446 | 522 … | ||
447 | 523 … | module.exports = fetchCats | |
448 | 524 … | ||
449 | 525 … | function fetchCats ({ cats }) { | |
450 | - return cb => parallel(cats.map(cat => { | ||
451 | - return request(cat, cb) | ||
526 … | + return callback => parallel(cats.map(cat => { | ||
527 … | + return request(cat, callback) | ||
452 | 528 … | })) | |
453 | 529 … | }) | |
454 | 530 … | ``` | |
455 | 531 … | ||
@@ -459,10 +535,10 @@ | |||
459 | 535 … | ### async errors | |
460 | 536 … | ||
461 | 537 … | with a node-style error-first callback, there are three possible signals: | |
462 | 538 … | ||
463 | -1. value: `cb(null, value)` | ||
464 | -2. user error: `cb(error)` | ||
539 … | +1. value: `callback(null, value)` | ||
540 … | +2. user error: `callback(error)` | ||
465 | 541 … | 3. programmer error: `throw error` | |
466 | 542 … | ||
467 | 543 … | ??? | |
468 | 544 … | ||
@@ -506,8 +582,17 @@ | |||
506 | 582 … | - [`push-stream`](https://github.com/ahdinosaur/push-stream) | |
507 | 583 … | - [`mutant`](https://github.com/mmckegg/mutant) | |
508 | 584 … | ||
509 | 585 … | --- | |
586 … | +class: success | ||
587 … | + | ||
588 … | +```js | ||
589 … | +TODO add mutant html example | ||
590 … | +``` | ||
591 … | + | ||
592 … | +??? | ||
593 … | + | ||
594 … | +--- | ||
510 | 595 … | class: center, info | |
511 | 596 … | ||
512 | 597 … | ## values over time | |
513 | 598 … | ||
@@ -541,9 +626,9 @@ | |||
541 | 626 … | ||
542 | 627 … | async streams using only functions! | |
543 | 628 … | ||
544 | 629 … | ```js | |
545 | -pull(source(), through(), sink()) | ||
630 … | +pull(source, through, sink) | ||
546 | 631 … | ``` | |
547 | 632 … | ||
548 | 633 … | - composable partial pipelines | |
549 | 634 … | - unbuffered by default | |
@@ -562,23 +647,27 @@ | |||
562 | 647 … | ||
563 | 648 … | --- | |
564 | 649 … | class: success | |
565 | 650 … | ||
566 | -##### source usage | ||
651 … | +#### source spec | ||
567 | 652 … | ||
568 | 653 … | ```js | |
569 | -const source = values([0, 1, 2, 3]) | ||
570 | - | ||
571 | -source(null, (err, value) { | ||
572 | - console.log('first value:', value) | ||
573 | -}) | ||
574 | -// first value: 0 | ||
654 … | +function createSource (...args) { | ||
655 … | + // a source function accepts | ||
656 … | + // - abort: a boolean whether to signal end | ||
657 … | + // - callback: where to send next signal | ||
658 … | + return source (abort, callback) => { | ||
659 … | + if (abort || done) callback(true) | ||
660 … | + else callback(null, value) | ||
661 … | + } | ||
662 … | +} | ||
575 | 663 … | ``` | |
576 | 664 … | ||
577 | ---- | ||
578 | -class: success | ||
665 … | +??? | ||
579 | 666 … | ||
580 | -##### source example | ||
667 … | +- look ma, just functions! | ||
668 … | +- yes, we are using callbacks even for synchronous results | ||
669 … | + - much faster this way, no reason to delay til next tick | ||
581 | 670 … | ||
582 | 671 … | ```js | |
583 | 672 … | function values (array) { | |
584 | 673 … | var i = 0 | |
@@ -586,96 +675,139 @@ | |||
586 | 675 … | if (abort || i === array.length) { | |
587 | 676 … | callback(true) | |
588 | 677 … | } | |
589 | 678 … | else { | |
590 | - cb(null, array[i++] | ||
679 … | + callback(null, array[i++] | ||
591 | 680 … | } | |
592 | 681 … | } | |
593 | 682 … | } | |
594 | 683 … | ``` | |
595 | 684 … | ||
596 | -??? | ||
597 | - | ||
598 | -- look ma, just functions! | ||
599 | -- yes, we are using callbacks even for synchronous results | ||
600 | - - much faster this way, no reason to delay til next tick | ||
601 | - | ||
602 | 685 … | --- | |
603 | 686 … | class: success | |
604 | 687 … | ||
605 | -#### sink usage | ||
688 … | +#### source usage | ||
606 | 689 … | ||
607 | 690 … | ```js | |
691 … | +const values = require('pull-stream/sources/values') | ||
692 … | + | ||
608 | 693 … | const source = values([0, 1, 2, 3]) | |
609 | 694 … | ||
610 | -log(source) | ||
611 | -// 0 | ||
612 | -// 1 | ||
613 | -// 2 | ||
614 | -// 3 | ||
695 … | +source(null, (err, value) { | ||
696 … | + console.log('first value:', value) | ||
697 … | +}) | ||
698 … | +// first value: 0 | ||
615 | 699 … | ``` | |
616 | 700 … | ||
617 | 701 … | --- | |
618 | 702 … | class: success | |
619 | 703 … | ||
620 | -#### sink example | ||
704 … | +#### sink spec | ||
621 | 705 … | ||
622 | 706 … | ```js | |
623 | -function log (read) { | ||
624 | - read(null, function next (err, data) { | ||
707 … | +function createSink (...args) { | ||
708 … | + // a sink function accepts a source | ||
709 … | + return (source) => { | ||
710 … | + // reads a value from the source | ||
711 … | + source(null, function next (err, value) { | ||
712 … | + // handle the result | ||
713 … | + if (err) return handleError(err) | ||
714 … | + handleValue(value) | ||
715 … | + | ||
716 … | + // recursively call source again! | ||
717 … | + source(null, next) | ||
718 … | + }) | ||
719 … | + } | ||
720 … | +} | ||
721 … | +``` | ||
722 … | + | ||
723 … | +??? | ||
724 … | + | ||
725 … | +- `handleError` might abort the source and call a done callback passed in through the args | ||
726 … | +- `handleValue` might do something with each value | ||
727 … | + | ||
728 … | + | ||
729 … | +```js | ||
730 … | +function log (source) { | ||
731 … | + source(null, function next (err, data) { | ||
625 | 732 … | if (err) return console.log(err) | |
626 | 733 … | console.log(data) | |
627 | - // recursively call read again! | ||
628 | - read(null, next) | ||
734 … | + // recursively call source again! | ||
735 … | + source(null, next) | ||
629 | 736 … | }) | |
630 | 737 … | } | |
631 | 738 … | ``` | |
632 | 739 … | ||
633 | -??? | ||
634 | - | ||
635 | 740 … | with continuables: | |
636 | 741 … | ||
637 | 742 … | ```js | |
638 | -function log (read) { | ||
639 | - return (cb) => { | ||
640 | - read(null, function next (err, data) { | ||
641 | - if (err) return cb(err) | ||
743 … | +function log (source) { | ||
744 … | + return (callback) => { | ||
745 … | + source(null, function next (err, data) { | ||
746 … | + if (err) return callback(err) | ||
642 | 747 … | console.log(data) | |
643 | - // recursively call read again! | ||
644 | - read(null, next) | ||
748 … | + // recursively call source again! | ||
749 … | + source(null, next) | ||
645 | 750 … | }) | |
646 | 751 … | } | |
647 | 752 … | } | |
648 | 753 … | ``` | |
649 | 754 … | ||
650 | 755 … | --- | |
651 | 756 … | class: success | |
652 | 757 … | ||
653 | -#### through usage | ||
758 … | +#### sink usage | ||
654 | 759 … | ||
655 | 760 … | ```js | |
761 … | +const values = require('pull-stream/sources/values') | ||
762 … | +const drain = require('pull-stream/sinks/drain') | ||
763 … | + | ||
656 | 764 … | const source = values([0, 1, 2, 3]) | |
657 | -const double = map(x => x * 2) | ||
765 … | +const log = drain(console.log) | ||
658 | 766 … | ||
659 | -log(double(source)) | ||
767 … | +log(source) | ||
768 … | +// 0 | ||
769 … | +// 1 | ||
770 … | +// 2 | ||
771 … | +// 3 | ||
660 | 772 … | ``` | |
661 | 773 … | ||
662 | 774 … | --- | |
663 | 775 … | class: success | |
664 | 776 … | ||
665 | -#### through example | ||
777 … | +#### through spec | ||
666 | 778 … | ||
667 | 779 … | ```js | |
780 … | +function createThrough (...args) { | ||
781 … | + // a sink function: accept a source | ||
782 … | + return (source) => { | ||
783 … | + // but return another source! | ||
784 … | + return (abort, callback) { | ||
785 … | + // if the through should abort, pass that on. | ||
786 … | + source(abort, (err, value) => { | ||
787 … | + // if the source has an error, pass that on. | ||
788 … | + if (err) callback(err) | ||
789 … | + // else transform the value | ||
790 … | + else callback(null, transformValue(value)) | ||
791 … | + }) | ||
792 … | + } | ||
793 … | + } | ||
794 … | +} | ||
795 … | +``` | ||
796 … | + | ||
797 … | +??? | ||
798 … | + | ||
799 … | +```js | ||
668 | 800 … | function map (mapper) { | |
669 | 801 … | // a sink function: accept a source | |
670 | - return function (read) { | ||
802 … | + return function (source) { | ||
671 | 803 … | // but return another source! | |
672 | - return function (abort, cb) { | ||
673 | - read(abort, function (err, data) { | ||
804 … | + return function (abort, callback) { | ||
805 … | + source(abort, function (err, data) { | ||
674 | 806 … | // if the stream has ended, pass that on. | |
675 | - if (err) cb(err) | ||
807 … | + if (err) callback(err) | ||
676 | 808 … | // apply a mapping to that data | |
677 | - else cb(null, mapper(data)) | ||
809 … | + else callback(null, mapper(data)) | ||
678 | 810 … | }) | |
679 | 811 … | } | |
680 | 812 … | } | |
681 | 813 … | } | |
@@ -683,13 +815,47 @@ | |||
683 | 815 … | ||
684 | 816 … | --- | |
685 | 817 … | class: success | |
686 | 818 … | ||
819 … | +#### through usage | ||
820 … | + | ||
821 … | +```js | ||
822 … | +const values = require('pull-stream/sources/values') | ||
823 … | +const drain = require('pull-stream/sinks/drain') | ||
824 … | +const map = require('pull-stream/throughs/map') | ||
825 … | + | ||
826 … | +const source = values([0, 1, 2, 3]) | ||
827 … | +const log = drain(console.log) | ||
828 … | +const double = map(x => x * 2) | ||
829 … | + | ||
830 … | +log(double(source)) | ||
831 … | +// 0 | ||
832 … | +// 2 | ||
833 … | +// 4 | ||
834 … | +// 6 | ||
835 … | +``` | ||
836 … | + | ||
837 … | +--- | ||
838 … | +class: success | ||
839 … | + | ||
840 … | +#### compose pull streams | ||
841 … | + | ||
842 … | +```js | ||
843 … | +pull(source, through) // returns source | ||
844 … | + | ||
845 … | +pull(through, sink) // returns sink | ||
846 … | + | ||
847 … | +pull(source, sink) // runs to end | ||
848 … | +``` | ||
849 … | + | ||
850 … | +--- | ||
851 … | +class: success | ||
852 … | + | ||
687 | 853 … | #### wild pull streams | |
688 | 854 … | ||
689 | 855 … | ecosystem of modules: [pull-stream.github.io](https://pull-stream.github.io) | |
690 | 856 … | ||
691 | -``` | ||
857 … | +```js | ||
692 | 858 … | // parse a csv file | |
693 | 859 … | pull( | |
694 | 860 … | File(filename), | |
695 | 861 … | CSV(), | |
@@ -716,12 +882,12 @@ | |||
716 | 882 … | #### pull stream errors | |
717 | 883 … | ||
718 | 884 … | with a pull stream source callback, there are four possible signals: | |
719 | 885 … | ||
720 | -1. value: `cb(null, value)` | ||
721 | -2. user error: `cb(error)` | ||
886 … | +1. value: `callback(null, value)` | ||
887 … | +2. user error: `callback(error)` | ||
722 | 888 … | 3. programmer error: `throw error` | |
723 | -4. complete: `cb(true)` | ||
889 … | +4. complete: `callback(true)` | ||
724 | 890 … | ||
725 | 891 … | ??? | |
726 | 892 … | ||
727 | 893 … | - both the source and sink can signal back-pressure ("hey i'm busy") by not calling the respective callback | |
@@ -752,67 +918,31 @@ | |||
752 | 918 … | ||
753 | 919 … | ??? | |
754 | 920 … | ||
755 | 921 … | - clear inputs and outputs | |
756 | -- no hidden state to manage | ||
922 … | +- small code blocks (or "snippets") can be deceiving | ||
923 … | + - leads to a positive first impression, until you use in production where the edge cases leak through the abstractions | ||
924 … | + - i find nothing more difficult than edge cases at scale caused by hiding complexity in our tools | ||
757 | 925 … | ||
758 | 926 … | --- | |
759 | 927 … | class: success | |
760 | 928 … | ||
761 | -### easier to understand | ||
929 … | +### path to mastery | ||
762 | 930 … | ||
763 | -less "snippet-driven development" | ||
764 | - | ||
765 | -more learnable tools focused on power users | ||
766 | - | ||
767 | -??? | ||
768 | - | ||
769 | -- is probably a contentious opinion: | ||
770 | - - yes promises are more "intuitive" than callbacks, a beginner can start using with less learning, training, or practice | ||
771 | - | ||
772 | - 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. | ||
773 | - | ||
774 | - He intended to boost collective intelligence and enable knowledge workers to think in powerful new ways, to collectively solve urgent global problems. | ||
775 | - | ||
776 | -> 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. | ||
777 | - | ||
778 | ---- | ||
779 | -class: info | ||
780 | - | ||
781 | -#### augment human intellect | ||
782 | - | ||
783 | 931 … | learnable tools focused on power users | |
784 | 932 … | ||
785 | -<img src="./engelbart.jpg" height="350" class="center" /> | ||
933 … | +<img src="./training-wheels.jpg" height="350" class="center" /> | ||
786 | 934 … | ||
787 | 935 … | ??? | |
788 | 936 … | ||
789 | -- i take the Douglas Engelbart approach to developer experience | ||
790 | - - technology should augment human intellect, which means it should be a learnable tool focused on power users | ||
791 | - - priority is not ease of use but powerful human computer expression | ||
937 … | +- training wheels are great to get started and go around the blockS | ||
938 … | +- yes promises are easier than callbacks, a beginner can start using with less learning, training, or practice | ||
939 … | +- but when you want to go up a hill or go a long distance, you want a real bike | ||
940 … | + - this takes time to learn how to steer and balance on | ||
941 … | +- how many hours to do we spend writing complex code, is the most intuitive abstraction best suited for our evolving understanding? | ||
942 … | + - here's one of many possible abstractions, but is not the end answer | ||
792 | 943 … | ||
793 | -references: | ||
794 | - | ||
795 | -- https://alistapart.com/column/douglas-engelbart | ||
796 | -- http://www.dougengelbart.org/pubs/augment-3906.html | ||
797 | -- http://99percentinvisible.org/episode/of-mice-and-men/ | ||
798 | - | ||
799 | 944 … | --- | |
800 | -class: info | ||
801 | - | ||
802 | -#### remove the training wheels! | ||
803 | - | ||
804 | -<img src="./training-wheels.jpg" height="425" class="center" /> | ||
805 | - | ||
806 | - | ||
807 | -??? | ||
808 | - | ||
809 | -"You don’t need any special training to operate a tricycle, and that’s fine if you’re just going to go around the block. If you’re trying to go up a hill or go a long distance, you want a real bike. The kind with gears and brakes– the kind that takes time to learn how to steer and balance on." | ||
810 | - | ||
811 | -how many hours do we spend writing complex code, why should we keep using the training-wheel abstractions best suited for unexperienced newbies? | ||
812 | - | ||
813 | - | ||
814 | ---- | ||
815 | 945 … | class: center, info | |
816 | 946 … | ||
817 | 947 … | ## stories | |
818 | 948 … | ||
@@ -826,37 +956,14 @@ | |||
826 | 956 … | <img src="./catstack.jpg" height="350" class="center" /> | |
827 | 957 … | ||
828 | 958 … | ??? | |
829 | 959 … | ||
830 | -reinvent every wheel possible! | ||
960 … | +reinvent every wheel possible! the entire web stack. | ||
831 | 961 … | ||
832 | 962 … | https://github.com/root-systems/catstack | |
833 | 963 … | ||
834 | 964 … | i did it, but it was unsustainable, unable to transfer context to team | |
835 | 965 … | ||
836 | -- ui views | ||
837 | - - hyps | ||
838 | - - hyper-fela | ||
839 | -- ui state | ||
840 | - - inu-engine | ||
841 | - - inu | ||
842 | - - inu-log | ||
843 | - - inu-router | ||
844 | -- http handlers | ||
845 | - - http-compose | ||
846 | - - http-sender | ||
847 | - - http-routes | ||
848 | -- services | ||
849 | - - vas | ||
850 | - - vas-http | ||
851 | -- modules | ||
852 | - - depject | ||
853 | - - depnest | ||
854 | - - depject-priority | ||
855 | -- framework | ||
856 | - - module system | ||
857 | - - command-line tasks | ||
858 | - | ||
859 | 966 … | --- | |
860 | 967 … | class: warning | |
861 | 968 … | ||
862 | 969 … | ### learning: | |
@@ -925,17 +1032,23 @@ | |||
925 | 1032 … | class: success, center | |
926 | 1033 … | ||
927 | 1034 … | #### offline social media | |
928 | 1035 … | ||
929 | -<img src="./patchwork-screenshot.jpg" height="500" class="center" /> | ||
1036 … | +<http://patchwork.campjs.com> | ||
930 | 1037 … | ||
1038 … | +<img src="./patchwork-screenshot.jpg" height="400" class="center" /> | ||
1039 … | + | ||
931 | 1040 … | --- | |
932 | 1041 … | class: success, center | |
933 | 1042 … | ||
934 | 1043 … | #### git projects | |
935 | 1044 … | ||
936 | -<img src="./git-ssb-screenshot.png" height="450" class="center" /> | ||
1045 … | +```js | ||
1046 … | +npm install -g git-ssb | ||
1047 … | +``` | ||
937 | 1048 … | ||
1049 … | +<img src="./git-ssb-screenshot.png" height="400" class="center" /> | ||
1050 … | + | ||
938 | 1051 … | --- | |
939 | 1052 … | class: success | |
940 | 1053 … | ||
941 | 1054 … | ### learning: mad science works! | |
@@ -961,9 +1074,9 @@ | |||
961 | 1074 … | ### so what | |
962 | 1075 … | ||
963 | 1076 … | everyone has opinions. | |
964 | 1077 … | ||
965 | -this one is mine. :3 | ||
1078 … | +this one is mine. =^.^= | ||
966 | 1079 … | ||
967 | 1080 … | ??? | |
968 | 1081 … | ||
969 | 1082 … | as my Mom always says: |
index.html | ||
---|---|---|
The diff is too large to show. Use a local git client to view these changes. Old file size: 22902 bytes New file size: 900334 bytes |
package.json | ||
---|---|---|
@@ -4,9 +4,9 @@ | ||
4 | 4 … | "description": "Luddite.js, or how to write quality JavaScript apps using only functions and objects.", |
5 | 5 … | "main": "index.js", |
6 | 6 … | "scripts": { |
7 | 7 … | "present": "ecstatic .", |
8 | - "build": "markdown-to-slides -t 'Luddite.js' README.md -o index.html -s index.css -j index.js", | |
8 … | + "build": "markdown-to-slides -t 'Luddite.js' README.md -o index.html -s index.css -j index.js -i", | |
9 | 9 … | "watch": "npm run build -- -w", |
10 | 10 … | "livereload": "wtch -d . -e html,css,png,gif,jpg | garnish --level debug", |
11 | 11 … | "static": "ecstatic-lr .", |
12 | 12 … | "start": "npm-run-all -p watch livereload static", |
Built with git-ssb-web