| Simplicity is Complicated |
| |
| dotGo |
| 9 Nov 2015 |
| |
| Rob Pike |
| Google |
| https://go.dev/ |
| |
| * Bonjour mes Gophers! |
| |
| .image simplicity-is-complicated/gophers.jpg 512 _ |
| |
| * Success |
| |
| What makes Go successful? |
| |
| Many reasons cited: |
| |
| - speed of compilation |
| - speed of execution |
| - deployment |
| - tools |
| - libraries |
| |
| These are not language features. |
| Less often cited: true language features such as interfaces or concurrency. |
| |
| All are important but not really an answer. |
| |
| * Simplicity |
| |
| My answer: Simplicity. |
| |
| Go is simple, at least compared to established languages. |
| |
| Simplicity has many facets. |
| |
| Simplicity is complicated. |
| |
| * Convergence |
| |
| [[http://channel9.msdn.com/Events/Lang-NEXT/Lang-NEXT-2014/From-Parallel-to-Concurrent?utm_content=bufferf1e11&utm_medium=social&utm_source=twitter.com&utm_campaign=buffer][Attended]] [[https://langnext2014.eventday.com/][Lang.Next]] conference last year (2014). |
| |
| Heard talks about new versions of Java, JavaScript (ECMAScript), Typescript, C#, C++, Hack (PHP), and more. |
| |
| These languages actively borrow features from one another. |
| |
| They are converging into a single huge language. |
| |
| * Language relativity |
| |
| _Sapir-Whorf_hypothesis_: Language influences thought. |
| |
| Controversial with regard to human languages. |
| |
| Close to a fact for computer languages. Consider: |
| |
| - logic programming |
| - procedural programming |
| - functional programming |
| - object-oriented programming |
| - concurrent programming |
| |
| Like disciplines in mathematics. |
| |
| * Convergence and relativity |
| |
| If the languages all converge, we will all think the same. |
| |
| But different ways of thinking are good. |
| |
| Need different languages for different problems. |
| |
| We don't want just one tool, we want a set of tools, each best at one task. |
| |
| * Convergence and features |
| |
| The talks at Lang.Next were about new language versions (Java 8, ECMAScript 6, C#, C++14) and were lists of features. |
| |
| These languages evolve and compete by adding features. |
| |
| The languages grow in complexity while becoming more similar. |
| |
| Bloat without distinction. |
| |
| * Features in Go |
| |
| Go is different. |
| |
| Go does not try to be like the other languages. |
| |
| Go does not compete on features. |
| |
| As of Go 1, the language is fixed. |
| |
| Many newcomers to Go ask for features from languages they know. |
| But those features do not belong in Go—and the language is fixed. |
| |
| Adding features to Go would not make it better, just bigger. |
| |
| That would make Go less interesting by being less different. |
| |
| * But you need features! |
| |
| Of course, there must be _some_ features. |
| |
| But which ones? The right ones! |
| |
| Design by consensus. |
| |
| * Readability |
| |
| If a language has too many features, you waste time choosing which ones to use. |
| Then implement, refine, possibly rethink and redo. |
| |
| Later, "Why does the code work this way?" |
| |
| _The_code_is_harder_to_understand_simply_because_it_is_using_a_more_complex_language._ |
| |
| Preferable to have just one way, or at least fewer, simpler ways. |
| |
| Features add complexity. We want simplicity. |
| |
| Features hurt readability. We want readability. |
| |
| Readability is paramount. |
| |
| * Readable means Reliable |
| |
| Readable code is reliable code. |
| |
| It's easier to understand. |
| |
| It's easier to work on. |
| |
| If it breaks, it's easier to fix. |
| |
| If the language is complicated: |
| |
| - You must understand more things to read and work on the code. |
| - You must understand more things to debug and fix it. |
| |
| A key tradeoff: More fun to write, or less work to maintain? |
| |
| * Expressiveness |
| |
| Features are often suggested to aid "expressiveness". |
| |
| Conciseness can be expressive but not always readable. |
| (Consider APL: ⊃ 1 ω ∨ . ∧ 3 4 = +/ +⌿ 1 0 ‾1 ∘.θ 1 - ‾1 Φ″ ⊂ ω) |
| |
| Can also be expensive, implementing simple ideas with too-powerful primitives. |
| Performance can also be unpredictable. |
| |
| On the other hand, verbosity can inhibit readability by obscuring the intent. |
| |
| Build on, but do not be limited by, familiar ideas. |
| |
| Be concise while remaining expressive. |
| |
| * The right set of features |
| |
| Not features for features' sake. |
| |
| Features that "cover the space", like a vector basis covering solution space. |
| |
| Orthogonal features that interact predictably. |
| |
| Simple features that interact in simple ways. |
| |
| Simplicity comes from orthogonality and predictability. |
| |
| Keep the language's goals in mind. |
| |
| * Go's goals |
| |
| Clean procedural language designed for scalable cloud software. |
| |
| Composable distinct elements, including: |
| |
| - concrete data types |
| - functions and methods |
| - interfaces |
| - packages |
| - concurrency |
| |
| Plus: Good tools, fast builds. |
| |
| All the pieces feel simple in practice. |
| |
| * Simple can be expressive |
| |
| .image simplicity-is-complicated/gopherslide2smblue.jpg 512 _ |
| |
| * Don't need all those features |
| |
| They add complexity without clarity. |
| |
| .image simplicity-is-complicated/gopherslide2sm.jpg 512 _ |
| |
| * Simplicity |
| |
| Go is actually complex, but it _feels_ simple. |
| |
| Interacting elements must mesh seamlessly, without surprises. |
| |
| Requires a lot of design, implementation work, refinement. |
| |
| Simplicity is the art of hiding complexity. |
| |
| * A few simple things in Go |
| |
| - garbage collection |
| - goroutines |
| - constants |
| - interfaces |
| - packages |
| |
| Each hides complexity behind a simple facade. |
| |
| * Garbage collection |
| |
| Perhaps the best example of simplicity hiding complexity. |
| |
| Very difficult to implement well, but worth it. |
| Yet so simple the language specification mentions it only in the introduction. |
| Nonetheless, parts of the language strongly influenced by it. |
| |
| Code is simpler because GC is there. |
| Design does not need to include "ownership". |
| |
| Go: there is no `free`. There is only garbage collection. |
| As simple as it can be. (But complex behind the facade.) |
| |
| * Concurrency |
| |
| Concurrency is the ability to write your program as independently executing pieces. |
| In Go, concurrency has three elements: |
| |
| - goroutines (execution) |
| - channels (communication) |
| - `select` (coordination) |
| |
| Let's talk about goroutines. |
| |
| * Goroutines |
| |
| Start a goroutine with the `go` keyword: |
| |
| go function(args) |
| |
| Three extra keystrokes ('g', 'o', ' '). Hard to be much simpler. |
| |
| Like garbage collection, eliminate considerations from the programmer's concern: |
| |
| - no stack size |
| - no return or completion status |
| - no mechanism for management |
| - no "ID" |
| |
| These are things other systems would provide. Go instead has a minimalist design. |
| |
| Implementation complex, dependent on garbage collection for stack management. |
| |
| * Constants |
| |
| In Go, constants are just numbers, even though (because) it is strongly typed. |
| |
| var nanosecond = time.Second/1e9 |
| |
| Simple idea took about a year to work out. Difficulties: |
| |
| - "infinite" precision integers |
| - "infinite" precision floating point (tried and failed with rationals) |
| - promotion rules (`i` `:=` `2;` `f` `:=` `2.0;` `g` `:=` `1/2;` `h` `:=` `1/2.0`) |
| - corner cases like shift |
| |
| .play simplicity-is-complicated/shift.go /Printf/ |
| |
| Still not totally satisfied, but the effect is that constants feel like numbers, contribute to the ease of using Go. But complicated behind the scenes. |
| |
| More at [[/blog/constants][this blog post]]. |
| |
| * Interfaces |
| |
| Just a set of methods. No data. Simple idea, but more complex than expected. |
| |
| type Reader interface { |
| Read([]byte) (int, error) |
| } |
| |
| Also need variables of that type (`var` `reader` `io.Reader`). |
| These variables add dynamic typing to a statically typed language. |
| |
| var r Reader = os.Stdin // Statically checked. |
| var x interface{} = os.Stdin // Statically checked. |
| r = x.(Reader) // Dynamically checked. Must be explicit here - design decision. |
| |
| Requires careful design. Interface assignment must be implemented at run time (not a v-table). What if it fails? Led to type assertions and the "comma, ok" idiom. |
| |
| More complexity crept in. Type assertions and type switches were not in the original plan. |
| |
| * Interfaces |
| |
| Go's most distinctive and powerful feature. |
| |
| Profound effect on library design. |
| |
| Enables true component architectures. Prime examples are `io.Reader` and `io.Writer`, generalizations of the Unix pipe idea. |
| |
| Feel simple, worth the complexity. |
| |
| * Packages |
| |
| A design for structuring programs and libraries. |
| |
| package big |
| ... |
| import "math/big" |
| |
| Took a long time to design. Enable componentization, scalability, sharing, data hiding and isolation, ... |
| |
| Affect program design, syntax, naming, building, linking, testing, ... |
| |
| Separation of package path (`"math/big"`) from package name (`big`). |
| Enabled the `go` `get` mechanism. |
| |
| Intricate to implement yet natural to use. |
| |
| After garbage collection, perhaps the highest ratio of true complexity to apparent simplicity, and therefore of the power of simplicity to hide complexity. |
| |
| * A "simple" example |
| |
| .play simplicity-is-complicated/hello.go |
| |
| * Hidden complexity |
| |
| Unicode and UTF-8 handled seamlessly. |
| |
| Packages imported and used easily. |
| |
| `Fprintf` direct to network connection. |
| |
| Function promoted to method (`HandleFunc`). |
| |
| Truly concurrent—server won't block. |
| |
| Production ready. |
| |
| All very simple. |
| |
| * Summary |
| |
| Simplicity is complicated but the clarity is worth the fight. |
| |
| .image simplicity-is-complicated/gopherslide2sm.jpg 512 _ |
| |
| * Conclusion |
| |
| Simplicity is hard—to design. |
| |
| Simplicity is complicated—to build. |
| |
| But if you get it right... |
| |
| Simplicity is easy—to use. |
| |
| The success of Go proves it. |
| |
| .image simplicity-is-complicated/gopherslide2smblue.jpg 256 _ |