dotGo 2015 - Rob Pike - Simplicity is Complicated
Summary
TLDRIn this talk, the speaker explores the success of the Go programming language, attributing it to its simplicity compared to other complex languages. They discuss the concept of language relativity and its impact on programming, emphasizing the importance of readability and maintainability over language features. The speaker highlights Go's design philosophy, which focuses on long-term maintenance and large-scale programming, and how it balances expressiveness with simplicity. They also touch on the complexities hidden behind Go's simple interface, such as garbage collection, goroutines, constants, interfaces, and packages, illustrating how these contribute to Go's ease of use and popularity.
Takeaways
- 😀 The speaker humorously translates 'Bonjour Madame de Monsieur' into 'Hello my waffles', setting a light-hearted tone for the discussion on the Go programming language.
- 🌟 Go's success is attributed to its simplicity, which contrasts with the complexity and feature bloat seen in other programming languages.
- 🔍 The speaker criticizes the trend of languages borrowing features from one another, leading to a convergence that could limit diverse problem-solving approaches.
- 🎯 Go's design philosophy prioritizes readability and maintainability over adding features for the sake of expressiveness or novelty.
- 🛠️ The language's creators, including Ken Thompson and Robert Griesemer, insisted on a consensus for including features, ensuring they were both necessary and appropriate.
- 🚫 Go deliberately avoids adding features that do not enhance the language's core goals, such as long-term maintenance and infrastructure software development.
- 💡 The speaker emphasizes that simplicity in programming languages is about hiding complexity behind a simple interface, making the language easy to use without sacrificing power.
- 🔗 Go's features like garbage collection, goroutines, and interfaces are examples of simplicity on the surface hiding complex implementations.
- 📦 Packages in Go are a model of simplicity, abstracting away the complexities of cross-compiling and linking while providing a straightforward import system.
- 🌐 The design of Go reflects a commitment to solving real-world problems at scale, particularly in the context of cloud and server infrastructure.
Q & A
What is the main reason behind Go's success according to the speaker?
-The speaker believes the main reason behind Go's success is its simplicity compared to other languages. This simplicity is not just a superficial feature but a core design principle that makes Go stand out.
What does the speaker think about the trend of languages adding features from other languages?
-The speaker is concerned that many languages are converging into a similar model by borrowing features from one another, which could lead to a homogenization of thought in programming and less interesting solutions.
What is the Sapir-Whorf hypothesis as mentioned in the script?
-The Sapir-Whorf hypothesis, also known as linguistic relativity, suggests that the language one speaks influences the way one thinks. The speaker uses this concept to argue that different programming languages should encourage different ways of thinking.
Why did the creators of Go decide to fix the language after Go 1?
-The creators of Go decided to fix the language after Go 1 to prevent it from becoming bloated and to maintain its simplicity. They believed that adding more features would not improve the language but would make it less distinct.
What was the guiding principle behind selecting features for Go?
-The guiding principle behind selecting features for Go was readability. The creators wanted a language that was easy to read and understand, which would lead to more reliable and maintainable code.
How does the speaker view the trade-off between language expressiveness and simplicity?
-The speaker believes there is a fundamental trade-off between making a language fun to write in and making it easier to work on and maintain. Go chose the latter, focusing on long-term maintainability and readability.
What does the speaker mean when he says 'simplicity is the art of hiding complexity'?
-The speaker means that while the surface-level features and usage of Go are simple, a lot of complex design, implementation, and refinement has gone into making it feel that way. The complexity is hidden from the user.
Why did the Go team decide against adding built-in map and filter functions?
-The Go team decided against adding built-in map and filter functions because they might be more computationally expensive than a simple for loop and could lead to less efficient code by encouraging their use.
How does the speaker describe the concurrency model in Go?
-The speaker describes the concurrency model in Go as one of the simplest available, using go routines, channels, and select to handle concurrency in a straightforward manner.
What is the speaker's view on constants in Go?
-The speaker views constants in Go as a favorite feature, appreciating how they are treated just like numbers despite the language being strictly typed, which simplifies code without sacrificing type safety.
Why did the design of Go's package system take a long time for the creators?
-Designing Go's package system was challenging because it interacts with various aspects like scoping, naming, information hiding, isolation, linking, compiling, and cross-compiling, making it a complex system to get right.
Outlines
🌐 The Simplicity of Go
The speaker begins by humorously translating 'Bonjour Madame de Monsieur' into 'hello my waffles' to illustrate the simplicity that makes Go successful. They argue that Go's success is not due to superficial factors like tooling or language features, but rather its simplicity compared to other languages. The speaker reflects on a Microsoft conference where they observed a trend of languages borrowing features from one another, leading to a convergence that could potentially limit diverse problem-solving approaches. They express concern about this trend, advocating for maintaining different languages to foster varied ways of thinking and problem-solving.
🔍 The Importance of Readability
The speaker emphasizes that Go's design philosophy prioritizes readability over feature richness. They argue that languages with too many features can complicate programming, as developers spend time considering which features to use and later must retrace their thought processes. This complexity hinders code understanding and maintenance. The speaker advocates for simplicity, suggesting that readable code equates to reliable code, facilitating easier comprehension, extension, and debugging. They contrast Go's approach with other languages that add features for expressiveness or fun, which can lead to less efficient solutions and more verbose code.
🛠 Balancing Expressiveness and Simplicity
The speaker discusses the challenge of balancing expressiveness with simplicity in language design. They use the example of APL, a language where programs are concise but hard to read, to illustrate the risks of prioritizing expressiveness over readability. The speaker suggests that features should be added judiciously to a language, ensuring they are orthogonal and do not introduce unnecessary complexity. They also touch on the idea that simplicity can be achieved by hiding complexity behind straightforward interfaces, as seen in Go's design.
🔄 The Complexity Behind Go's Features
The speaker delves into the complexity hidden behind Go's simple features, such as garbage collection, goroutines, constants, interfaces, and packages. They explain that while these features have simple interfaces for the programmer, their implementation is intricate and requires careful design. For instance, Go's garbage collection has no user interface but involves complex mechanisms. Similarly, goroutines, constants, interfaces, and packages are simple to use but involve complex rules and interactions. The speaker argues that this careful balancing of simplicity and complexity is what makes Go both powerful and easy to use.
🌟 Simplicity as a Design Goal
In the final paragraph, the speaker reiterates that simplicity is a complex goal to achieve in language design. They use the 'hello world' server example to show how Go enables writing concise, production-ready code that is also truly concurrent and efficient. The speaker concludes by emphasizing that while simplicity is hard to design and implement, it results in clarity and ease of use, which are central to Go's success. They express a preference for the simplicity and expressiveness of Go over more complex alternatives.
Mindmap
Keywords
💡Simplicity
💡Gofer
💡Language Relativity
💡Bloat
💡Readability
💡Concurrency
💡Garbage Collection
💡Constants
💡Interfaces
💡Packages
Highlights
Go language's success is attributed to its simplicity compared to other languages.
Simplicity is a complicated subject with many ways to think about it.
Many programming languages are becoming similar by adding features from one another.
Language relativity suggests that language influences thought, which is applicable to programming languages.
Having different programming languages allows for different ways of thinking and solving problems.
Go avoids feature bloat and strives for distinctiveness among programming languages.
Go's designers agreed on features that were not just additions, but the right ones to include.
Readability is the most important feature of a programming language, leading to reliability.
Go's simplicity is a result of careful design to hide complexity.
Garbage collection in Go has a simple interface but is extremely complex under the hood.
Concurrency in Go is one of the simplest models available, exemplified by goroutines.
Constants in Go are numbers, a simple idea with complex implications.
Interfaces in Go are simple sets of methods but have complex rules behind them.
Packages in Go seem simple but involve intricate design considerations.
Go's simplicity is not just about fewer features but about the right selection of features.
The design of Go focuses on long-term maintenance, especially in large-scale programming.
Go's simplicity is a result of months of design and refinement by its creators.
Go's ethos is represented by simple, expressive elements like the gopher image.
The success of Go is evidenced by its large community and adoption.
Transcripts
Bonjour Madame de Monsieur or assume a
gofer which if I translate I keep
laughing of course those who speak
French understand that the translation
of that is hello my waffles I just
learned that this weekend obviously go
is successful if you look at this room
look at what's going on here yeah and a
lot of people have asked why go is
successful or I've asked me why go is
successful and a lot of people have
answers that involve tooling or the
language or things about it but I think
those are all sort of superficial
reasons I think the real reason is
simplicity go is simple at least
compared to a lot of other languages
that are running around at the moment
and simplicity is actually a complicated
subject and there are many ways to think
about it last year about May I think I
went to a conference hosted by Microsoft
called line got mixed and I saw a number
of actually quite interesting talks many
of which were the leaders of a
particular language talking about a new
version that was coming out like
JavaScript PHP c-sharp and so on and I
really was struck by one thing about
these talks and these languages which is
most of the talks consisted of features
being added by taking something from
another language and adding it to this
one so you know Java scripts getting
classes and that kind of thing and I
realized that what's happening is all of
these languages are turning into the
same language there's a concept called
language relativity in linguistics which
is also colloquially called the
sapir-whorf hypothesis although neither
sup you're nor Worf quite agreed with it
and the idea is basically that language
influences thought and the sort of
cartoon version is you know if you speak
French you're you're more amorous and
it's pretty obviously controversial
there's some evidence that there may be
some truth but not very much but I think
it's really obvious if you think about
it that computer languages this very
much applies if you're in a logic
programming language you write a very
different kind of program you think a
different way
if you're using an object-oriented
programming language or concurrent one
it's very much like disciplines in
mathematics you don't solve calculus
using linear algebra even though they
have some structural comparisons and so
I'm worried about this trend in the
languages because they all converge to
the same language we're all going to be
thinking the same way and that would
make life very very uninteresting you
want to have different languages for
different problems you want to have
different domains we solve by different
ways of thinking and different notations
in other words you kind of want a tool
that's optimized for each particular way
you're working now these tosit line dot
next were about things like Java eight
equi script six which has been a long
time coming
c-sharp C+ was 14 and there few others
that didn't quite fit this mold but
let's just talk about the ones that do
as I said these languages are evolving
by adding features that means they're
becoming more complicated their
complexity is growing while they are
simultaneously becoming more similar to
one another that's a very strange
situation for a field to be in I would
summarize that is bloat without
distinction go however as I hope you
appreciate isn't like that goes a
different language in this respect it
doesn't try to be like these other
languages because it's not taking
features it doesn't try to compete by
saying oh if they have that feature we
better have it or people will be
unwilling to use their language in fact
as of goal 1 which is what three years
old now the language is fixed you know
you may have noticed that the features
that have gone in since then are
absolutely tiny there's really been no
significant change to the language since
since go one and that was the point of
go one however many newcomers to go
start by asking can we add this feature
of the language can we make error
handling different can we change the way
arrays work or something like that but
the language is fixed those things don't
get to go in but it's not just that the
language is fixed it's because adding
features will not really make go better
and why is that true it would just make
it bigger but it would make it less
different and both of those are worse in
my opinion but obviously you need
features you can't have a programming
language without some features in it but
which ones
well obviously the right ones and so we
picked the right ones how did we pick
the right ones well
one way is that the original language
was designed by Ken Thompson Robert
Greer and myself and we all have very
different backgrounds Ken and I had
worked together at Bell Labs quite a bit
but we also had done very different
things and you know Ken is the God so
when we came to talk about what was
going into the language we insisted that
all three of us not only agreed with the
feature going in but agreed that it was
the right feature to go in and with our
different backgrounds and our different
perspectives that dramatically narrowed
the number of things that went into go
but you still have to pick what to put
in and our overriding thing for doing
this was readability and here's how we
think about this if a language has too
many features or even more than you know
you might need you spend time
programming thinking about which
features to use if there's really a lot
of features you may look at the line of
code write it one way who I could do
something different I could use this
feature I use that feature you might
even spend you know half an hour playing
with a few lines of code to find all the
right ways you could use different
features to make the code work a certain
way and it's kind of a waste of time to
do that but worse when you come back to
the program later you have to recreate
that thought process you not only have
to understand this complicated program
programming language doing whatever it's
doing you have to understand why the
programmer who might be you decided that
this was the way to approach the problem
from the feature set available and that
is just I think bad engineering the
summary summarization of this is the
code is harder to understand simply
because it is using a more complex
language you want to have just one way
or at least fewer simpler easier to
understand ways so in other words
features add complexity we want
simplicity features hurt readability we
really want readability and readability
is by my opinion the most important
feature of a programming language
because readable means reliable if you
can read the code and know what it means
then you can it's easier to understand
it's easier to work on it's easier to
extend it's easier to fix when it breaks
it's easier to understand why it's
broken these are all good things
and that is why readability is so
important if the language is complicated
on the other hand you have to understand
more 2-under
stand even where to start working on the
program and you have to understand more
complicated model in which the program
is being written these cost time and
make the language harder to use but
there's a trade-off obviously making
more features in a language gives you
more fun things to play with and so
there's a fundamental trade-off ingo
that we've made in a different direction
from most other languages and the
trade-off is what do you want a language
is more fun to write in or easier to
work on and maintain and for the most
part the decisions in go about what went
in were about long term maintenance and
in particularly in the context of
large-scale programming although that's
a little off the topic today now the
thing is you put features in to make
languages expressive you obviously want
to not have to type you know hexadecimal
numbers which would be a very low
feature way to write code but obviously
very hard to use just be careful because
you make something too concise it can
become just unreadable this example here
is a real working program in a dialect
of APL called dialogue and an implements
Conway's Game of Life and I think you
could argue that even if you're an
expert APL programmer it's not very
readable APL is famous for being easy to
write and hard to read but and I think
it's very we have to be very careful we
don't write software like this in a
modern distributed multi programmer you
know open source world but there's a
more important point I think well maybe
maybe an equally important point which
is when you have features that add
expressiveness they typically add
expense for instance a lot of people
have asked for things like map and
filter to be built in to go and we said
no one of the reasons we've said no is
that if you if you have things like map
and filter they're going to use them
that's why they're there but they may be
more expensive than a simple for loop
and when the features are there to make
life easier and more expressive they
tend to generate more expensive in terms
of computer time solutions the problems
that have much simpler solutions so
they're also they may help the
programmer although not always but
they'll almost always hurt the computer
unless the implementation is extremely
smart and believe me the implementation
of APL is extremely smart so that
actually is a modestly efficient
implementation of the game of life but
you wouldn't you could do much much
better
if you wrote a simpler program but
you've got to be careful because if you
make everything too expansive explain
everything in detail you get a very
verbose language I won't name any but
you know the ones I'm thinking of where
it just seems like you're writing too
much to say a simple thing so you have
to balance this look so what we did was
we tried to make the right selection
building on the ideas that we're
familiar so that a programmer with a
background in procedural programming
like with C or Java or even you know
Fortran say could read a go program and
get a pretty good idea right out of the
box what was happening and not be
confused by strange notation so you have
to balance you have to be concise but be
expressive make sure that the program is
easy to read you have to pick the right
fit set of features in other words not
just features for features sake way I
like to think of this is to think of the
entire world of programming is a vector
space of very high dimension and what
you want to do is define the basis set
that covers that vector space so that
you can write the programs you want by
combining the appropriate orthogonal
because that's what basis it is
orthogonal set of features and what
happens when you add features for
expressiveness or for fun is it tends to
add more non basis vectors into that
space and so there become many paths to
get to a particular solution so that's
when we say features are orthogonal
that's what we mean we mean that they
cover this space but we also mean they
interact really well so if you take
feature a and feature B and you write a
program that uses them they work exactly
the way you expect feature a and feature
B to work they're not as some weird
diagonal that causes all kinds of
complications you have to worry about
again I won't mention which language I'm
thinking of so you have to keep all of
this in mind when you're designing a
language and also think about what the
goal is what are you actually trying to
achieve what is the problem domain that
this language being done for well in gos
case we were trying to write code for
Google because that's what we do andgo
is software that least the parts that we
work on are mostly infrastructure server
infrastructure what we now call cloud
software but used to just be called
servers and to do this you have to find
enough pieces to build the software and
so the fundamental components we started
with were ideas like concrete data types
you know integer
structures floating-point numbers
functions and methods interfaces
packages concurrency and then the sort
of guiding engineering principle of
having a really good fast implementation
with the abilities of really good
tooling and with that sort of all with
all those guidelines which is a fairly
complicated set of considerations the
pieces sort of fell into place and
actually ended up being kind of simple
in practice and in fact simplicity can
be expressive this is a very simple
drawing when Rene drew this a while back
and yeah he's expressive right
he's not really a gofer and I'm not
talking about the Magritte version of
Scecina buzzing gopher I mean he's just
the representation of a gopher very much
like like shreaves talked earlier with
the horse right and so this for me is
what is part of like the ethos of go
here's this really simple drawing that
represents what go is like we could put
more features on we make it more like a
gopher we could give them lots more
detail and we get something like this
right but mostly what we've added is
ugliness and hair we haven't actually
made embed it right its complexity
without clarity so but I want to make a
really important point here which is
I've said go is simple but it's not it's
very complicated I know I worked on it
it's one of those complicated things
they've ever worked on and yet it feels
simple and I think that's a really
important idea and it feels simple
because these pieces fit together
orthogonal and that requires a lot of
design a lot of thinking a lot of
refinement and implementation and
re-implementation and to put it very
bluntly simplicity at least in this
context is the art of hiding complexity
so let me talk about a few simple things
and go and why they're really
complicated garbage collection
goroutines constants interface and
packages each of these things is very
simple and very complicated but at the
same time there's a lot of other
subjects I could pick but let's quickly
go through these garbage collection is
probably the best example of simplicity
hiding complexity what is the programmer
interface for garbage collection
there isn't one can't get simpler than
that the empty set is as simple as it
gets right and yet look how hard it is
to implement all that incredible code to
do
with stack maps and you know the copying
the stacks on when you need to grow them
and tracking all the references down
pausing it running in parallel with thee
with the mutator it's a tremendously
complicated problem that fortunately I
didn't have to work on we have some
really good people in the NGO team who
did but I think it's amazing to consider
how much code is there for something
that has absolutely no user interface
there isn't even a free function in go
there's nothing but garbage collection
to manage memory and it's remarkable to
point out that it isn't even in the spec
the goal language does not define it is
garbage collected in the specification
the only mention is in the introduction
it was a throwaway property of a feature
of language that's how small and
therefore how simple the spec is I mean
the garbage collection is and you how
complicated it is behind the scenes and
it also makes code simpler because you
don't have to think about who owns the
data who's going to free it how to
manage it for you you can think about
implementation details and efficiency
but for just straightforward go
programming garbage collection hides
everything it's fantastic and one of the
things that people love about Go is the
concurrency I think it's arguably one of
the simplest concurrency models
available in a programming language not
that they're that many but there are
some others there's several components
to it go routines channels and select
and I'm going to talk about go routines
for a minute you start a go routine with
the go keyword you say go space geo
space and then the function call so
three keystrokes you can't make it much
shorter than that yeah I can imagine one
or two changes I can take but three
keystrokes and you just started a sub
process in the general mathematical term
and so it's like garbage collection
because it's extremely simple UI there's
nothing in the UI about the size of the
stack or a thread ID or managing
goroutines show them down things like
that there's there's no completion
status there's no type a lot of people
ask for these things that in fact some
other languages or thread packages
provide the equivalent functionality of
some of those things but we didn't put
them in we wanted to go key word to be
so simple that had the minimum possible
UI here's a function call run it
alongside my other
three keystrokes and that's part of this
minimal design and in crashes talk
earlier today he talked about one of the
reasons I think you can appreciate now
why for instance our no ID on a
goroutine internally of course you have
a lot of complexity managing this
managing the relationship between the
goroutine implementation the runtime
stack and the garbage collector for
example credibly complicated behind the
scenes stuff but three keystrokes
constants this is one of my favorite
things about go that most people don't
even think about and they don't think
about it because it's incredibly simple
when we decided that go ahead to be
strictly typed that meant that numeric
types could not be interchange freely
that was a very common source of bugs in
C and C++ you are not allowed and go to
takin it and put it into a float 64 or
anything like that but that can be very
clumsy you don't want have to say float
64 zero every time you want to use a
floating point zero so we had this idea
which is one of those I think relatively
novel ideas which is that we made
constant just be numbers they're just
numbers even though the language is
strictly typed and this means you get to
throw around things like 1e9 dividing
into a time dot second which has a
strict type and to get this to work was
really art is one of the hardest things
in designing language not in
implementing it so much but designing it
we had to worry about what infinite
presented in precision integers means
what infinite precision floating point
means what happens to the promotion
rules if you divide an integer two
versus divide a floating point 2 and you
get corner cases like this crazy shift
which I can't run but what do you think
the answer is to this what does this
program print it's got a 2.0 and a 2.0
shift is 0 and asking the type of both
of them you have to think don't you this
is a place where the complexity comes up
you get it you actually get a float 64
in an int and that's not a good thing
it's just a consequence of the rules
that we've ventually converged on to
make constants work quick but for the
most part you never see these kind of
works when you're using constants they
just feel like numbers and it's
fantastic so I'm not totally satisfied
but I think it was a really good example
again of simplicity hiding complexity
and I wrote a blog post
on blog Doug golang.org / Constance that
talks about this stuff in much more
detail interfaces one of those favorite
features for myself and I think for a
lot of programmers a very simple idea
all there is is a set of methods people
ask for data as well all the time not
going to get it it's just it's just
functions very simple you also need a
variable of type interface you can
program with these things but even here
you get some funny things happening
because you for instance can assign OS
dusted into a reader no problem
you can assign OS dusted into an empty
interface no problem but if you have to
narrow the interface you have to do a
dynamic type check which we call the
type assertion and one of the things
that's not well-known about go is that
was not in the original design we
realized a few months into it that we
needed type assertions to make the
program work right the addition of
effectively dynamic typing into a
statically programming language was a
complicated thing that we had to deal
with and make it work and it's I'm not
totally thrilled with how it worked out
but I think it's pretty good and it does
in the end do its job but for the most
part what you have again is a very
simple idea an interfaces a set of
methods and with it again are quite
complicated set of rules behind them
that mostly just do what you want but it
was hard in fact interfaces are probably
goes most distinctive and powerful
feature I think concurrency is talked
about a little more but you don't write
as much concurrency in a typical program
as you as you use interfaces interfaces
have a profound effect on the library
they've enabled the very structure of go
programs to be the way they are with it
I think the most component oriented
architecture of any programming language
I've used and so the in fact I think can
safely say they are simple to use even
though they add complexity they're worth
it
and finally packages packages are one of
the hardest things we had to deal with
and design the language it doesn't seem
like there's anything there what do you
have you have packaged big there's the
name of the package you have import
stringing the client what's there it
took us months to figure this out
because it interacts with things like
scoping naming information hiding
isolation linking compiling
cross-compiling and getting all those
details right took a very very long time
and but on the other hand you guys never
think about this stuff right they just
work somebody earlier today said import
was this favorite keyword that's great I
love it and all that complexity which is
fantastically intricate when you start
talking about working across multiple
language implementations of you know
four different architectures and
different operating systems it's all
hidden behind this simple package idea
that has basically two concepts and that
includes things like go get which is a
fantastic enabler for open source based
on the fact that the import string is
literally that a string with no semantic
meaning within the language so again
very hard to implement very complicate
under the covers extremely simple to use
and I think after garbage collection
packages are actually the most the best
example of simplicity hiding complexity
let me show you here's a simple example
it's just the sort of standard hello
world server it's written with some
Japanese in it because why not but you I
think and recognized as confident go
programmers very quickly what that
program does I don't need to run it it
does run it does what you think very
simple right there's hardly anything
there just a few lines of code starts a
server runs it okay here's what's going
on inside this program first of all most
visibly it's doing unicode utf-8 working
flawlessly it's supporting some magic
packages and they're being used from
flog net HTTP the HTTP being one of the
most awesome packages there's an F
printf directly to a network connection
which is interesting and unusual there's
a function being promoted method that
with the handle func in there which is a
bit of a mind blow to people new to go
was mind blow to me when it was pointed
out to me by Russ that we could do that
it's also truly concurrent the server
won't block as long as it enough
resources on the server hardware you can
have zillions of people talking to this
service simultaneously which is to say
it's production ready there it is a
production or any web server in just a
few lines of code it doesn't get much
simpler than that right so in summary
simplicity is complicated but the
clarity is worth the fight I don't want
to hang out with the gofer on the right
I want to hang out with the guy in the
left he's much more expressive and fun
and much less hairy
so in conclusion simplicity is very hard
to design it's very complicated to build
it sounds strange to say that but it's
true making things simple is hard work
but if you get it right you get
something that's very easy to use and I
think the success of go and the fact
that you're all here listening to me
proves that there's something there
thank you
浏览更多相关视频
5.0 / 5 (0 votes)