Gary Bernhardt Profile picture
Execute Program (learn programming tools quickly); Destroy All Software (dense programming screencasts); formerly Deconstruct conference.
2 subscribers
Mar 4, 2023 7 tweets 1 min read
1960s: "COBOL will let non-programmers make the software!"

1980s: "4GLs will let non-programmers make the software!"

2000s: "UML will let non-programmers make the software!"

2020s: "AI will let non-programmers make the software!" I am so tired
Nov 25, 2020 4 tweets 1 min read
So deep in a rabbit hole of made-up webpack work that shouldn't exist that I'm seriously considering using esbuild, not even worrying about code splitting or caching, and letting every client download 6 MB of JS on every pageload... We do all of this soul-sucking, inscrutable work to save our users from 100 ms of waiting? This is the trade-off that we've made?
Nov 18, 2020 4 tweets 1 min read
I will never get over this Image Free library idea: wrap the Date type and date-fns. Your Date wrapper's type exposes nothing on Date; it's opaque. Your date-fns wrapper has TS types that take only wrapped Dates. You also provide an eslint rule that disallows the built-in Date. Now I can have Date without Date.
Oct 28, 2020 4 tweets 2 min read
New YouTube channel! The first video is "End-to-End TypeScript: Database, Backend, API, and Frontend". It shows our end-to-end type guarantees from the backend database all the way to the React props. Demoed live using @exec_prog's codebase as the example. This is what @adamwathan and I talked about on @fullstackradio (fullstackradio.com/144). But seeing it in action probably makes it more tangible.
May 28, 2020 12 tweets 3 min read
I see people claim that TypeScript is "really a linter, not a static type system" pretty often. This is a strange thing to say. It's unsound and you can turn the type system off. But that sentence is true of every popular static type system in the history of programming. TypeScript: x as any
C: (void *)x
Java: (Object)x

This is totally normal for static type systems with widespread adoption. Java is not a "linter".
Mar 17, 2020 9 tweets 2 min read
The longer I spend on an SPA, the more it feels like reimplementing the entire browser myself. Example: you set titles per-page. But then those titles persist when navigating to a different page. So you have to always set the page title on navigation, reimplementing the browser. Likewise for the meta description tag: you have to actually find and modify the <meta name="description"> DOM node every time the user navigates to a new page. (And implementing the entire concept of "page" is your problem!)
Mar 16, 2020 7 tweets 2 min read
Pretty wild future where the company that actively tried to discredit and destroy the entire concept of open source for an entire decade now owns both the world's largest site for hosting open source repositories and the world's largest open source package manager. I'm still 50/50 on whether we see the embrace->extend->extinguish cycle play out here in the long term. The old guard still lives.
Mar 15, 2020 13 tweets 3 min read
Web apps with hashes in asset filenames have this problem:

1. A deploy starts.
2. A browser starts loading a page.
3. The deploy finishes.
4. The browser requests assets referenced by the page.
5. Those assets no longer exist due to the deploy. What's the standard solution to this? We're on Heroku, so the old asset files aren't available after a fresh deploy. I can write a server-side route that detects requests for old assets and... I'm not even sure what it should do. But presumably there's a standard solution?
Mar 14, 2020 7 tweets 2 min read
I'd rather spend 3 hours writing my own small library than some unknown but non-zero number of hours in the future fixing my app because it was broken by an update in some upstream tool I've been very happy maintaining Execute Program, which uses Express and React and not a lot else (e.g. it has its own 116-line database library). By contrast, I'm trying to update Destroy All Software from Rails 5.2.3 to Rails 5.2.4.1 and it doesn't even boot.
Mar 6, 2020 10 tweets 2 min read
Taking any one design technique "too far" is a really good way to learn about design! ...until it starts to feel like a silver bullet, at which point you risk frog-boiling yourself, contorting the entire design of your system to serve the silver bullet. Case study: "mocking only hurts because your design is wrong." E.g., specifically: "Your module depends on 5 others, which it shouldn't. Fix your module dependency graph and the tests will be easy." Five is definitely not a huge number of modules to depend on.
Sep 9, 2019 6 tweets 1 min read
I describe a problem. I get replies telling me to "just" use a solution that involves a million lines of third party code, or 200 transitive dependencies, or a README that says "not ready for production use", or, most often, doesn't even address the stated problem. Sometimes I get 20 of those! Then, suddenly, the 21st reply gives me a four-line function, with no dependencies, that completely solves the problem.
Sep 6, 2019 15 tweets 3 min read
Currently at 11 months since switching to TypeScript, probably 20 hours spent just trying to get a reliable build watcher (with easily 20,000 hours of Unix experience). I've never even gotten close. I'll go to my grave screaming that long-running stateful build tools never work. I just rewrote all of it for the nth time, but this time is fundamentally different. All of the dev processes are managed by a single 175-line script that starts, stops, and restarts them at the right times. The process that it runs never spawn children. Any leaks are my fault.
Aug 30, 2019 4 tweets 1 min read
Some people find the idea of ads in terminal software repulsive. Some people think it's a tolerable evil. NPM Inc. is not in either of these groups. NPM Inc. is a for-profit, VC-backed corporation, unlike every other language's package manager. Over the last year or so, everyone who went along with a for-profit package registry has started to see what they voted for. The ecosystem's most critical tool is controlled by a privately-held for-profit entity whose incentives aren't fully aligned with package authors or users.
Mar 18, 2019 10 tweets 3 min read
I just got the first big TypeScript port payoff. All API communication is statically checked on both the server and the client. I tested it by renaming ~100 identifiers at once. 3,914 lines of total diff. Once I got it to typecheck, it worked the first time. It took ~30 minutes. The idea of doing a huge identifier switch like this in Ruby fills me with fear. Without the huge effort of getting to 100% test coverage, it would cause so many bugs in obscure corners of the system. OTOH, the function I wrote to define checked server routes is 34 lines long.
Mar 8, 2019 6 tweets 2 min read
This tweet made me wonder: if we actually printed the dependencies of a "hello world" create-react-app app, how tall would the stack of paper be? Let's calculate. We'll use Pages' default margins and font size (11 pt). I arbitrarily choose Consolas as the font. That gives 49 lines of code per sheet.
Feb 18, 2019 5 tweets 2 min read
"code split across 20 different packages"... a newly generated create-react-app 2.1.5 app that doesn't actually do anything will have 1,568 dependencies.

$ npm ls --parseable | wc -l
[Errors elided. Why does a newly generated app error? -GRB]
1568

When I write tweets like this, some read it as "Gary hates JS". I like React and prefer it to all alternatives including HTML. I like and use TypeScript. Etc. That doesn't require me to think that "hello world" having 1,568 dependencies containing 1,119,218 LOC is a good idea.
Feb 7, 2019 4 tweets 1 min read
"Update all packages to latest versions" is scary, because what if one of those releases is an hour old and breaks something? I'd much rather do "update all packages to the latest version that is at least three days old." Does any package tool support that kind of update? Obviously this would be a problem if everyone did it, because then no release would get tested until day three. But I'd expect usage to stabilize into a group of slower-updating users who have stable apps in production, plus a group of faster-updating users working on new apps.
Jan 24, 2019 13 tweets 3 min read
There's no such thing as abstraction in web tools and never has been. Every framework claims that it will hide the complexity from you, but it always leaks through. You end up having to understand the framework, its dependencies, and the web primitives they're built on. Fool me n times (TurboGears, Django, Rails, Rollup, Webpack, etc.), shame on you. Fool me n+1 times, shame on me, I guess.
Dec 18, 2018 5 tweets 1 min read
I wrote a bunch of horribly awkward code, then deleted it and replaced it with eight lines of SQL (max width 64 chars). Greetings from 1974. Update: six lines!
Nov 26, 2018 9 tweets 2 min read
An NPM package with 2,000,000 weekly downloads had malicious code injected into it. No one knows what the malicious code does yet. github.com/dominictarr/ev… There are basically two camps in that thread.

1) This is the original maintainer's fault for transferring ownership to someone they didn't know and trust.
2) Ownership transfer was fine; it's your job to vet all of the code you run.
Nov 14, 2018 16 tweets 3 min read
An npm module named husky destructively added pre- and post-commit hooks to my dotfiles repo (literally ~/.git!). Or maybe some other module told it to do that. I never asked for that. I don't understand why the JavaScript tool ecosystem is like this! please don't "distrupt" my dotfiles, tech industry