GPTScript / AiScript

A Minimal, Full-Stack, Tool-Assisted Language. Native to Browsers and Bun. Strictly & Strongly-Typed.
https://github.com/GPTScript/AiScript
Mozilla Public License 2.0
9 stars 1 forks source link

Axioms of AJ #28

Open coolaj86 opened 2 years ago

coolaj86 commented 2 years ago

An Expert's Guide to Navigating JavaScript in the 22nd Century

Work In Progress

Words that resonate through the halls of the Zen of Python, the Go Proverbs, and other Creeds of Craftsmanship...

0. Limit usefulness
1. Don't Make Waves
2. Less Magic in Code, More Magic in Tooling
3. return something, or return nothing
4. return await, or await without return
5. let errors bubble until they burst \
   (Correct or Classify, but do not Catch)
6. Gatekeepers at the gates, Doorkeepers at the doors
7. Interfaces over Generics
8. No worthless abstractions \
   (_Abstractions should be deep - John Ousterhout_)
9. But by the 3rd or 4th time, you should know what it is
10. await catch: Don't trade one pyramid of doom for another 
11. It's easier to read from top to bottom than left to right, or right to top \
  (return early)
12. Optimize for the happy path (not for exceptions)
13. _When it is broken, it is the right time to fix it - Chinese Fortune Cookie_
14. The constraint of the medium defines the Art \
   "Anything goes" is _not_ a workable constraint
15. For every metric, a counter metric
16. If it sounds cool, DON'T DO IT 🚨!

Need a more succinct way to say "We did what we always do when there’s a problem without a clear solution: we waited. Waiting gives us more time to add experience and understanding of the problem and also more time to find a good solution." - Toward Go 2

"return await, or await without return"

Omitting the await as a shortcut is cute, but likely to lead to bugs when you need to refactor later on:

return fetchResponse.json()

// becomes
let data = fetchResponse.json()
data.foo = 'foo'; // ❌
return data;

vs

return await fetchResponse.json()

// becomes
let data = await fetchResponse.json()
data.foo = 'foo'; // ✅
return data;
coolaj86 commented 2 years ago

"return something, or return nothing"

returns should convey meaning.

Bad Examples

if (x) {
    return res.json(x);
}
function runJob() {
    return otherWiseUnusedPromisableThing()
}

This axiom was intended to apply at the language level, but it also serves at the framework level. This is bad:

res.json()

Good Examples

if (x) {
    res.json(x);
    return;
}
async function runJob() {
    await otherWiseUnusedPromisableThing()
}
res.json({ success: true });
coolaj86 commented 2 years ago

"let errors bubble, until they burst"

Correct, Classify, but don't Catch

Preferential order for dealing with errors:

1. Correct the mistake

Ex: ENOENT => Fs.mkdir(path, { recursive: true })

2. Classify the error

Ex: mustValidate(userInput) throws an error with err.status = 400

3. but do NOT Catch

Don't catch uncorrectable errors locally. Let them bubble up.

Ex: notFatalButShouldBeLogged() throws an error with err.code = 'E_WARN', which is caught and logged by a top-level error handler

Bad Ex:

try {
    oops();
} catch(e) {
    /* silencing because not sure what to do here */ 
}
coolaj86 commented 2 years ago

"limit usefulness"

"Perfection is achieved, not when there is nothing more to add, \ but when there is nothing left to take away." - Antoine de Saint-Exupéry

One of the human assets that becomes a real problem when programming is that we can find anything useful - even when it's not for its intended or optimal use. So much so, in fact, that we have an entire area of study dedicated to it - it's called "Art".

Instead, I argue for the RISC (Reduced Instruction Set Computer) principle - less mental burden, fewer edge cases, etc.