Cheng Lou, a former member of the React team, gave an incredible talk at React Europe 2016 entitled "On the Spectrum of Abstraction". That talk is available for viewing here: https://www.youtube.com/watch?v=mVVNJKv9esE
It's only a half-hour, but it is mind-blowing. It's worth re-watching two or three times, to let the ideas sink in.
I just rewatched the talk for some research, and wrote down a summary that's semi-transcript-ish. I didn't see any other transcripts for this talk, other than the auto-generated closed captions, so I wanted to share for reference.
Side anecdote:
-
subclass vs superclass: trick question! Are you counting "methods" or "instances"? Superclass has more instances, so "superset"
-
Need to make sure on the same page, same set of assumptions
-
Tree of abstractions
- Top level/root: abstract, more "power"
- Leaf nodes: concrete use cases, more immediately "useful"
-
Terms:
- "Power": no emotional attachment; "the ability to drill down the level of abstraction and get to a concrete use case". Tools.
- "Utility/useful": other end of spectrum, "don't need to understand abstractions to make it work". Products.
- "Cost" to go up or down a level of abstraction
- "Principle of Least Power / Pareto Principle": use least powerful tools to achieve goals, because less mental overhead
-
Libraries vs Frameworks: specialization of this idea. Libraries are lower in the tree ("more useful"), frameworks are higher ("more powerful"). Frameworks cover more use cases, shared knowledge.
-
Micro-modules: red circles around green "concrete" nodes. No need to understand how they work. Not "bad", just a representation.
-
Cheng Lou: "Lots of problems arise from a bad understanding of where we should be in the levels of abstraction".
- Typing is easy. Wrong abstractions have a cost.
-
Consequences
- Too concrete: don't cover all the green use cases
- Too abstract: too much mental overhead to understand, lose interest
- Use intuition to determine
- More abstract: lose "situational-specific properties"
- "Properties": "the things we want to maximize"; the specific unique useful features.
- Turning everything into a string would many things a lot harder. "Undistringuishable". Being able to tell apart functions, if statements, etc, has usefulness.
-
Redux limits expressivity: "no mutability". Immutability is a lower abstraction. We gain time traveling as a result (much easier to implement). Mutability lets us do more, so it's higher in the tree.
-
Cheng Lou: "We're often not seeking for more power. We're seeking for more principled ways to use our existing power."
- If we wanted more power, we could have stopped at
goto
and0s and 1s
. - By reducing expressivity, we gain more power.
- What about a "mapper" instead of a "reducer"? Would give possibilities for parallelization.
- Not always about "what possible things I can do", it's about "what can I do now without further abstraction"
- If we wanted more power, we could have stopped at
-
Case studies
- Grunt vs Gulp
- Gulp winning. Maybe because "idiomatic Node", but more because "declarative DSLs work best with defined use cases".
- Build systems not defined the same way as a state machine
- Role of a build system: "include everything I don't know where to put"
- Since req'ts keep changing, do you want simple declarations, or higher abstraction of functions that can be modified?
- Declarative DSLs lack expressivity
- React vs Templates
- FAQ: "Are you actually putting HTML in my JS?" Want to resolve this question once and for all.
- Templates are data.
- React team says data is lower in abstraction, but JS apps need more power than templates provide. This is a concession that we need more abstraction for this use case.
- Ember gets nice perf from templates being optimizable
- React loses some raw perf, but can regain some from other higher optimizations
- Diffing on Views vs Diffing on (Model + Computation)
- React is diffing on views. Here, they chose to use data for better perf. Data can be produced, compared, discarded, which you can't do with functions.
- Other frameworks diff on the model, and additional work can't be easily compared.
- Immutability vs Mutability
- Most devs don't get why immutability is better. "Mutability lets me do more, why choose something that's less powerful?".
- Not about potential power of doing more - it's about exploiting properties you gain by doing less. Immutability constraints give things like time traveling, from "doing less"
- JS (Inline) CSS vs Traditional CSS
- One good argument against JS+CSS: power of a full language is way too much, lose too many properties.
- CSS is less powerful and expressive. Try to do things with CSS, as easier to reason about (because fewer abstractions). Theoretically easier to analyze CSS. Harder to analyze properties with a full language.
- Preprocessors show CSS is the wrong level of expressivity - need actual functions (so why not full power of JS?). Not just "familiar language", it's about levels of abstraction.
- Grunt vs Gulp
-
Concrete Experiences
- Don't Cover Every Use-case
- Easy perf gained by doing less work
- Clear justification for not covering every use case: higher abstraction means less optimization
- React loses some optimizations becaues of API surface overall, but small API surface gives some room for optimizations
- Don't over-constrain TOO much. Techs that take off are averagely powerful. Not all-powerful, not all-constraining.
- Not DRY (ie, repeating code) is... Fine
- It's okay to copy-paste code.
- Controversial (engineers don't want to do something twice), but cost of abstracting away is higher cost than just one use case. More mental overhead to understand abstractions. Use judgment.
- Related to JS micro-modules: paying more cost to abstract things than to use them.
- Don't Be Swayed By Elegance
- Overloaded term: means "things that are way too powerful", like monads and macros. With one thing, can tame many concepts. But, "single unifying principle" is too powerful to be popular and not as usable.
- Making a lib or writing an app: be aware of level of abstraction for the end user.
- When in Doubt, Use Examples
- Examples are leaf nodes on tree of abstraction. Examples are copy-pastable templates showing concrete use cases - use now, understand later.
- When lacking ideas of how to express a lib correctly, write examples, write docs.
- Don't Cover Every Use-case
-
Conclusion
- This talk itself is high up on the level of abstraction. "By definition, probably the most useless talk of this conference." But, definition is consistent.
- By definition, also a very powerful talk. Drilling down levels can help apply concept to concrete use cases. If you don't apply, and only think in theory, you won't have much use for the talk at all.
- Think in these terms next time you write a lib or app.