GopherCon 2019 - The Gopher's manual of style
Beyang Liu for the GopherCon 2019 Liveblog
Presenter: Kris Brandow
Liveblogger: Beyang Liu
Our industry has borrowed ideas and practices from a range of industries to improve the design and production of software. In this talk, we'll look to the publishing industry for ways to improve software development for our industry and within the Go community.
Kris Brandow is senior engineer at MongoDB. He works on the MongoDB Go driver and has been writing Go full-time for nearly 6 years. In addition to programming he also loves to bake and to write.
What is this talk about?
In programming, we borrow concepts from a lot of other organizations:
- The role of a software architect borrows from architecture (obviously)
- Agile software development is inspired by lean and agile manufacturing
We can also borrow from the publishing industry. Kris's degree is not in computer science, but creative writing and one of the things that first drew him to programming was the parallel between the two. Programming is a form of creative writing.
Writing is highly structured:
- You don't just stream-of-consciousness it. You write treatments and character bios before the story. This is similar to the design docs and product specs you create before writing code.
- The creation of the story is also structured. In screenwriting, there's the "8 sequences" framework. Every movie you've ever seen follows this. (If you know about it, it kind of ruins movies...)
- 3 act plays are another common structural pattern
- Writing is a very iterative process, just like programming.
Programming is to creative writing as software engineering is to publishing. So let's pull concepts and ideas from publishing to help us improve the craft of software engineering.
Publishing is has a wide variety of things:
Similarly, in programming, you have libraries, databases, various types of application. These are all very different but all of them go through the same high-level publishing process.
We can borrow 2 things primarily from the publishing industry:
- Editors (as in "newspaper editor", not as in "vim")
- Manuals of style
- Opinionated and idiomatic
- No comprehensive manual of style
- Codebases are consistent via gofmt, but not much else is
- Go is growing and changing
Publishing has things like the Chicago Manual of Style to enforce consistency and shared standards. Go has strong idioms, but no standard manual of style akin to the scope of the Chicago Manual of Style. Go's culture and values share a lot with that in the publishing industry, but they've been doing their thing a lot longer than we've been doing ours. So let's learn from them.
What can we borrow from the publishing industry?
These are the roles of an editor in publishing:
|Acquisition editor||Prototype engineer|
|Developmental editor||Software architect|
|Copy editor||Code reviewer|
|Production editor||Operations engineer|
- The acquisition editor acquires ideas. Oftentimes, the acquisition editor also handles the developmental, line editing, and copy editing.
- The developmental editor is involved in the development of the idea into a work of writing (e.g., story development, character development).
- The line editor goes line-by-line and checks for grammar, consistency, and factual correctness.
- The copy editor is the final typesetting and preparation for publication. Any last-minute proofreading and spell-checking.
- The production editor handles any changes that need to be made in the production process.
- The prototype engineer builds the initial prototype
- The software architect handles higher-level architecture
- There's no strong comp for the line editor in engineering. More on that later.
- Code reviewers do the final review of the code for style and correctness before it gets pushed. You might think Code reviewing is like line editor, but it's not because it happens toward the end of the process.
- The operations engineer handles things once they're in production.
Borrowing from publishing for code reviews:
- The conventional wisdom for code reviews is that they should be kept small.
- This has always struck Kris as very constricting and dogmatic.
- You don't write a good book as 200-500 work chunks. You can certainly do it for periods of time, but you may want to write bigger chunks, and every now and then you want to do a higher-level review to check for overall plot arc and consistency.
- We're missing a tool in software to do a high-level expansive review of software.
- We should avoid dogma when it comes to code reviews. Kris has a coworker who actually prefers doing gigantic code reviews to small one. Different people work differently.
Borrowing for codebase structure and maintenance:
- Manuscripts require more than proofreading and copyeidting. You need to do higher-level structural reviews of the writing.
- We could do structural reviews of a codebase for things like dependency structure and hierarchical structures in code. For example, when should you split a package in two?
- However, continuous delivery in software is different from publishing a book. But it still makes sense to do periodic high-level reviews, even though there isn't a single shipping date that provides a natural focal point to do so.
- Testing is a particularly difficult problem. Testing styles and philosophies evolve with the codebase and team writing the code. New tests are added, but existing ones are rarely updated to be consistent with the new best practices. Then at some point you need to build a new a feature and you have to update a bunch of tests written under very different styles. In some cases, you might just burn down a lot of tests and rewrite them from scratch, and that's not good. Kris has come to view tests like a book's bibliography. You don't expect most readers to go through your bibliography, but it needs to exist to lend legitimacy to the work. If we view tests as the source of legitimacy for the code, it makes it much more important to maintain it in a consistent state. Bibliographies are stylistically consistent. If you change the citation structure, you need to update all citations. Similarly for unit tests, if you change the testing style or framework, you should update existing tests.
A brief story: Kris at one point wound up on a team of one and his manager wasn't familiar with Go. So who did his code reviews? They decided that an engineer from another team would be "loaned". This teammate was named Craig and he is the one who likes doing large code reviews. Kris didn't know this at the time and he submitted a gigantic PR to him and told Craig, "I'm so sorry." But to Kris's surprise, he came back the next day and he found a ton of useful comments in Gerrit. Craig told him it was a lot of fun and he learned a lot about Go in the process. One thing that stuck out to Kris was that Craig kept saying, "I've left a lot of comments but this is your code. You are making the final decisions and own this code."
So isn't a programmer more like a writer, rather than an editor?
Borrowing from the notion of an "editor":
- Editors don't write manuscripts themselves. They don't "own" the manuscript themselves, but they are absolutely necessary to deliver writing into publication.
- Some companies have engineers that help with this. It depends on the company's size if this is feasible, but someone should be doing this, even if not full-time.
Manuals of style
There are many manuals of style in publishing, but there are two main ones:
- The Chicago Manual of Style
- The AP Stylebook
There is nothing on the scale of these two style guides in Go. Some projects and companies have tried to adopt a consistent manual of style across the whole team or organization.
What is a manual of style?
- They are maily a reference manual
- They expect the reader to have an understanding of the language already
- They are extremely prescriptive. The purpose is to give an unambiguous answer to every questions.
- They enforce consistency
There is a hierarchy of manuals of style. At the top are the CMS and AP Stylebook, but each publishing house also has a localized manual of style.
What should go into a manual of style? "Meta" things, NOT "design" things:
- Type naming conventions
- How many methods per interface
- Else statements in the codebase NOT:
- Wire protocols
- Storage formats
The distinction gets a little fuzzy. In a localized manual of style, you may want to enforce consistency in something like middleware that might be a combo of systems "design" and "meta" things.
How do we get started?
- Start with a community manual of style
- Start with Code review comments
- Make it evolutionary, not revolutionary. The original Chicago Manual of Style was small and it grew over 17 subsequent editions
- You figure out what to include by asking questions about your codebase that don't yet have answers
- GoDoc can be used to merge manuals of style together and then to enforce the consolidated style guide across many codebases
But avoid dogma. There is a difference between enlightened consistency and dogmatism. Even experienced adherents to the Chicago Manual of Style will deviate from it. Learn the rules, then break them:
- Know the rules first.
- Track your deviation from what is prescribed by the manual of style. Explain why.
- Stay consistent. If you deviate, at least ensure every instance of that pattern (e.g., comman inside the quotes or outside) is consistent.
- Go is positioned to borrow a lot of good ideas from publishing
- The roles of an editor in publishing can inform what we do in the process of software engineering
- Manuals of style
About the author
Beyang Liu is the CTO and co-founder of Sourcegraph. Beyang studied Computer Science at Stanford, where he published research in probabilistic graphical models and computer vision at the Stanford AI Lab. You can chat with Beyang on Twitter @beyang or our community Discord.