“Simple Made Easy” - Rich Hickey (2011)
- Simple vs. easy: simple means is not complex or entangled. Easy means
familiar or near to our understanding.
- Construct vs. Artifact: construct is the codebase. Artifact is what we deliver
- We can make software simple by choosing constructs with simpler artifacts and
avoiding constructs that have complex artifacts.
- Human limits: we can only keep a few things in our mind at a time
- The Complexity vs. Simplicity part was to abstract and doesn’t have code
examples
- one fold/braid: one role, one task, one concept
- but not: one instance, one operation
- about lack of interleaving, not cardinality
- objective
- Near(by), at hand: on our hard drive, in our tool set, IDE, apt get, gem
install, etc.
- Near to our understanding/skill set: familiar
- Near to our capabilities
- Easy is relative, unlike simple
- Construct is the codebase
- Artifact is what we deliver
- We focus on experience of use of construct (programmer convenience and
replaceability) rather than the long term results of use (software quality,
correctness, maintenance, change)
- We must assess contructs by their artifacts
If you want everything to be familiar, you will never learn anything new,
because it can’t be significantly different from what you already know.
- Changes to software require analysis and decisions; What will be impacted?
Where do changes need to be made?
- Debugging: all bugs pass the type checker and all the tests. All guard rails
will fail
- Development Speed: emphasizing ease gives early speed, but ignoring
complexity will slow you down over the long haul
- Software can be easy, but complex. Many complicating constructs are:
succinctly described; familiar; available; easy to use.
- Benefits of Simplicity: ease understanding, changing, debugging, flexibility
- State is easy (in the at-hand and familiar senses), but it is never simple.
- There is the environmental complexity: shared resources, e.g. memory, CPU,
etc. It’s inherent (not your fault).
- Simplicity is a Choice: requires vigilance, sensibilities and care
- Information is Simple. Don’t ruin it by hiding it behind micro-language (i.e.
a class with information-specific methods). Represent data as data, no nned
to write a class for every new data.
| Complexity | Simplicity |
|---|
| State, Objects | Values |
| Methods | Functions, Namespaces |
| vars | Managed refs |
| Inheritance, switch, matching | Polymorphism a la carte |
| Syntax | Data |
| Imperative loops, fold | Set funcitons |
| Actors | Queues |
| ORM | Declarative data manipulation |
| Conditionals | Rules |
| Inconsistency | Consistency |
| Construct | Complects |
|---|
| State | Everything that touches it |
| Objects | State, identity, value |
| Methods | Function and state, namespaces |
| Syntax | Meaning, order |
| Inheritance | Types |
| Switch/matching | Multiple who/what pairs |
| var(iable)s | Value, time |
| Imperative loops, fold | what/how |
| Actors | what/who |
| ORM | OMG |
| Conditionals | Why, rest of program |
| Construct | Get it via… |
|---|
| Values | final, persistent collections |
| Functions | a.k.a. stateless methods |
| Namespaces | language support |
| Data | Maps, arrays, sets, XML, JSON, etc. |
| Polymorphism a la carte | (Clojure) Protocols, (Haskell) type classes |
| Managed refs | Clojure/Haskell refs |
| Set functions | Libraries |
| Queues | Libraries |
| Declarative data manipulation | SQL/LINQ/Datalog |
| Rules | Libraries, Prolog |
| Consistency | Transactions, Rules |
- vs Abstraction as complexity hiding
- I don’t know, I don’t want to know
- Who, What, When, Where, Why and How
- Choose simple constructs over complexity-generating constructs
- It’s the artifacts, not the authoring
- Create abstractions with simplicity as a basis
- Simplify the problem space before you start
- Simplify often means making more things not fewer