README.mdView |
---|
20 | 20 … | ??? |
21 | 21 … | |
22 | 22 … | second time presenting at a conference. |
23 | 23 … | |
| 24 … | +i'm going to attack some JavaScript patterns, but i use those patterns too. |
| 25 … | + |
| 26 … | +everyone in the JavaScript community is doing a wonderful job. |
| 27 … | + |
24 | 28 … | apologies in advance if i disguise any opinions as facts. |
25 | 29 … | |
26 | 30 … | --- |
27 | 31 … | |
28 | | -# what? |
| 32 … | +## what? |
29 | 33 … | |
30 | | -luddite.js is a JavaScript framework to make building apps fun again |
| 34 … | +**luddite.js** is _simple decentralized JavaScript_. |
31 | 35 … | |
32 | | ---- |
| 36 … | +??? |
33 | 37 … | |
34 | | -## who are the Luddites? |
| 38 … | +a study of JavaScript evolution |
35 | 39 … | |
36 | | -[Luddites](https://en.wikipedia.org/wiki/Luddite) are people against _centralized technology_ which decreases quality of life. |
| 40 … | +also totally made up |
37 | 41 … | |
| 42 … | +JavaScript was good |
| 43 … | + |
| 44 … | +now it's popular |
| 45 … | + |
| 46 … | +here's the beef |
| 47 … | + |
38 | 48 … | --- |
39 | 49 … | |
| 50 … | +## Luddite? |
40 | 51 … | |
41 | | -## what is luddite.js? |
| 52 … | +the [Luddites](https://en.wikipedia.org/wiki/Luddite) was a political movement against _automated centralized technology_. |
42 | 53 … | |
43 | | -a movement against _centralized standards_ which decreases developer experience |
| 54 … | +<img src="./luddite.jpeg" /> |
44 | 55 … | |
45 | | ---- |
| 56 … | +??? |
46 | 57 … | |
47 | | -## what centralized standards? |
| 58 … | +- many Luddites were skilled machine operators in the textile industry |
| 59 … | +- they attacked centralized factories who used automated machines operated by unskilled labor |
| 60 … | +- they wanted machines to make high-quality goods, run by workers who had gone through an apprenticeship and got paid decent wages |
48 | 61 … | |
49 | 62 … | --- |
50 | 63 … | |
51 | | -### tc39 |
| 64 … | +## but JavaScript? |
52 | 65 … | |
53 | | -a great team advancing the state of the art in JavaScript, |
| 66 … | +at the |
54 | 67 … | |
55 | | -but is one of _many_ possible opinions about JavaScript. |
| 68 … | +- simple primitives |
| 69 … | +- decentralized userland |
56 | 70 … | |
57 | | ---- |
| 71 … | +??? |
58 | 72 … | |
59 | | -### what other opinions? |
| 73 … | +- top-down standards process |
| 74 … | + - vs emergent (mad science) bottom-up module ecosystems |
| 75 … | + - izs pants post |
60 | 76 … | |
61 | | ---- |
| 77 … | +## simple primitives |
62 | 78 … | |
63 | 79 … | what if i told you... |
64 | 80 … | |
65 | 81 … | that you only needed plain functions and objects? |
66 | 82 … | |
| 83 … | +??? |
| 84 … | + |
| 85 … | +- no fancy syntax |
| 86 … | +- less language clutter |
| 87 … | + |
| 88 … | +---- |
| 89 … | + |
| 90 … | +## sync function |
| 91 … | + |
| 92 … | +```js |
| 93 … | +function fn (...args) { return value } |
| 94 … | +``` |
| 95 … | + |
| 96 … | +```js |
| 97 … | +const fn = (...args) => { return value } |
| 98 … | +``` |
| 99 … | + |
| 100 … | +```js |
| 101 … | +const fn = (...args) => value |
| 102 … | +``` |
| 103 … | + |
| 104 … | + |
| 105 … | +```js |
| 106 … | +const fn = (...args) => ({ value }) |
| 107 … | +``` |
| 108 … | + |
67 | 109 … | --- |
68 | 110 … | |
69 | | -### modules |
| 111 … | +## sync function error |
70 | 112 … | |
71 | 113 … | ```js |
72 | | -// randomCat.js |
73 | | -const { random: randomCat } = require('cat-names') |
| 114 … | +function fn (...args) { throw error } |
| 115 … | +``` |
74 | 116 … | |
75 | | -module.exports = randomCat |
| 117 … | +```js |
| 118 … | +try { |
| 119 … | + fn(...args) |
| 120 … | +} catch (const err) { |
| 121 … | + // handle error |
| 122 … | +} |
76 | 123 … | ``` |
77 | 124 … | |
78 | | -??? |
| 125 … | +--- |
79 | 126 … | |
80 | | -we first create a `const` variable from a sync `require` function. |
| 127 … | +## require / module.exports = |
81 | 128 … | |
82 | | -we assign the result of this to a global variable `module.exports` |
| 129 … | +```js |
| 130 … | +const thing = require('module') |
| 131 … | +module.exports = thing |
| 132 … | +``` |
83 | 133 … | |
84 | | -not the hundred million special syntaxes to import and export es modules |
| 134 … | +```js |
| 135 … | +const { thing: thingy } = require('module') |
| 136 … | +module.exports = { thing: thingy } |
| 137 … | +``` |
85 | 138 … | |
| 139 … | +--- |
86 | 140 … | |
87 | | -## functions |
| 141 … | +## vs: import / export |
88 | 142 … | |
89 | 143 … | ```js |
90 | | -// randomCatAsync.js |
91 | | -const randomCat = require('./randomCat') |
| 144 … | +import thing from 'module' |
| 145 … | +import { thing as thingy } from 'module' |
| 146 … | +``` |
92 | 147 … | |
93 | | -module.exports = function randomCatAsync (cb) { |
94 | | - try { |
95 | | - cb(null, randomCat()) |
96 | | - } catch (err) { |
97 | | - cb(err) |
98 | | - } |
| 148 … | +--- |
| 149 … | + |
| 150 … | +## hyperscript |
| 151 … | + |
| 152 … | +```js |
| 153 … | +const h = require('react-hyperscript') |
| 154 … | + |
| 155 … | +module.exports = Table |
| 156 … | + |
| 157 … | +function Table ({ rows ) { |
| 158 … | + return h('table.table', rows.map(row => { |
| 159 … | + h('tr.row', row.map(item => { |
| 160 … | + h('td.item', item) |
| 161 … | + }) |
| 162 … | + }) |
99 | 163 … | } |
| 164 … | +``` |
| 165 … | + |
100 | 166 … | --- |
101 | 167 … | |
102 | | -## sync functions |
| 168 … | +## vs: jsx |
103 | 169 … | |
| 170 … | +```js |
| 171 … | +const React = require('react') |
104 | 172 … | |
105 | | -``` |
106 | | -function fn () { |
107 | | - try { |
108 | | - return value() |
109 | | - } catch (err) {} |
| 173 … | +export default function Table ({ rows ) { |
| 174 … | + return <table className='table'> |
| 175 … | + {rows.map(row => { |
| 176 … | + <tr className='row'> |
| 177 … | + {row.map(item => { |
| 178 … | + <td className='item'>{item}</td> |
| 179 … | + })} |
| 180 … | + </tr> |
| 181 … | + }) |
| 182 … | + </table> |
110 | 183 … | } |
111 | 184 … | ``` |
112 | 185 … | |
113 | | -## async functions |
| 186 … | +--- |
114 | 187 … | |
115 | | -### `cb(err, value()) |
| 188 … | +async function |
116 | 189 … | |
117 | | -## aids |
| 190 … | +--- |
118 | 191 … | |
119 | | -- [eating your own dog food](https://en.wikipedia.org/wiki/Eating_your_own_dog_food) |
120 | | -- [mad science method](https://github.com/ahdinosaur/mad-science-handbook/blob/master/collaboration.md#the-mad-science-cycle) |
121 | | -- [do-ocracy](https://communitywiki.org/wiki/DoOcracy) |
122 | | -- marathon: keep a slow & steady pace one step at a time |
123 | | -- if you see a job that needs doing, it's your job to do (do-ocrarcy) |
124 | | -- too much sugar is bad for your health (simple interfaces) |
| 192 … | +continable |
125 | 193 … | |
126 | | -## blocks |
| 194 … | +--- |
127 | 195 … | |
128 | | -- cave method: try to design or implement the _perfect_ system before sharing it |
129 | | -- [design by committee](https://en.wikipedia.org/wiki/Design_by_committee) |
130 | | -- sprint: hype, mania, and burn-out |
131 | | -- [waterfall design](https://en.wikipedia.org/wiki/Waterfall_model) |
| 196 … | +vs: promise |
132 | 197 … | |
133 | 198 … | --- |
134 | 199 … | |
135 | | -# 2009 |
| 200 … | +callback errors |
136 | 201 … | |
137 | | -## nobody cares about JavaScript |
| 202 … | +--- |
138 | 203 … | |
139 | | -> it's a toy language |
| 204 … | +promise errors |
140 | 205 … | |
141 | 206 … | --- |
142 | 207 … | |
143 | | -## Ryan Dahl (@ry) creates Node.js |
| 208 … | +observ-able |
144 | 209 … | |
145 | | -[watch the original presentation](https://www.youtube.com/watch?v=ztspvPYybIY) |
| 210 … | +--- |
146 | 211 … | |
147 | | -> To provide a *purely evented*, *non-blocking* infrastructure to script *highly concurrent* programs. |
| 212 … | +vs: es observable |
148 | 213 … | |
149 | | -(original website [here](https://web.archive.org/web/20091003131634/http://nodejs.org/)) |
| 214 … | +--- |
150 | 215 … | |
| 216 … | +pull stream |
151 | 217 … | |
152 | | -??? |
| 218 … | +--- |
153 | 219 … | |
154 | | -// core-less node? https://github.com/nodejs/node/issues/7098 |
155 | | -// https://github.com/nucleus-js/design |
| 220 … | +vs: wg-streams |
156 | 221 … | |
157 | 222 … | --- |
158 | 223 … | |
159 | | -## function |
| 224 … | +why am i picking on tc39? |
160 | 225 … | |
161 | | -```js |
162 | | -function (...args) { |
163 | | - return value |
164 | | -} |
165 | | -``` |
| 226 … | +--- |
166 | 227 … | |
| 228 … | +top-down decision-making |
| 229 … | + |
167 | 230 … | --- |
168 | 231 … | |
169 | | -## module |
| 232 … | +bloat |
170 | 233 … | |
171 | | -here's the CommonJS module system, as used and popularized by Node.js |
| 234 … | +- show code size of chrome |
| 235 … | +- fast software is less about building muscle and more about losing weight |
| 236 … | + - refactor in less code, not more fancy code |
172 | 237 … | |
173 | | -```js |
174 | | -// cat.js |
175 | | -require('cat-names').random |
176 | | -``` |
177 | | -```js |
178 | | -// cat-loop.js |
179 | | -const cat = require('./cat') |
| 238 … | +--- |
180 | 239 … | |
181 | | -setInterval(() => { |
182 | | - console.log(cat()) |
183 | | -}) |
184 | | -``` |
| 240 … | +snippet-driven development |
185 | 241 … | |
| 242 … | +- short snippets supposedly easier for beginners |
| 243 … | + - i work at a developer bootcamp, i'm not so sure |
| 244 … | + - too many ways to do something is confusing |
| 245 … | + - not being able to understand the primitive is confusing |
| 246 … | + |
186 | 247 … | --- |
187 | 248 … | |
188 | | -# [the module wrapper](https://nodejs.org/api/modules.html#modules_the_module_wrapper) |
| 249 … | +what is a standard? |
189 | 250 … | |
190 | | -every module is actually wrapped in a closure |
| 251 … | +- anything that enough people use is a "standard" |
191 | 252 … | |
192 | | -```js |
193 | | -(function (exports, require, module, __filename, __dirname) { |
194 | | - // your module code actually lives in here |
195 | | -}) |
196 | | -``` |
| 253 … | +example: `feross/standard` |
197 | 254 … | |
198 | 255 … | --- |
199 | 256 … | |
200 | | -# [how require works](https://github.com/maxogden/art-of-node#how-require-works) |
| 257 … | +how to we do better standards? |
201 | 258 … | |
202 | | -> When you call `require('some_module')` in node here is what happens: |
203 | | -> |
204 | | -> 1. if a file called `some_module.js` exists in the current folder node will load that, otherwise: |
205 | | -> 2. node looks in the current folder for a `node_modules` folder with a `some_module` folder in it |
206 | | -> 3. if it doesn't find it, it will go up one folder and repeat step 2 |
207 | | -> |
208 | | -> This cycle repeats until node reaches the root folder of the filesystem, at which point it will then check any global module folders (e.g. `/usr/local/node_modules` on Mac OS) and if it still doesn't find `some_module` it will throw an exception. |
| 259 … | +less coupling to trendy libraries, more function signature conventions: https://twitter.com/jekrb/status/859242655011745793 |
209 | 260 … | |
210 | 261 … | --- |
211 | 262 … | |
212 | | -# [the Node aesthetic](http://substack.net/node_aesthetic) |
| 263 … | +### redux |
213 | 264 … | |
214 | | -> - Callback austerity: Simplicity, asyncronous nature and nice additions that are included like the event system. |
215 | | -> - Limited surface area: Using modules instead of extending them, NPM, re-usable interfaces and simple, consistent function calls. |
216 | | -> - Batteries not included: Only few modules in the core distribution – reduces clutter, version dependencies and bureaucracy. |
217 | | -> - Radical reusability: Breaking up a problem in small pieces, NPM module locations, great versioning approach |
| 265 … | +--- |
218 | 266 … | |
| 267 … | +### tc39 |
219 | 268 … | |
| 269 … | +a great team advancing the state of the art in JavaScript, |
| 270 … | + |
| 271 … | +but is one of _many_ possible JavaScript standards. |
| 272 … | + |
220 | 273 … | --- |
221 | 274 … | |
222 | | -# factory |
| 275 … | +### what other standards? |
223 | 276 … | |
224 | | -> “The problem with object-oriented languages is they’ve got all this implicit environment that they carry around with them. You wanted a banana but what you got was a gorilla holding the banana and the entire jungle.” ~ Joe Armstrong |
| 277 … | +--- |
225 | 278 … | |
226 | | -- [The Two Pillars of JavaScript Part 1: How to Escape the 7th Circle of Hell](https://medium.com/javascript-scene/the-two-pillars-of-javascript-ee6f3281e7f3) |
227 | | -- [`stampit`](https://github.com/stampit-org/stampit) |
| 279 … | +what if i told you... |
228 | 280 … | |
229 | | -??? |
| 281 … | +that anyone can make a JavaScript _standard_? |
230 | 282 … | |
231 | | -TODO two ways of handling errors: throw err and cb(err) |
232 | | -how it's important to throw 'programmer errors' |
| 283 … | +--- |
233 | 284 … | |
| 285 … | +## standards in the wild |
| 286 … | + |
234 | 287 … | --- |
235 | 288 … | |
236 | | -# callback |
| 289 … | +### Node.js core |
237 | 290 … | |
238 | | -- [`run-series`](https://github.com/feross/run-series) |
239 | | -- [`run-parallel`](https://github.com/feross/run-parallel) |
240 | | -- [`run-auto`](https://github.com/feross/run-auto) |
241 | | -- [`run-waterfall`](https://github.com/feross/run-waterfall) |
| 291 … | +--- |
242 | 292 … | |
| 293 … | +#### `require` |
| 294 … | + |
243 | 295 … | --- |
244 | 296 … | |
245 | | -# continuable |
| 297 … | +#### `callback(error, result)` |
246 | 298 … | |
247 | | -a "continuable" is a function that takes a single argument, a node-style (error-1st) callback. |
| 299 … | +??? |
248 | 300 … | |
249 | | -```js |
250 | | -const continuable = (cb) => { |
251 | | - // do stuff... |
252 | | - cb(err, data) |
253 | | -} |
254 | | -``` |
| 301 … | +- simple, less edge cases |
| 302 … | + - for example, promise edge cases: https://pouchdb.com/2015/05/18/we-have-a-problem-with-promises.html |
| 303 … | +- callback hell vs promise hell |
255 | 304 … | |
256 | | -- [`continuable`](https://github.com/Raynos/continuable) |
257 | | -- [`cont`](https://github.com/dominictarr/cont) |
| 305 … | +--- |
258 | 306 … | |
| 307 … | +##### `async` ecosystem |
| 308 … | + |
| 309 … | +to make callbacks sane |
| 310 … | + |
259 | 311 … | --- |
260 | 312 … | |
261 | | -# observable |
| 313 … | +#### programmer errors |
262 | 314 … | |
263 | | -> - `thing()` gets the value |
264 | | -> - `thing.set(...)` sets the value |
265 | | -> - `thing(function (value) { ... })` listens to the value. |
| 315 … | +??? |
266 | 316 … | |
267 | | -- [`observ`](https://github.com/Raynos/observ) |
268 | | -- [`observable`](https://github.com/dominictarr/observable) |
269 | | -- [`push-stream`](https://github.com/ahdinosaur/push-stream) |
270 | | -- [`mutant`](https://github.com/mmckegg/mutant) |
| 317 … | +- promises deliberately break this paradigm: https://blog.domenic.me/youre-missing-the-point-of-promises/ |
| 318 … | +- i blame promises because they capture any thrown errors, which means thrown programmer errors (syntax, bad args, ...) are now swallowed. - https://twitter.com/ahdinosaur/status/864782131666370560 |
| 319 … | +- i'm curious how others deal with this. should i give up on simple intuition and embrace the new JS complexity with more complex dev tools? - https://twitter.com/ahdinosaur/status/864785376644218880 |
| 320 … | +- complexity is cruise control for cool. look at how many things i can do! the technical singularity will save us from our debt, all good bro. |
271 | 321 … | |
272 | 322 … | --- |
273 | 323 … | |
274 | | -# stream |
| 324 … | +### Node.js userland |
275 | 325 … | |
276 | | -- [`pull-stream`](https://pull-stream.github.io) |
277 | | -- [pull streams](http://dominictarr.com/post/149248845122/pull-streams-pull-streams-are-a-very-simple) |
278 | | -- [pull-stream-examples](https://github.com/dominictarr/pull-stream-examples) |
279 | 326 … | |
| 327 … | +??? |
| 328 … | + |
| 329 … | + |
280 | 330 … | --- |
281 | 331 … | |
282 | | -# references |
| 332 … | +#### hyperscript |
283 | 333 … | |
284 | | -- [es2040](https://github.com/ahdinosaur/es2040) |
285 | | -- [Art of Node](https://github.com/maxogden/art-of-node) |
286 | | -- [Art of I/O](http://ioschool.is/art-of-io/sessions/0/?notes=true) |
287 | | -- [Tiny Guide to Non Fancy Node](https://github.com/yoshuawuyts/tiny-guide-to-non-fancy-node) |
| 334 … | +--- |
288 | 335 … | |
| 336 … | +#### continuables |
| 337 … | + |
| 338 … | +--- |
| 339 … | + |
| 340 … | +#### observ-ables |
| 341 … | + |
| 342 … | +--- |
| 343 … | + |
| 344 … | +#### pull streams |
| 345 … | + |
| 346 … | + |
289 | 347 … | ??? |
290 | 348 … | |
291 | | -TODO luddite.js apps: |
| 349 … | +- [history of streams](http://dominictarr.com/post/145135293917/history-of-streams) |
| 350 … | +- [pull stream examples](https://github.com/dominictarr/pull-stream-examples) |
| 351 … | +- [pull streams intro](http://dominictarr.com/post/149248845122/pull-streams-pull-streams-are-a-very-simple) |
| 352 … | +- [pull stream](https://pull-stream.github.io/) |
| 353 … | +- [pull stream workshop](https://github.com/pull-stream/pull-stream-workshop) |
292 | 354 … | |
293 | | -- https://webtorrent.io/ |
294 | | -- http://standardjs.com/ |
295 | | -- https://peermaps.github.io/ |
296 | | -- http://loopjs.com/ |
297 | | -- https://scuttlebot.io/ |
298 | | -- https://choo.io/ |
| 355 … | +differences with node streams: |
| 356 … | + |
| 357 … | +- something you can't do using node streams (and probably wg-streams too), return a partial stream pipeline: https://twitter.com/ahdinosaur/status/860057158934712320 |
| 358 … | +- pull streams have pipeline error propagation by default, which is what `pump` does to get around node stream errors being per `.pipe()`. |
| 359 … | +- pull streams don't buffer by default, which is what `syncthrough` does to get around node stream buffers. |
| 360 … | + |
| 361 … | + |
| 362 … | +#### redux |
| 363 … | + |
| 364 … | +#### http middleware |
| 365 … | + |
| 366 … | +#### depject |
| 367 … | + |
| 368 … | +## stories |
| 369 … | + |
| 370 … | +### why |
| 371 … | + |
| 372 … | +> When engineering is about “solving interesting problems” and never about why these are problems, you get stuff like Uber. |
| 373 … | + |
| 374 … | +https://twitter.com/sanspoint/status/856185837582790655 |
| 375 … | + |
| 376 … | +### Node.js core |
| 377 … | + |
| 378 … | +- https://developer.ibm.com/node/2017/04/20/keeping-node-js-core-small/ |
| 379 … | + |
| 380 … | + |
| 381 … | +## references |
| 382 … | + |
| 383 … | +- [The Post JavaScript Apocalypse - Douglas Crockford](https://www.youtube.com/watch?v=NPB34lDZj3E) |