The world runs on software. When software is hard to change, so is the world
They say you can't teach software design. That it has to be learned through hard experience
That good programmers are born, not made
I say: challenge accepted
My magnum opus:
Programmer: "If someone types a letter at the beginning of a sentence, they probably want it capitalized."
Result: Powerpoint just tried to correct λ-calculus to Λ-calculus.
What makes good API documentation?
To answer this, we must ask: what do programmers need to know to use an API?
One paper claims there are three major parts
Enter "A Theory of Robust API Knowledge" by Kyle Thayer,
@sarahchasins
, and
@amyjko
.
🧵
Hyrum's Law: With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.
Solution: Destroy observable behaviors
Programming tip: Memorize your standard libraries
Make flashcards for the standard functions. If you don't use spaced repetition, then start.
I did this for Haskell years ago. It brought me from constantly looking at documentation to coding at the speed of thought
@JessicaHullman
On my way to Singapore in 2019, I read a 10-year old paper by
@ilyasergey
, and then asked about an error I found early on when we met
Why? It was directly related to the work I presented
Turns out, I'm allowed to be interested in things others were a long time ago
Me earlier this year: everything we do is just defunctionalization.
Me last month: everything I did 4 years ago was also just defunctionalization.
Just released: my guest post for the
@sigplan
blog (ed.
@michael_w_hicks
), giving a full 7 applications.
1/
Had a blast Monday giving a code-review guest lecture for MIT's 6.1040 "Software Studio" class with Daniel Jackson. Now my head's full of examples of good and bad frontend code.
n^2 likes = n+1 examples of making cleaner and more robust frontend code
First one's free.
4 years, 4 papers, and way too much fiddling with CSS later, I am pleased to finally release my Cubix "One Tool, Many Languages" framework to the world. May the days of single-language tools soon be behind us.
In 2019, I brought you defunctionalization, the "Best Refactoring You've Never Heard Of"
In 2023, enter: The best multicore-parallelization refactoring you've never heard of
Every time I hear someone advocate for teaching "practical" languages in universities, I recall the words of Mary Shaw, who helped create the field of software architecture. Had she succumbed, people would have learned JCL instead of algorithms.
Don't know what JCL is?
Exactly
ESR says: Learn Lisp. Even if you never use it, the profound enlightenment makes it worth it.
What’s today’s equivalent?
I think it’s Haskell.
Lisp is like learning a few extra tricks beyond what you already know.
Haskell is like learning to program all over again.
Yesterday we lost the 1984 Turing laureate, but no-one's talking about his deepest contribution: stepwise refinement
In 1971, he showed how to turn pseudocode into real code. 50 years later, refinement-based synthesis is being used to generate cryptography code in Chrome
RIP
Hyrum’s Law applies, even when you take into account Hyrum’s Law.
Go's map iteration order is random to prevent dependence on its order. Then someone made a load balancer depend on its randomness. But it wasn't random enough.
Language features by gap between invention and penetration in the mainstream languages
Algebraic data types: 40 years
Lambdas: 80 years
Existential quantifiers: 127 years and counting
Infinity: It'll be a while
@hillelogram
"Write simple code" is a classic case of citrus advice:
The only "serious" attempt I've seen to define complexity for a programming-related thing is (Defn. 2). Other approaches are stymied by focusing on code rather than logic.
Theo may have worked hard on this video, but it is dangerously wrong. The video is based on a couple of deep misconceptions, and can actively make your code harder to change.
The short explanation is "principal typing is not modular." What does that mean? Time for a 🧵
The two best-known codebases I've worked in are Postgres and Android ART. Postgres had this; ART did not. I learned Postgres's internals several times faster.
More codebases need developer walkthroughs that explain how the codebase does X.
"The TimeFarbler UI is in foo/bar, which pulls config from baz/blat. Most of the timefarble implementation is auditing; the actual mutation happens in the timefarble -> x -> y -> z call stack."
Sometimes I ask someone to learn something, and they just regurgitate the textbook. They don't realize that's not understanding
My trick: Bloom's taxonomy
They rate themselves, and realize they need to get to a higher level
And hopefully get cured of bad study habits forever
MYTH: Bad software design rarely causes business failures
FACT: Software design mistakes regular cause massive damage
Recent example:
Toyota blames "recent maintenance," but a single overflowing disk should not shut down 14 factories
1/
Last week, I went through “Designing Systems Programs” (1970), quite possible the world’s oldest software engineering book.
I've read many software writings rom the 70's that feel refreshingly modern and deeply insightful, even 40 years later.
But this is an alien text.
"FP languages" is a misnomer
There is only functional style.
Is OCaml a functional language? I know a professor who treats it as "C with types" and likes replacing list maps with for-loops
Is JavaScript a functional language? "SICP for JS" treats it as a skin on Scheme.
"There are two things to know about TLA+. The first is that it checks models, not code. The second is that its syntax makes no sense."
I've posted my review of
@hillelogram
's book, Practical TLA+:
Three months ago, I asked Mike to coteach my Reverse Engineering Course. Two months ago, he invited me to reverse-engineer a voting app with him. One month ago, we had some frightening results, and began disclosure. Thank you
@nytimes
; we're proud to share our work today.
Today, myself and co-authors
@jimmykoppel
and
@djweitzner
released a paper discussing a slew of vulnerabilities we found in
@voatz
, a blockchain voting app that's been used in US federal elections. You can read about it in the
@nytimes
!
Every programmer should learn the HS Traversable library
The easiest code to read has everything in 3 lines
The second easiest lets you glance at it and instantly see 3 chunks
That’s what understanding traversals gives you.
Even if you don’t use it, it will stretch your brain
Today’s software design example:
Memcache::set(…, expire=60*60*24*29) makes a key expire in 29 days
Memcache::set(…, expire=60*60*24*30)? 30 days
Memcache::set(…, expire=60*60*24*31)? Expires on February 1, 1970 (i.e.: instantly)
h/t
@edmondlau
Saying companies never die of tech debt is like saying people never die of old age
It’s always ‘Lost too many sales to competitors" “Couldn’t pivot fast enough”
But if they could produce 2x the features with half the bugs, maybe they'd have survived
Good software engineering
I've trained about 200 engineers, but there's a lot of bad software out there demanding more good people. It's going to take some serious tech to scale up.
Thank you to
@slatestarcodex
for this support, and to
@AndrewOlney1
and
@XiangenHu
for helping me enter the field of ITS.
"DRY" is a great example of an idea perverted by poor choice of name. The original presentation in The Pragmatic Programmer defined it basically as "single point of truth," but people assume it means "no syntactic clones."
@nicklockwood
@jimmykoppel
phrases it slightly differently as avoiding repetition of *concepts* rather than code, which I really like. I love this episode of
@corecursive
with him and recommend it to basically everyone.
Just because you can give your callers more information doesn't mean you should. Just because you can let them do more doesn't mean it's good.
For the power of a design lies not in what it can do, but in what it can't do.
Others are saying that dynamic/static and weak/strong is a false dichotomy.
But it goes further.
The way most programmers are taught categories of PLs is broken.
Think features, not families. Imperative is a feature, not a language. Pure is the default.
Genetics, not taxonomy
If there's programming language topic that really needs to be taught, it's the difference between static/dynamic typing and strong/weak typing. I've even had comp sci lecturers get the two confused, saying a language is weakly typed when what they mean is *dynamically* typed.
All code should be written with
1. The assumption it will never be replaced (because they cost isn't worth it)
2. The assumption it will be replaced in a year
One of the most important skills a developer can cultivate is understanding the knowledge and reasoning they are using to create code. Matt here is doing a fine job of showing the "why"
"Some programmers hardcoded the size of this thing was 4 bytes. Now I need to change them all."
2 hours of grep later: "K, found them all"
Testing: breaks, because you still missed some
Want that to stop? Come learn about our new Yogo tool at PLDI 2020:
Like it or not, the growth of JavaScript is unstoppable. It is now more than 50% of code on GitHub. It has evolved to fill every niche in the ecosystem. It is too fit
This can only mean one thing: Humanity is no longer the dominant species.
(1/3)
This is a boarding pass.
Why is there no space before his middle name?
It's because the name goes through a software system based on SABRE, which doesn't support middle names, and has a tight character limit.
Why? Way back when, IBM used to charge airlines per byte.
Among the worst advice about training is "The only way to get better at X is to just do X"
My last semester of college was spending 10 hours a week training for the ACM-ICPC World Finals. Twice a week, we'd race to code up algorithm problems faster than a recording of the
A Google engineer goes up for promotion. He is denied.
Next year, he writes a design document about a feature he just launched, taking great pains to exaggerate how complex it is. The "simplifications" of how it actually works go in the appendix.
He gets promoted.
#truestory
When I started training professional devs, I found I was among the onyl people doing advanced tech-agnostic software engineering training.
7 years and 4 days later, I still enjoy a near-monopoly.
300 students and counting have gone through Mirdin's training.
The coding tutorial space looks super crowded, but it is actually a barren wasteland after the basics of a programming language
everyone is making -> "Learn Python"
some -> "API Auth in Python" or "DBs + Python"
few -> "How to build a full project in Python"
These two lines carry deep software design wisdom
It lets me keep output and logs distinguished
Keeps the logging-centric code organized
But without creating a separate logging. py
Without figuring out an actual logging setup
I've saved the intention, but deferred the work
Every once in a while you learn something that makes you look back and think “That’s what I was doing wrong”
This book did that for me: When I Say No, I Feel Guilty
I’d been reliving so many times when someone said hurtful stuff or manipulated me
With this book: finally healed
A GHC plugin that turns types into Haskell code?
Automatically generating property-based tests?
Both easy-peasy, thanks to ECTAs, a new kind of constraint solver we invented.
Come hear me and
@tritlo
talk about our recent work with
@polikarn
and
@ZhengGuo069
.
To level up as a software engineer, practice regularly
Ask yourself: What have I done lately that's like playing scales?
Lots of ways to do so. Opportunities abound.
A new one from
@jeremyphoward
: when you see a function with lots of optional arguments, practice using each
If you're a software engineer, is studying theory a path to productive enlightenment, or a giant time sink?
Answer: Yes.
New blog post: Why Programmer's Should(n't) Learn Theory
With books like
@opticsbyexample
coming up, lots of people want to rework old code to use lenses.
Watching a headset designer writing a project proposal last night as she accidentally coined the term for this: refractoring.
fork() has to go down in history as one of those ideas, like the C switch statement, that seemed cool initially but turned out to be one of the worst ideas ever. It causes so many problems, I am astounded that in 2023 it is still the standard (and only?) thing on Linux.
It is my pleasure to announce that I am now a Scientific Advisor to
@KuraTechAR
. Kura is playing software design on hard mode, wanting to have software that will run decades from now on dozens of custom variants of their headset. I am honored to help them create the AR future.
People ask me about OO vs. functional programming. But that’s the wrong question.
C++ has lambdas.
Java has monads.
Python programmers use map instead of loops
FP already won.
We are all functional programmers now.
Wouldn't it be nice if debuggers presented information the way you think about it?
After 5 years, we finally have an intro JS debugger that renders closures as diagrams.
What will programming look like when your debugger looks like this for apps and distributed systems too?
"Man, these scoring rules are really complicated." "I wonder if it's NP-hard."
4 years later, we've proven it. Presenting my paper with
@YunWilliamYu
, "Skiing is Easy, Gymnastics is Hard: Complexity of Routine Construction in Olympic Sports", in FUN '22.
"Do you teach architecture?"
Bro, here''s what architecture can mean in SE
* Module-level patterns like Active Record
* Stuff between modules
* Stuff between whole systems
* What database you use
* Anything involving diagrams
* Anything "high level" whatsoever
So.....yes?
@hillelogram
I recommend for understanding the Prolog execution model. f(X, Y) has two different meanings depending on mode.
Also, Curry report:
I do research on multi-language tools.
C and OCaml? Child's play.
OCaml and Prolog? Terrifying.
Are you using spaced repetition for all your technical knowledge?
On a hike last month, I taught my cofounder 1/3 of a DB course
I studied this stuff 8 years ago, put it into Anki, and have scarcely looked at it since
Imagine if you could do that for everything you’ve learned
A Y2K programmer wishes to sleep through the chaos, and gets cryogenically frozen for a few months.
Alas, the vat isn't Y2K compliant, so he's not woken for 8000 years.
"Why now?"
"You see, the year 10,000 is just around the corner, and your resume says you know COBOL..."
TIL:
Some engineers will fight you if you say we should write a spec before doing the work.
But if you tell them that we should write down the properties we want our tests to check, they will agree instantly!
The world runs on software. Those who want to change the world should care about software being easy to change.
Latest news: changing genetics is easier than changing Excel.
h/t
@w_gottschalk
When “good advice” stops working
In 1747, Lind proved lemons cure scurvy
Then they replaced the lemons with limes. Scurvy came back
If you don’t understand why it works, one day it won’t
So much SE advice is like this. I call it “citrus advice”
We need to find the root cause
Small Haskell trick I just discovered:
Problem: I have a GADT, e.g. `Graph v e` whose contents I want to keep opaque, but it contains some instances on v and e I want to expose
Solution:
pattern GetInstances <- Graph _
E.g.:
myGraphOperation g
@Graph
.GetInstances = ...
"I've read it 5 times, and I still don't understand it"
I don't know who needs to hear this, but
Rereading doesn't work
It feels easier the second time because it's more familiar. Not because you understand it
Find another source, ask ChatGPT — do anything else instead.
I've been on a mission to rigorously define the major terms of software engineering. Abstraction was figured out in the 70's ( ). Daniel Jackson and I figured out dependence 2 years ago.
Now made accessible. New post!
A good software designer can write good code in any PL
I barely knew Typescript when I did this critique. But I knew that hardcoded list was bad, so I found a language feature that let me fix it
General principles made me a skilled language-wielder, not the other way around
Base on their analysis of the literature and their past teaching and research experience, the researchers proposed a theory that API knowledge consists of three factors:
Domain concepts, Execution Facts, and API usage patterns
@hillelogram
I think this is very true. FP and OOP are not real separate disciplines. FP is a style with lots of higher-order functions; OOP is some mix of a certain namespace-y syntax and using "recursive existential types" (aka "objects").
LP is a totally different execution model.
What's the scariest kind of software to work on?
For me, that might be MTG Online, or Dominion. Countless cards, each of which can change the rules and interact. Even a simple version stumps my best students
But I see PyDominion has reached full generality.
Java classes are a combination of:
* Namespaces
* Modules
* Objects
* Classes
* Object types
* Structures/products
* Sums
* Interfaces (abstract classes)
Did I miss any?
Each of these concepts has their own type theory, sometimes opposed to each other.
Every time I've heard someone give an example of why early abstraction is bad, my response has been "That's not abstraction." Abstraction is about information hiding, not finding patterns. Finding patterns is called "anti-unification."
And anti-unification is not abstraction.
Very disappointed by
@paulg
's Bel: 10 years after the mistakes of Arc, the new language still claims abstraction while lacking abstract datatypes . I speak as someone who once idolized PG and contributed to the Arc libraries. Excellent review by dfranke:
Refactoring challenge
#1
Starting off with a classic
It's checking the URL format twice. And it feels fragile; too easy to forget an isValid check.
Can you improve this?
“The architectural information typically does not exist in the codebase given our languages today” --
@simonbrown
Simon Brown echoing the insights I shared in , in the best talk I've seen in a long time:
Why is it that working with marketing feels frantic, and working with BigCo feels lumbering?
It's because of a mismatch in Buxton index, a differing time period over which decisions are made
Easily the most profound thing I've learned from
@swizec
Teller.
Check out this great summary of ALL(*) parsing at an MIT programming language lunch lecture by
@jimmykoppel
;
@samharwell
and I designed ALL(*) as part of ANTLR 4.
Video:
Paper: (w/Kathleen Fisher)
I just watched the incredible documentary "Antarctica: A Year on Ice" by
@Antzkiwi
. And then I realized:
Here are 12 ways maintaining a legacy software system is like wintering at an Antarctic base:
Today I watched my computer struggle with DNS limitations from 1983 while running on an ISA from the 70s. And so I think back to one of my all-time favorite SE quotes:
Software is like clay. Soft initially, but then it hardens. It needs to be like gold, malleable for life
This New Year, take some small steps to tidy your code
That's the theme of Kent Beck's "Tidy First"
It prescribes 16 "tidyings" you can do right now to clean up your code. I'll post one daily
The first:
Use early returns to flatten guard clauses
"Only one return" is so 1985
Micro software design lesson:
Found this in a README:
code --install-extension my-vscode-plugin-0.0.1.vsix
This is Hidden coupling.
With this, the README must be updated on every version bump:
Instead try
code --install-extension my-vscode-plugin-*.vsix
Fire and forget
Hyrum’s law:
With a sufficient number of users of an API,
it does not matter what you promise in the contract:
all observable behaviors of your system
will be depended on by somebody.
Solution: Destroy observable behaviors
The year is 2025. Programmers own chatbots like racehorses, carefully managing their training so they can bring in prizes. Resumes focus on the accomplishments of the chatbot.
That means:
It will finally be possible to have 10 years of experience in last month's framework.