"Simple Made Easy" - Rich Hickey (2011)

ClojureTV9 HN recommenders · 2021–2026
434K views · talk · evergreen · Uploaded 2021-09-02

Rich Hickey's Strange Loop 2011 keynote separates 'simple' (not intertwined) from 'easy' (familiar or near at hand) and argues that software complexity comes from complecting things. It offers a vocabulary for judging designs and abstractions.

It is one of HN's most frequently recommended programming talks, cited whenever people debate complexity, simplicity and abstraction, and valued well beyond Clojure.

Watch on YouTube

17 comments from Hacker News

@elamje2021 · in “Ask HN: Programming talks that made something click for you?”

Simple Made Easy ( [VIDEO] ) The Language of the System ( [LINK] ) The Value of Values ( [LINK] ) All by Rich Hickey (Clojure creator) - strongest programming speaker I've found to date.

Strongly recommendsView on HN
@tacotacotaco2021 · in “Etsy’s Journey to TypeScript”

No, my argument is that TS makes writing code easier and that easier does not equal to quality [0]. I have been writing code for more than 20 years. Personally, TS doesn't impress me. This is not meant as a criticism. Personally, I have found functional programming to be revelatory. I am shocked that is as been around as long as it has and that our schools don't teach it (or just mention it) and the majority of people in our industry as resistant to it. "No matter what language you work in, programming in a functional style provides benefits. You should do it whenever it is convenient, and you should think hard about the decision when it isn’t convenient." -- John Carmack [1] [0] "Simple Made Easy" Rich Hickey [VIDEO] [1] "John Carmack on Functional Programming in C++" [LINK]

@zackmorris2021 · in “Overengineering can kill a product”

Engineering within the wrong paradigm can kill your product. I see far more problems on a day-to-day basis with patterns and anti-patterns taken too far. For example, I never use the factory pattern, because it leads one down the Java road where everything ends up an object with mutable state. Which isn't scalable over some metric (like a million lines of code) because a human brain can't trace execution, even with a debugger. A far better pattern generally is to take a functional approach of accepting data, swizzling it, and returning the resulting data without mutability or side effects. Another really bad pattern is when execution suspends and resumes somewhere else (goto hell). Any project which uses queuing, eventual consistency, promises, nonblocking streams, even basic notifications or things as complex as monads will encounter this nondeterminism and inability to statically analyze code. Note that pretty much all web development suffers from some aspect of this due to its async and multi-signaling nature. So what I do now, which I don't see much these days, is solve problems abstractly in a spreadsheet (pure functional programming), in the shell (the Actor model) or as a flowchart (declarative and data-driven design), and then translate that to whatever crappy language/framework I have to use for the project. I find that today, roughly 90% of developer effort goes to discovery, refactoring and testing of ill-conceived code. Only 10% is "actual work" and that's probabl

@zackmorris2021 · in “Features of a dream programming language”

Oh I'm looking at the development side, being able to iterate quickly and having full visibility of the code. This fits in with stuff like aspect-oriented-programming (AOP) so that things like execution traces can be generated at runtime without modifying code. I mostly work with the shell and scripting languages. I'm racing as fast as I can all day to get anything at all to work, then building on that to get to a solution. Most of the time, I can't really edit the code I'm working with and still maintain velocity, so can't do any kind of manual type annotation. Also I question if there is really any merit to hiding the type of a variable at runtime. It feels like a power trip by the language, a form of security theater. I also view the "private" and "final" keywords with similar skepticism. If I can call typeof on an element in my own struct/class, then I get frustrated when I can't do that with anonymous data from a framework or in the REPL. It also frustrates me when I can't access the call stack or get information about the calling function. If there's a way to do it in C++ (no matter how ugly), then I must be able to do it in whatever language I'm using or my psyche views it as stifling and I lose motivation. I guess I find the obsession with types today to be a form of pedantry. So much concern for only accepting a narrow range of shapes, but then holding that info close to the chest. It should be the opposite. That's also the reason why I've gotten away from object-ori

@almostdeadguy2022 · in “Minimalism in programming language design”

This conversation almost always strikes me as a pointless exercise. We can't even agree on what it means to be "simple" or precisely define what it means to have "less features" in a programming language (or perhaps we can by saying complexity is anything more than what is provided by machine language, but we get no closer to an understanding of how much of this is necessary or when this is desirable). A programming language is an abstraction over machines and inevitably all languages introduce features to unburden the programmer from extraneous detail, toil, or precarity involved in orchestrating the operation of that machine. The author is correct that many "simple" languages like Brainfuck are actually very complex to use, but this strikes at the inherent feebleness of the premise that we can clearly define what we mean by a "simple" language (or at least any clarity on when the complexity tax is worthwhile or not worthwhile). Many programming language features are conditioned on a trade-off that having to think about X less in exchange for requiring knowledge of Y is a net benefit to the programmer. If we take the idea that simplicity means "less features" at face value, we throw out the notion of any high level language having the potential to be simple. The oft-cited Rich Hickey talk [0] I think gets _somewhat_ closer to vindicating the concept of simplicity being something we can talk about more objectively, but I'm still not convinced the concept is worth redeeming. I

@dgb232022 · in “Why does this code execute more slowly after strength-reducing multiplications?”

If we ignore the details, then this is a perfect example of how simpler code should be preferred _by default_ over complex code. Both for performance and reasoning. In this case and often elsewhere, these are related things. I'm taking the definition of simple and complex (or complected) from this talk[0]. In short: Simple means individual pieces are standing on their own, not necessarily easy or minimal. Complex means individual pieces are braided together into a whole. The first code is simpler than the second. Just have a look at the two solutions and you see what I mean: The individual instructions in the first stand on their own and clearly declare what they mean as well. The second example is more complex, because each line/subexpression cannot be understood in isolation, there is an implicit coupling that requires the programmer _and_ the machine code interpreter to understand the whole thing for it to make sense. The CPU apparently fails at that and cannot optimize the machine instructions into more efficient microcode. The example illustrates performance benefits of simpler code, but there are others too: For example a type checker might be able to infer things from simpler code, but not from complex code. Again, complexity is about coupling, which can for example arise from making assumptions about things that are out of bounds or logic that happens in some other part of your program, which _this_ part relies on. Things like these can either be outright rejected by

@loudmax2022 · in “The collapse of complex software”

I highly recommend Rich Hickey's "Simple Made Easy" talk as a way to think about software complexity. We all know that complex systems are hard to work with, but I've found his presentation very useful in understanding the nature of complexity. Understanding complexity helps being able to avoid or minimize it. For example, easy is not the same as simple, and simple changes to one part of a system can introduce great complexity at the macro level. [VIDEO]

Strongly recommendsView on HN
@frogulis2022 · in “Revisiting the principles of data-oriented programming”

Rich Hickey's talks "Simple Made Easy" [1] and "Effective Programs" [2] provide a better explanation of these ideas IMO. The specific definition of "simple" is pretty crucial. [1] [VIDEO] [2] [LINK]

RecommendsView on HN
@zackmorris2022 · in “Show HN: Async UI: A Rust UI Library Where Everything is a Future”

I second this, as personally I believe that async is an anti-pattern. It's an unfortunate result of the programming world choosing easy over simple so it could recruit vast armies of inexperienced programmers for profit: "Simple Made Easy" by Rich Hickey: [VIDEO] I'm old school, I want the runtime to do as much work for me as possible so I don't have to. Basically that looks like the runtime providing things like process isolation and concurrency, even if the underlying hardware can't do that. Especially if we're using a high-level scripting language like Javascript anyway. Rust I could maybe see at least providing access to async functionality, but I'd vote specifically against that footgun and go with lightweight threads and message passing (how Go does it) or scatter-gather arrays (there may be a better term for this) with the compiler detecting side effects and auto-parallizing everything else like loops. The simplest way to facilitate that is to use immutable data as much as possible, passed via copy-on-write (the Unix way). The idea of async being scattered around operating systems and kernels and such is anathema to my psyche. Code smells setting off my spidey sense everywhere I look. To the point where if the world goes that route, I just don't think we'll have determinism anymore. That makes me want to get out of programming. Note that I feel the same dismay about stuff like the DSP approach used by video cards, where the developer has to manually manage vertex buffe

@xiphias22023 · in “Do the Simplest Thing That Can Possibly Work (2004)”

Actually Rick Hickey's talk ( [VIDEO] ) is amazing because he talks about your case by going back to the original meaining of words: ,,Complex comes from the Latin complecti, which means “to entwine around, to embrace'' Simplicity requires layering, so in your examples the main requirement for simplicity is about how intertwined your hobby project is with the transciever code or ethernet code. As long as the abstraction layer works well for you without getting too much into the details of the implementation, it's a simple solution. Of course it's not a clear answer whether you should do things yourself or use a third-party, but if the third-party works perfectly for use case without significant tradeoff in your system, of course it's better to use it.

Strongly recommendsView on HN
@Pet_Ant2023 · in “No One Wants Simplicity”

I believe GP is using it in the literal etymologically correct way in the vein of Rich Hickey: [VIDEO] Pedantically, Common Lisp being a Lisp-2 vs a Lisp-1 arguably makes it a duplex vs a simplex…

@liveoneggs2023 · in “Can't Be Fucked: Underrated Cause of Tech Debt”

take it up with Rich Hickey I suppose :) If you've never watched Simple Made Easy I really recommend it: [VIDEO]

RecommendsView on HN
@funcDropShadow2023 · in “Push ifs up and fors down”

This doesn't sound like a simple solution from your fellow devs. It appears to have been an easy solution. If the distinction isn't familiar to you, there is a great talk of Rich Hickey [0], that explains that distinction and some more. The talk is definitely not only applicable to Clojure. YAGNI is a great slogan, but must not be a dogma. If you already know, that you are going to need custom rules. Then prepare for it. But, if --- for example --- the current rules are almost trivial, and you don't know yet, which rule engine will be the right fit later on. Then it might be a good idea to postpone the decision about the rule engine, until you know more. In the meantime a hard-coded solution could be enough. [0]: [VIDEO]

Strongly recommendsView on HN
@gavinhoward2024 · in “Rewriting Rust: A Response”

> I'm sadly not very well versed with this alternative to OOP. But something tells me that a more "basic" and less dynamic scheme like that is probably best for performance reasons, since you'd either need a Julia-like JIT or a granular "dynamism knob" like [LINK] to truly amortize the cost of CLOS-like dispatch and polymorphism; though magic can be done, as the "Fast generic dispatch for Common Lisp" paper shows. You know, for someone who isn't "well versed" with it, you certainly nailed exactly why I chose it. Also, simplicity. The "as easy as Python" is only possible if I remove complecting [1] things like inheritance. > Huh! If this includes types deduced by compiler inference and not just user declarations (since Yao seems gradually typed, to my eyes), that'd be pretty impressive. It does, actually. But Yao is not gradually typed, unfortunately. Too complecting. [1]: [VIDEO]

@yooogurt2025 · in “Rich Hickey: Thanks AI”

If you haven't heard of Rich Hickey, then you're fortunate to have the opportunity to watch "Simple Made Easy" for the first time: [VIDEO]

Strongly recommendsView on HN
@delaminator2026 · in “Ask HN: In the Age of AI, How Do I Grow as a Software Engineer?”

> Claude can make decisions about architecture but they are often not very good decisions, and sometimes absolutely terrible I have to kick it back onto the right track, but as you sort of point out, I got that experience from making my own terrible decisions and finding out the hard way the blind alley I was walking up. Second system, inner platform, too general, planning for scenarios that never happen, stuff that doesn't scale - I've made them all. I think I learned as much from reading as doing though, I could later put names on the mistakes I made. So, for what it's worth - study the meta. Read about architectural theory, system design Study the craft and listen to the masters - [VIDEO] And when you talk to Claude say "follow rich hickeys advice about explicit rules" and it knows what you mean more than you do !

RecommendsView on HN
@ale2026 · in “My Thoughts on Bun's Rust Rewrite”

Great point about testing. The knee jerk reaction to defend this enormous rewrite because it passes a test suite reminds me of a Rick Hickey classic: what’s true of every bug found in the field? It passed all the tests. [VIDEO]

RecommendsView on HN