talks: add 2016/refactor.article, based on my GothamGo talk

Change-Id: I62653a352773429c4517355d6c280289badd213f
Reviewed-on: https://go-review.googlesource.com/33723
Run-TryBot: Russ Cox <rsc@golang.org>
Reviewed-by: Russ Cox <rsc@golang.org>
diff --git a/2016/refactor.article b/2016/refactor.article
new file mode 100644
index 0000000..3639a7d
--- /dev/null
+++ b/2016/refactor.article
@@ -0,0 +1,698 @@
+Codebase Refactoring (with help from Go)
+
+Russ Cox
+rsc@golang.org
+
+* Abstract
+
+Go should add the ability to create alternate equivalent names for types,
+in order to enable gradual code repair during codebase refactoring.
+This article explains the need for that ability and the implications of not having it
+for today’s large Go codebases.
+This article also examines some potential solutions,
+including the alias feature proposed during the development of
+(but not included in) Go 1.8.
+However, this article is _not_ a proposal of any specific solution.
+Instead, it is intended as the start of a discussion by the Go community
+about what solution should be included in Go 1.9.
+
+This article is an extended version of a talk given at
+GothamGo in New York on November 18, 2016.
+
+* Introduction
+
+Go’s goal is to make it easy to build software that scales.
+There are two kinds of scale that we care about.
+One kind of scale is the size of the systems that you can build with Go,
+meaning how easy it is to use large numbers of computers,
+process large amounts of data, and so on.
+That’s an important focus for Go but not for this article.
+Instead, this article focuses on another kind of scale,
+the size of Go programs,
+meaning how easy it is to work in large codebases
+with large numbers of engineers
+making large numbers of changes independently.
+
+One such codebase is
+[[http://m.cacm.acm.org/magazines/2016/7/204032-why-google-stores-billions-of-lines-of-code-in-a-single-repository/pdf][Google’s single repository]]
+that nearly all engineers work in on a daily basis.
+As of January 2015,
+that repository was seeing 40,000 commits per day
+across 9 million source files
+and 2 billion lines of code.
+Of course, there is more in the repository than just Go code.
+
+Another large codebase is the set of all the open source Go code
+that people have made available on GitHub
+and other code hosting sites.
+You might think of this as `go` `get`’s codebase.
+In contrast to Google’s codebase,
+`go` `get`’s codebase is completely decentralized,
+so it’s more difficult to get exact numbers.
+In November 2016, there were 140,000 packages known to [[https://godoc.org/][godoc.org]],
+and over 160,000
+[[https://github.com/search?utf8=%E2%9C%93&q=language%3AGo&type=Repositories&ref=searchresults][GitHub repos written in Go]].
+
+Supporting software development at this scale was in our
+minds from the very beginning of Go.
+We paid a lot of attention to implementing imports efficiently.
+We made sure that it was difficult to import code but forget to use it, to avoid code bloat.
+We made sure that there weren’t unnecessary dependencies
+between packages, both to simplify programs and to make it
+easier to test and refactor them.
+For more detail about these considerations, see Rob Pike’s 2012 article
+“[[https://talks.golang.org/2012/splash.article][Go at Google: Language Design in the Service of Software Engineering]].”
+
+Over the past few years we’ve come to realize that there’s
+more that can and should be done to make it easier
+to refactor whole codebases,
+especially at the broad package structure level,
+to help Go scale to ever-larger programs.
+
+* Codebase refactoring
+
+Most programs start with one package.
+As you add code, occasionally you recognize
+a coherent section of code that could stand on its own,
+so you move that section into its own package.
+Codebase refactoring is the process of rethinking
+and revising decisions about both the grouping of code
+into packages and the relationships between those packages.
+There are a few reasons you might want to change the way
+a codebase is organized into packages.
+
+The first reason is to split a package into more manageable pieces for users.
+For example, most users of [[https://golang.org/pkg/regexp/][package regexp]] don’t need access to the
+regular expression parser, although [[https://godoc.org/github.com/google/codesearch/regexp][advanced uses may]],
+so the parser is exported in [[https://golang.org/pkg/regexp/syntax][a separate regexp/syntax package]].
+
+The second reason is to [[https://blog.golang.org/package-names][improve naming]]. 
+For example, early versions of Go had an `io.ByteBuffer`,
+but we decided `bytes.Buffer` was a better name and package bytes a better place for the code.
+
+The third reason is to lighten dependencies.
+For example, we moved `os.EOF` to `io.EOF` so that code not using the operating system
+can avoid importing the fairly heavyweight [[https://golang.org/pkg/os][package os]].
+
+The fourth reason is to change the dependency graph
+so that one package can import another.
+For example, as part of the preparation for Go 1, we looked at the explicit dependencies
+between packages and how they constrained the APIs.
+Then we changed the dependency graph to make the APIs better.
+
+Before Go 1, the `os.FileInfo` struct contained these fields:
+
+	type FileInfo struct {
+		Dev      uint64 // device number
+		Ino      uint64 // inode number
+		...
+		Atime_ns int64  // access time; ns since epoch
+		Mtime_ns int64  // modified time; ns since epoch
+		Ctime_ns int64  // change time; ns since epoch
+		Name     string // name of file
+	}
+
+Notice the times `Atime_ns`, `Mtime_ns`, `Ctime_ns` have type int64,
+an `_ns` suffix, and are commented as “nanoseconds since epoch.”
+These fields would clearly be nicer using [[https://golang.org/pkg/time/#Time][`time.Time`]],
+but mistakes in the design of the package structure of the codebase
+prevented that.
+To be able to use `time.Time` here, we refactored the codebase.
+
+This graph shows eight packages from the standard library
+before Go 1, with an arrow from P to Q indicating that P imports Q.
+
+.html refactor/import1.html
+
+Nearly every package has to consider errors,
+so nearly every package, including package time, imported package os for `os.Error`.
+To avoid cycles, anything that imports package os cannot itself be used by package os.
+As a result, operating system APIs could not use `time.Time`.
+
+This kind of problem convinced us that
+`os.Error` and its constructor `os.NewError` were so fundamental
+that they should be moved out of package os.
+In the end, we moved `os.Error` into the language as [[https://golang.org/ref/spec/#Errors][`error`]]
+and `os.NewError` into the new 
+[[https://golang.org/pkg/errors][package errors]]
+as `errors.New`.
+After this and other refactoring, the import graph in Go 1 looked like:
+
+.html refactor/import2.html
+
+Package io and package time had few enough dependencies
+to be used by package os, and
+the Go 1 definition of [[https://golang.org/pkg/os/#FileInfo][`os.FileInfo`]] does use `time.Time`.
+
+(As a side note, our first idea was to move `os.Error` and `os.NewError`
+to a new package named error (singular) as `error.Value` and `error.New`.
+Feedback from Roger Peppe and others in the Go community helped us
+see that making the error type predefined in the language would 
+allow its use even in low-level contexts like the specification of 
+[[https://golang.org/ref/spec#Run_time_panics][run-time panics]].
+Since the type was named `error`, the package became errors (plural)
+and the constructor `errors.New`.
+Andrew Gerrand’s 2015 talk
+“[[https://talks.golang.org/2015/how-go-was-made.slide#37][How Go was Made]]” has more detail.)
+
+* Gradual code repair
+
+The benefits of a codebase refactoring apply throughout the codebase.
+Unfortunately, so do the costs:
+often a large number of repairs must be made as a result of the refactoring.
+As codebases grow, it becomes infeasible to do all the repairs at one time.
+The repairs must be done gradually, 
+and the programming language must make that possible.
+
+As a simple example,
+when we moved `io.ByteBuffer` to `bytes.Buffer` in 2009, the [[https://go.googlesource.com/go/+/d3a412a5abf1ee8815b2e70a18ee092154af7672][initial commit]]
+moved two files, adjusted three makefiles, and repaired 43 other Go source files.
+The repairs outweighed the actual API change by a factor of twenty,
+and the entire codebase was only 250 files.
+As codebases grow, so does the repair multiplier.
+Similar changes in large Go codebases, 
+such as Docker, and Juju, and Kubernetes,
+can have repair multipliers ranging from 10X to 100X.
+Inside Google we’ve seen repair multipliers well over 1000X.
+
+The conventional wisdom is that when making a codebase-wide API change,
+the API change and the associated code repairs should be committed
+together in one big commit:
+
+.html refactor/atomic.html
+
+The argument in favor of this approach, 
+which we will call “atomic code repair,”
+is that it is conceptually simple:
+by updating the API and the code repairs in the same commit,
+the codebase transitions in one step from the old API to the new API,
+without ever breaking the codebase.
+The atomic step avoids the need to plan for a transition
+during which both old and new API must coexist.
+In large codebases, however, the conceptual simplicity
+is quickly outweighed by a practical complexity:
+the one big commit can be very big.
+Big commits are hard to prepare, hard to review,
+and are fundamentally racing against other work in the tree.
+It’s easy to start doing a conversion, prepare your one big commit,
+finally get it submitted, and only then find out that another developer added
+a use of the old API while you were working.
+There were no merge conflicts,
+so you missed that use, and despite all your effort
+the one big commit broke the codebase.
+As codebases get larger,
+atomic code repairs become more difficult
+and more likely to break the codebase inadvertently.
+
+In our experience,
+an approach that scales better is to plan for a transition period
+during which the code repair proceeds gradually,
+across as many commits as needed:
+
+.html refactor/gradual.html
+
+Typically this means the overall process runs in three stages.
+First, introduce the new API.
+The old and new API must be _interchangeable_,
+meaning that it must be possible to convert individual uses
+from the old to the new API without changing the overall
+behavior of the program,
+and uses of the old and new APIs must be able to coexist
+in a single program.
+Second, across as many commits as you need,
+convert all the uses of the old API to the new API.
+Third, remove the old API.
+
+“Gradual code repair” is usually more work
+than the atomic code repair,
+but the work itself is easier:
+you don’t have to get everything right in one try.
+Also, the individual commits are much smaller,
+making them easier to review and submit
+and, if needed, roll back.
+Maybe most important of all, a gradual code repair
+works in situations when one big commit would be impossible,
+for example when code that needs repairs
+is spread across multiple repositories.
+
+The `bytes.Buffer` change looks like an atomic code repair, but it wasn’t.
+Even though the commit updated 43 source files,
+the commit message says,
+“left io.ByteBuffer stub around for now, for protocol compiler.”
+That stub was in a new file named `io/xxx.go` that read:
+
+	// This file defines the type io.ByteBuffer
+	// so that the protocol compiler's output
+	// still works. Once the protocol compiler
+	// gets fixed, this goes away.
+	
+	package io
+	
+	import "bytes"
+	
+	type ByteBuffer struct {
+		bytes.Buffer;
+	}
+
+Back then, just like today,
+Go was developed in a separate source repository
+from the rest of Google’s source code.
+The protocol compiler in Google’s main repository was
+responsible for generating Go source files from protocol buffer definitions;
+the generated code used `io.ByteBuffer`.
+This stub was enough to keep the generated code working
+until the protocol compiler could be updated.
+Then [[https://go.googlesource.com/go/+/832e72beff62e4fe4897699e9b40a2b228e8503b][a later commit]] removed `xxx.go`.
+
+Even though there were many fixes included in the original commit,
+this change was still a gradual code repair, not an atomic one,
+because the old API was only removed in a separate stage
+after the existing code was converted.
+
+In this specific case the gradual repair did succeed, but
+the old and new API were not completely interchangeable:
+if there had been a function taking an `*io.ByteBuffer` argument
+and code calling that function with an `*io.ByteBuffer`,
+those two pieces of code could not have been updated independently:
+code that passed an `*io.ByteBuffer` to a function expecting a `*bytes.Buffer`,
+or vice versa, would not compile.
+
+Again, a gradual code repair consists of three stages:
+
+.html refactor/template.html
+
+These stages apply to a gradual code repair for any API change.
+In the specific case of codebase refactoring—moving
+an API from one package to another, changing its full name in the process—making the old and new API
+interchangeable means making the old and new names interchangeable,
+so that code using the old name has exactly the same behavior
+as if it used the new name.
+
+Let’s look at examples of how Go makes that possible (or not).
+
+** Constants
+
+Let’s start with a simple example of moving a constant.
+
+Package io defines the [[https://golang.org/pkg/io/#Seeker][Seeker interface]],
+but the named constants that developers prefer to use
+when invoking the `Seek` method came from package os.
+Go 1.7 moved the constants to package io and gave them more idiomatic names;
+for example, `os.SEEK_SET` is now available as `io.SeekStart`.
+
+For a constant, one name is interchangeable with another
+when the definitions use the same type and value:
+
+	package io
+	const SeekStart int = 0
+	
+	package os
+	const SEEK_SET int = 0
+
+Due to [[https://golang.org/doc/go1compat][Go 1 compatibility]],
+we’re blocked in stage 2 of this gradual code change.
+We can’t delete the old constants,
+but making the new ones available in package io allows
+developers to avoid importing package os in code that
+does not actually depend on operating system functionality.
+
+This is also an example of a gradual code repair being done
+across many repositories.
+Go 1.7 introduced the new API,
+and now it’s up to everyone with Go code to update their code
+as they see fit.
+There’s no rush, no forced breakage of existing code.
+
+** Functions
+
+Now let’s look at moving a function from one package to another.
+
+As mentioned above,
+in 2011 we replaced `os.Error` with the predefined type `error`
+and moved the constructor `os.NewError` to a new package as
+[[https://golang.org/pkg/errors/#New][`errors.New`]].
+
+For a function, one name is interchangeable with another
+when the definitions use the same signature and implementation.
+In this case, we can define the old function as a wrapper calling
+the new function:
+
+	package errors
+	func New(msg string) error { ... }
+	
+	package os
+	func NewError(msg string) os.Error {
+	    return errors.New(msg)
+	}
+
+Since Go does not allow comparing functions for equality,
+there is no way to tell these two functions apart.
+The old and new API are interchangeable,
+so we can proceed to stages 2 and 3.
+
+(We are ignoring a small detail here: the original 
+`os.NewError` returned an `os.Error`, not an `error`,
+and two functions with different signatures _are_ distinguishable.
+To really make these functions indistinguishable,
+we would also need to make `os.Error` and `error` indistinguishable.
+We will return to that detail in the discussion of types below.)
+
+** Variables
+
+Now let’s look at moving a variable from one package to another.
+
+We are discussing exported package-level API, so the variable
+in question must be an exported global variable.
+Such variables are almost always set at init time
+and then only intended to be read from, never written again,
+to avoid races between reading and writing goroutines.
+For exported global variables that follow this pattern,
+one name is nearly interchangeable with another when the two have
+the same type and value.
+The simplest way to arrange that is to initialize one from the other:
+
+	package io
+	var EOF = ...
+	
+	package os
+	var EOF = io.EOF
+
+In this example, io.EOF and os.EOF are the same value. 
+The variable values are completely interchangeable.
+
+There is one small problem.
+Although the variable values are interchangeable,
+the variable addresses are not.
+In this example, `&io.EOF` and `&os.EOF` are different pointers.
+However, it is rare to export a read-only variable
+from a package and expect clients to take its address:
+it would be better for clients if the package exported a variable set to the address instead,
+and then the pattern works.
+
+** Types
+
+Finally let’s look at moving a type from one package to another.
+This is much harder to do in Go today, as the following three examples demonstrate.
+
+*** Go’s os.Error
+
+Consider once more the conversion from `os.Error` to `error`.
+There’s no way in Go to make two names of types interchangeable.
+The closest we can come in Go is to give `os.Error` and `error` the same underlying definition:
+
+	package os
+	type Error error 
+
+Even with this definition, and even though these are interface types,
+Go still considers these two types [[https://golang.org/ref/spec#Type_identity][different]],
+so that a function returning an os.Error
+is not the same as a function returning an error.
+Consider the [[https://golang.org/pkg/io/#Reader][`io.Reader`]] interface:
+	
+	package io
+	type Reader interface {
+	    Read(b []byte) (n int, err error)
+	}
+
+If `io.Reader` is defined using `error`, as above, then a `Read` method 
+returning `os.Error` will not satisfy the interface.
+
+If there’s no way to make two names for a type interchangeable,
+that raises two questions.
+First, how do we enable a gradual code repair for a moved or renamed type?
+Second, what did we do for `os.Error` in 2011?
+
+To answer the second question, we can look at the source control history.
+It turns out that to aid the conversion, we
+[[https://go.googlesource.com/go/+/47f4bf763dcb120d3b005974fec848eefe0858f0][added a temporary hack to the compiler]]
+to make code written using `os.Error` be interpreted as if it had written `error` instead.
+
+*** Kubernetes
+
+This problem with moving types is not limited to fundamental changes like `os.Error`,
+nor is it limited to the Go repository.
+Here’s a change from the [[https://kubernetes.io/][Kubernetes project]].
+Kubernetes has a package util, and at some point the developers
+decided to split out that package’s `IntOrString` type into its own 
+[[https://godoc.org/k8s.io/kubernetes/pkg/util/intstr][package intstr]].
+
+Applying the pattern for a gradual code repair,
+the first stage is to establish a way for the two types to be interchangeable.
+We can’t do that,
+because the `IntOrString` type is used in struct fields,
+and code can’t assign to that field unless the value being
+assigned has the correct type:
+
+	package util
+	type IntOrString intstr.IntOrString
+
+	// Not good enough for:
+	
+	// IngressBackend describes ...
+	type IngressBackend struct {
+	    ServiceName string             `json:"serviceName"`
+	    ServicePort intstr.IntOrString `json:"servicePort"`
+	}
+
+If this use were the only problem, then you could imagine
+writing a getter and setter using the old type
+and doing a gradual code repair to change all existing code
+to use the getter and setter,
+then modifying the field to use the new type
+and doing a gradual code repair to change all existing code
+to access the field directly using the new type,
+then finally deleting the getter and setter that mention the old type.
+That required two gradual code repairs instead of one,
+and there are many uses of the type other than this one struct field.
+
+In practice, the only option here is an atomic code repair,
+or else breaking all code using `IntOrString`.
+
+*** Docker
+
+As another example,
+here’s a change from the [[https://www.docker.com/][Docker project]].
+Docker has a package utils, and at some point the developers
+decided to split out that package’s `JSONError` type into a separate
+[[https://godoc.org/github.com/docker/docker/pkg/jsonmessage#JSONError][jsonmessage package]].
+
+Again we have the problem that the old and new types are not interchangeable,
+but it shows up in a different way, namely [[https://golang.org/ref/spec#Type_assertions][type assertions]]:
+
+	package utils
+	type JSONError jsonmessage.JSONError
+
+	// Not good enough for:
+	
+	jsonError, ok := err.(*jsonmessage.JSONError)
+	if !ok {
+		jsonError = &jsonmessage.JSONError{
+			Message: err.Error(),
+		}
+	}
+
+If the error `err` not already a `JSONError`, this code wraps it in one,
+but during a gradual repair, this code handles `utils.JSONError` and `jsonmessage.JSONError` differently.
+The two types are not interchangeable.
+(A [[https://golang.org/ref/spec#Type_switches][type switch]] would expose the same problem.)
+
+If this line were the only problem, then you could imagine
+adding a type assertion for `*utils.JSONError`,
+then doing a gradual code repair to remove other uses of `utils.JSONError`,
+and finally removing the additional type guard just before removing the old type.
+But this line is not the only problem.
+The type is also used elsewhere in the API and has all the 
+problems of the Kubernetes example.
+
+In practice, again the only option here is an atomic code repair
+or else breaking all code using `JSONError`.
+
+* Solutions?
+
+We’ve now seen examples of how we can and cannot move
+constants, functions, variables, and types from one package to another.
+The patterns for establishing interchangeable old and new API are:
+
+	const OldAPI = NewPackage.API
+
+	func OldAPI() { NewPackage.API() }
+
+	var OldAPI = NewPackage.API
+	
+	type OldAPI ... ??? modify compiler or ... ???
+
+For constants and functions, the setup for a gradual code repair is trivial.
+For variables, the trivial setup is incomplete but only in ways that are not likely to arise often in practice.
+
+For types, there is no way to set up a gradual code repair in essentially any real example.
+The most common option is to force an atomic code repair,
+or else to break all code using the moved type and leave clients
+to fix their code at the next update.
+In the case of moving os.Error, we resorted to modifying the compiler.
+None of these options is reasonable.
+Developers should be able to do refactorings
+that involve moving a type from one package to another
+without needing an atomic code repair,
+without resorting to intermediate code and multiple rounds of repair,
+without forcing all client packages to update their own code immediately,
+and without even thinking about modifying the compiler.
+
+But how? What should these refactorings look like tomorrow?
+
+We don’t know.
+The goal of this article is to define the problem well enough
+to discuss the possible answers.
+
+** Aliases
+
+As explained above, the fundamental problem with moving types is that
+while Go provides ways to create an alternate name
+for a constant or a function or (most of the time) a variable,
+there is no way to create an alternate name for a type.
+
+For Go 1.8 we experimented with introducing first-class support
+for these alternate names, called [[https://golang.org/design/16339-alias-decls][_aliases_]].
+A new declaration syntax, the alias form, would have provided a uniform way
+to create an alternate name for any kind of identifier:
+
+	const OldAPI => NewPackage.API
+	func  OldAPI => NewPackage.API
+	var   OldAPI => NewPackage.API
+	type  OldAPI => NewPackage.API
+
+Instead of four different mechanisms, the refactoring of package os we considered above
+would have used a single mechanism:
+
+	package os
+	const SEEK_SET => io.SeekStart
+	func  NewError => errors.New
+	var   EOF      => io.EOF
+	type  Error    => error
+
+During the Go 1.8 release freeze, we found two small but important unresolved technical details
+in the alias support (issues [[https://golang.org/issue/17746][17746]] and [[https://golang.org/issue/17784][17784]]),
+and we decided that it was not possible to resolve them confidently
+in the time remaining before the Go 1.8 release,
+so we held aliases back from Go 1.8.
+
+** Versioning
+
+An obvious question is whether to rely on versioning and
+dependency management for code repair,
+instead of focusing on strategies that enable gradual code repair.
+
+Versioning and gradual code repair strategies are complementary.
+A versioning system’s job is to identify a compatible set of
+versions of all the packages needed in a program, or else to
+explain why no such set can be constructed.
+Gradual code repair creates additional compatible combinations,
+making it more likely that a versioning system can find a way
+to build a particular program.
+
+Consider again the various updates to Go’s standard library
+that we discussed above.
+Suppose that the old API
+corresponded in a versioning system
+to standard library version 5.1.3.
+In the usual atomic code repair approach,
+the new API would be introduced and the old API removed at the same time,
+resulting in version 6.0.0;
+following [[http://semver.org/][semantic versioning]],
+the major version number is incremented to indicate the incompatibility
+caused by removing the old API.
+
+Now suppose that your larger program depends on two packages, Foo and Bar.
+Foo still uses the old standard library API.
+Bar has been updated to use the new standard library API,
+and there have been important changes since then that your
+program needs: you can’t use an older version of Bar from
+before the standard library changes.
+
+.html refactor/version1.html
+
+There is no compatible set of libraries to build your program:
+you want the latest version of Bar, which requires 
+standard library 6.0.0,
+but you also need Foo, which is incompatible with standard library 6.0.0.
+The best a versioning system can do in this case is report the failure clearly.
+(If you are sufficiently motivated, you might then resort to updating your own copy of Foo.)
+
+In contrast, with better support for gradual code repair,
+we can add the new, interchangeable API in version 5.2.0,
+and then remove the old API in version 6.0.0.
+
+.html refactor/version2.html
+
+The intermediate version 5.2.0 is backwards compatible with 5.1.3,
+indicated by the shared major version number 5.
+However, because the change from 5.2.0 to 6.0.0 only removed API,
+5.2.0 is also, perhaps surprisingly, backwards compatible with 6.0.0.
+Assuming that Bar declares its requirements precisely—it is
+compatible with both 5.2.0 and 6.0.0—a version system can see that
+both Foo and Bar are compatible with 5.2.0 and use that version
+of the standard library to build the program.
+
+Good support for and adoption of gradual code repair reduces incompatibility,
+giving versioning systems a better chance to find a way to build your program.
+
+** Type aliases
+
+To enable gradual code repair during codebase refactorings,
+it must be possible to create alternate names for a 
+constant, function, variable, or type.
+Go already allows introducing alternate names for 
+all constants, all functions, and nearly all variables, but no types.
+Put another way,
+the general alias form is never necessary for constants,
+never necessary for functions,
+only rarely necessary for variables,
+but always necessary for types.
+
+The relative importance to the specific declarations
+suggests that perhaps the Go 1.8 aliases were an overgeneralization,
+and that we should instead focus on a solution limited to types.
+The obvious solution is type-only aliases,
+for which no new operator is required.
+Following 
+[[http://www.freepascal.org/docs-html/ref/refse19.html][Pascal]]
+(or, if you prefer, [[https://doc.rust-lang.org/book/type-aliases.html][Rust]]),
+a Go program could introduce a type alias using the assignment operator:
+
+	type OldAPI = NewPackage.API
+
+The idea of limiting aliases to types was
+[[https://golang.org/issue/16339#issuecomment-233644777][raised during the Go 1.8 alias discussion]],
+but it seemed worth trying the more general approach, which we did, unsuccessfully.
+In retrospect, the fact that `=` and `=>` have identical meanings for constants
+while they have nearly identical but subtly different meanings for variables
+suggests that the general approach is not worth its complications.
+
+In fact, the idea of adding Pascal-style type aliases
+was [[https://golang.org/issue/16339#issuecomment-233759255][considered in the early design of Go]],
+but until now we didn’t have a strong use case for them.
+
+Type aliases seem like a promising approach to explore,
+but, at least to me, generalized aliases seemed equally promising
+before the discussion and experimentation during the Go 1.8 cycle.
+Rather than prejudge the outcome, the goal of this article is to
+explain the problem in detail and examine a few possible solutions,
+to enable a productive discussion and evaluation of ideas for next time.
+
+* Challenge
+
+Go aims to be ideal for large codebases.
+
+In large codebases, it’s important to be able to refactor codebase structure,
+which means moving APIs between packages and updating client code.
+
+In such large refactorings, it’s important to be able to use a gradual transition from the old API to the new API.
+
+Go does not support the specific case of gradual code repair when moving types between packages at all. It should.
+
+I hope we the Go community can fix this together in Go 1.9. Maybe type aliases are a good starting point. Maybe not. Time will tell.
+
+* Acknowledgements
+
+Thanks to the many people who helped us [[https://golang.org/issue/16339][think through the design questions]]
+that got us this far and led to the alias trial during Go 1.8 development.
+I look forward to the Go community helping us again when we revisit this problem for Go 1.9.
diff --git a/2016/refactor/atomic.graffle b/2016/refactor/atomic.graffle
new file mode 100644
index 0000000..a4d9fa4
--- /dev/null
+++ b/2016/refactor/atomic.graffle
Binary files differ
diff --git a/2016/refactor/atomic.html b/2016/refactor/atomic.html
new file mode 100644
index 0000000..7d15ce3
--- /dev/null
+++ b/2016/refactor/atomic.html
@@ -0,0 +1 @@
+<div class="image"><center><img src="refactor/atomic.svg" alt="Atomic Code Repair"></img></center></div>
diff --git a/2016/refactor/atomic.svg b/2016/refactor/atomic.svg
new file mode 100644
index 0000000..244fe37
--- /dev/null
+++ b/2016/refactor/atomic.svg
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-1 -1 124 82" width="124pt" height="82pt" xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <metadata> Produced by OmniGraffle 7.2.1 
+    <dc:date>2016-12-01 03:28:54 +0000</dc:date>
+  </metadata>
+  <defs>
+    <font-face font-family="Arial" font-size="12" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-105.95703" underline-thickness="73.24219" slope="0" x-height="518.5547" cap-height="716.3086" ascent="905.2734" descent="-211.91406" font-weight="500">
+      <font-face-src>
+        <font-face-name name="ArialMT"/>
+      </font-face-src>
+    </font-face>
+  </defs>
+  <g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1">
+    <title>Canvas 1</title>
+    <g>
+      <title>Layer 1</title>
+      <text transform="translate(17.125 4.411133)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="9.143555" y="11" textLength="50.033203">Add new </tspan>
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="58.51465" y="11" textLength="19.341797">API</tspan>
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="9.149414" y="39.39258" textLength="68.70117">Code repairs</tspan>
+        <tspan font-family="Arial" font-size="12" font-weight="500" x=".47753906" y="67.78516" textLength="67.365234">Remove old </tspan>
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="67.180664" y="67.78516" textLength="19.341797">API</tspan>
+      </text>
+      <path d="M 18.1875 7105427e-21 L 103.0625 7105427e-21 C 113.102 7105427e-21 121.25 17.92 121.25 40 C 121.25 62.08 113.102 80 103.0625 80 L 18.1875 80 C 8.148 80 0 62.08 0 40 C 0 17.92 8.148 7105427e-21 18.1875 7105427e-21" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+    </g>
+  </g>
+</svg>
diff --git a/2016/refactor/gradual.graffle b/2016/refactor/gradual.graffle
new file mode 100644
index 0000000..65b6e84
--- /dev/null
+++ b/2016/refactor/gradual.graffle
Binary files differ
diff --git a/2016/refactor/gradual.html b/2016/refactor/gradual.html
new file mode 100644
index 0000000..24c5612
--- /dev/null
+++ b/2016/refactor/gradual.html
@@ -0,0 +1 @@
+<div class="image"><center><img src="refactor/gradual.svg" alt="Gradual Code Repair"></img></center></div>
diff --git a/2016/refactor/gradual.svg b/2016/refactor/gradual.svg
new file mode 100644
index 0000000..d0caccb
--- /dev/null
+++ b/2016/refactor/gradual.svg
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-2 -1 305 178" width="305pt" height="178pt" xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <metadata> Produced by OmniGraffle 7.2.1 
+    <dc:date>2016-12-01 03:27:43 +0000</dc:date>
+  </metadata>
+  <defs>
+    <font-face font-family="Arial" font-size="12" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-105.95703" underline-thickness="73.24219" slope="0" x-height="518.5547" cap-height="716.3086" ascent="905.2734" descent="-211.91406" font-weight="500">
+      <font-face-src>
+        <font-face-name name="ArialMT"/>
+      </font-face-src>
+    </font-face>
+    <font-face font-family="Arial" font-size="10" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-105.95703" underline-thickness="73.24219" slope="0" x-height="518.5547" cap-height="716.3086" ascent="905.2734" descent="-211.91406" font-weight="500">
+      <font-face-src>
+        <font-face-name name="ArialMT"/>
+      </font-face-src>
+    </font-face>
+  </defs>
+  <g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1">
+    <title>Canvas 1</title>
+    <g>
+      <title>Layer 1</title>
+      <path d="M 107.86806 0 L 192.9375 0 C 203 0 211.16667 5.0524444 211.16667 11.277778 C 211.16667 17.503111 203 22.555556 192.9375 22.555556 L 107.86806 22.555556 C 97.80556 22.555556 89.63889 17.503111 89.63889 11.277778 C 89.63889 5.0524444 97.80556 0 107.86806 0" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+      <text transform="translate(106.79167 4.0814887)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="9.254666" y="11" textLength="50.033203">Add new </tspan>
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="58.62576" y="11" textLength="19.341797">API</tspan>
+      </text>
+      <path d="M 107.86806 38.11111 L 192.9375 38.11111 C 203 38.11111 211.16667 43.163556 211.16667 49.38889 C 211.16667 55.61422 203 60.66667 192.9375 60.66667 L 107.86806 60.66667 C 97.80556 60.66667 89.63889 55.61422 89.63889 49.38889 C 89.63889 43.163556 97.80556 38.11111 107.86806 38.11111" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+      <text transform="translate(106.79167 42.1926)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="9.260525" y="11" textLength="68.70117">Code repairs</tspan>
+      </text>
+      <path d="M 184.09028 76.22222 L 269.15972 76.22222 C 279.22222 76.22222 287.3889 81.27467 287.3889 87.5 C 287.3889 93.72533 279.22222 98.77778 269.15972 98.77778 L 184.09028 98.77778 C 174.02778 98.77778 165.86111 93.72533 165.86111 87.5 C 165.86111 81.27467 174.02778 76.22222 184.09028 76.22222" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+      <text transform="translate(183.01389 80.30371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="9.260525" y="11" textLength="68.70117">Code repairs</tspan>
+      </text>
+      <path d="M 30.868056 76.22222 L 115.9375 76.22222 C 126 76.22222 134.16667 81.27467 134.16667 87.5 C 134.16667 93.72533 126 98.77778 115.9375 98.77778 L 30.868056 98.77778 C 20.805556 98.77778 12.638889 93.72533 12.638889 87.5 C 12.638889 81.27467 20.805556 76.22222 30.868056 76.22222" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+      <text transform="translate(29.791667 80.30371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="9.260525" y="11" textLength="68.70117">Code repairs</tspan>
+      </text>
+      <path d="M 107.86806 114.33333 L 192.9375 114.33333 C 203 114.33333 211.16667 119.38578 211.16667 125.61111 C 211.16667 131.83644 203 136.88889 192.9375 136.88889 L 107.86806 136.88889 C 97.80556 136.88889 89.63889 131.83644 89.63889 125.61111 C 89.63889 119.38578 97.80556 114.33333 107.86806 114.33333" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+      <text transform="translate(106.79167 118.41482)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="9.260525" y="11" textLength="68.70117">Code repairs</tspan>
+      </text>
+      <path d="M 102.67639 152.66667 L 198.12917 152.66667 C 209.41987 152.66667 218.58333 157.71911 218.58333 163.94444 C 218.58333 170.16978 209.41987 175.22222 198.12917 175.22222 L 102.67639 175.22222 C 91.38569 175.22222 82.22222 170.16978 82.22222 163.94444 C 82.22222 157.71911 91.38569 152.66667 102.67639 152.66667" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"/>
+      <text transform="translate(100.85833 156.74816)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="6.5219835" y="11" textLength="67.365234">Remove old </tspan>
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="73.22511" y="11" textLength="19.341797">API</tspan>
+      </text>
+      <line x1="36948222e-20" y1="29.555556" x2="300.41667" y2="29.555556" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="36948222e-20" y1="144.27778" x2="300.41667" y2="144.27778" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(5 2.8919813)" fill="black">
+        <tspan font-family="Arial" font-size="10" font-weight="500" x="11.985894" y="9" textLength="34.472656">Stage 1</tspan>
+      </text>
+      <text transform="translate(5 40.225315)" fill="black">
+        <tspan font-family="Arial" font-size="10" font-weight="500" x="11.985894" y="9" textLength="34.472656">Stage 2</tspan>
+      </text>
+      <text transform="translate(5 155.33643)" fill="black">
+        <tspan font-family="Arial" font-size="10" font-weight="500" x="11.985894" y="9" textLength="34.472656">Stage 3</tspan>
+      </text>
+    </g>
+  </g>
+</svg>
diff --git a/2016/refactor/import1.graffle b/2016/refactor/import1.graffle
new file mode 100644
index 0000000..020014a
--- /dev/null
+++ b/2016/refactor/import1.graffle
Binary files differ
diff --git a/2016/refactor/import1.html b/2016/refactor/import1.html
new file mode 100644
index 0000000..72177fd
--- /dev/null
+++ b/2016/refactor/import1.html
@@ -0,0 +1 @@
+<div class="image"><center><img src="refactor/import1.svg" alt="Import graph before Go 1"></img></center></div>
diff --git a/2016/refactor/import1.svg b/2016/refactor/import1.svg
new file mode 100644
index 0000000..5019904
--- /dev/null
+++ b/2016/refactor/import1.svg
@@ -0,0 +1,76 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="0 -1 150 284" width="150pt" height="284pt" xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <metadata> Produced by OmniGraffle 7.2.1 
+    <dc:date>2016-12-01 04:39:54 +0000</dc:date>
+  </metadata>
+  <defs>
+    <font-face font-family="Arial" font-size="12" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-105.95703" underline-thickness="73.24219" slope="0" x-height="518.5547" cap-height="716.3086" ascent="905.2734" descent="-211.91406" font-weight="500">
+      <font-face-src>
+        <font-face-name name="ArialMT"/>
+      </font-face-src>
+    </font-face>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -3 6 6" markerWidth="6" markerHeight="6" color="black">
+      <g>
+        <path d="M 4 0 L 0 -1.5 L 0 1.5 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+  </defs>
+  <g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1">
+    <title>Canvas 1</title>
+    <g>
+      <title>Layer 1</title>
+      <rect x="30.776487" y="0" width="76" height="23.5" fill="#0432ff" fill-opacity=".29794784"/>
+      <rect x="30.776487" y="0" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(35.776487 4.553711)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="21.66504" y="11" textLength="22.669922">time</tspan>
+      </text>
+      <rect x="30.776487" y="37" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(35.776487 41.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="14.323242" y="11" textLength="37.353516">io/ioutil</tspan>
+      </text>
+      <rect x="30.776487" y="74" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(35.776487 78.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="13.661133" y="11" textLength="38.677734">strconv</tspan>
+      </text>
+      <rect x="30.776487" y="111" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(35.776487 115.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="18.65918" y="11" textLength="28.68164">bytes</tspan>
+      </text>
+      <rect x="30.776487" y="148" width="76" height="23.5" fill="#ff2600" fill-opacity=".30133143"/>
+      <rect x="30.776487" y="148" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(35.776487 152.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="28.330078" y="11" textLength="9.339844">io</tspan>
+      </text>
+      <rect x="30.776487" y="185" width="76" height="23.5" fill="#fffc00" fill-opacity=".30303697"/>
+      <rect x="30.776487" y="185" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(35.776487 189.5537)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="26.663086" y="11" textLength="12.673828">os</tspan>
+      </text>
+      <rect x="30.776487" y="222" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(35.776487 226.5537)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="14.99707" y="11" textLength="36.00586">syscall</tspan>
+      </text>
+      <rect x="30.776487" y="259" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(35.776487 263.5537)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="19.655273" y="11" textLength="26.689453">utf16</tspan>
+      </text>
+      <line x1="68.77649" y1="23.5" x2="68.77649" y2="31.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="68.77649" y1="60.5" x2="68.77649" y2="68.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="68.77649" y1="97.5" x2="68.77649" y2="105.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="68.77649" y1="134.5" x2="68.77649" y2="142.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="68.77649" y1="171.5" x2="68.77649" y2="179.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="68.77649" y1="208.5" x2="68.77649" y2="216.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="68.77649" y1="245.5" x2="68.77649" y2="253.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 93.17678 23.500002 C 105.04188 30.545757 116.77649 40.134275 116.77649 50.5 C 116.77649 58.39145 109.97533 65.336525 101.49318 70.92955" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 103.57523 23.5 C 111.59158 28.577334 118.62773 35.76719 121.54406 45.89844 C 128.6898 70.72245 118.68265 88.35867 106.49728 106.14751" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 106.77649 20.676139 C 117.07421 26.626272 127.1848 36.423313 133.77649 52.5 C 152.33296 97.75797 152.69131 130.63325 134.27649 171.5 C 128.80609 183.64007 120.80561 190.79561 112.26099 194.85676" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 46.69024 60.5 C 32.14596 69.32664 15.776487 81.84894 15.776487 93.5 C 15.776487 99.29801 19.83028 104.12623 25.695615 108.07761" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 44.78756 60.5 C 27.89426 70.32656 8.276487 85.59294 8.276487 103.5 C 8.276487 119.9993 24.931005 134.66971 40.763704 144.88843" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 40.13828 60.499996 C 24.193 69.34241 6.925629 83.65174 3.7764867 105 C -1.1995027 138.73258 18.695969 159.73378 36.18698 180.46417" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 106.77649 94.66501 C 113.31042 98.37008 119.27522 103.60549 123.27649 111 C 137.72504 137.7015 135.21661 155.7066 119.77649 180 C 117.47504 183.62108 114.72658 186.53483 111.71549 188.87164" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 95.43459 134.5 C 107.53044 141.217 119.17688 150.30111 119.17688 160.3789 C 119.17688 168.6678 111.29816 176.08786 101.77084 182.03036" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 96.65663 208.5 C 109.00063 215.10652 120.77649 224.02344 120.77649 234 C 120.77649 242.434 112.36065 250.02977 102.3003 256.09678" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+    </g>
+  </g>
+</svg>
diff --git a/2016/refactor/import2.graffle b/2016/refactor/import2.graffle
new file mode 100644
index 0000000..16fe79e
--- /dev/null
+++ b/2016/refactor/import2.graffle
Binary files differ
diff --git a/2016/refactor/import2.html b/2016/refactor/import2.html
new file mode 100644
index 0000000..c88de12
--- /dev/null
+++ b/2016/refactor/import2.html
@@ -0,0 +1 @@
+<div class="image"><center><img src="refactor/import2.svg" alt="Import graph for Go 1"></img></center></div>
diff --git a/2016/refactor/import2.svg b/2016/refactor/import2.svg
new file mode 100644
index 0000000..9e569fd
--- /dev/null
+++ b/2016/refactor/import2.svg
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-1 -1 250 247" width="250pt" height="247pt" xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <metadata> Produced by OmniGraffle 7.2.1 
+    <dc:date>2016-12-01 04:34:01 +0000</dc:date>
+  </metadata>
+  <defs>
+    <font-face font-family="Arial" font-size="12" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-105.95703" underline-thickness="73.24219" slope="0" x-height="518.5547" cap-height="716.3086" ascent="905.2734" descent="-211.91406" font-weight="500">
+      <font-face-src>
+        <font-face-name name="ArialMT"/>
+      </font-face-src>
+    </font-face>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -3 6 6" markerWidth="6" markerHeight="6" color="black">
+      <g>
+        <path d="M 4 0 L 0 -1.5 L 0 1.5 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+  </defs>
+  <g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1">
+    <title>Canvas 1</title>
+    <g>
+      <title>Layer 1</title>
+      <rect x="122.97266" y="148" width="76" height="23.5" fill="#0432ff" fill-opacity=".295307"/>
+      <rect x="122.97266" y="148" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(127.97266 152.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="21.66504" y="11" textLength="22.669922">time</tspan>
+      </text>
+      <rect x="122.21255" y="0" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(127.21255 4.553711)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="14.323242" y="11" textLength="37.353516">io/ioutil</tspan>
+      </text>
+      <rect x="122.21255" y="74" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(127.21255 78.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="13.661133" y="11" textLength="38.677734">strconv</tspan>
+      </text>
+      <rect x="122.21255" y="37" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(127.21255 41.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="18.65918" y="11" textLength="28.68164">bytes</tspan>
+      </text>
+      <rect x="0" y="185" width="76" height="23.5" fill="#ffc0c0"/>
+      <rect x="0" y="185" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(5 189.5537)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="28.330078" y="11" textLength="9.339844">io</tspan>
+      </text>
+      <rect x="122.97266" y="111" width="76" height="23.5" fill="#ffffc0"/>
+      <rect x="122.97266" y="111" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(127.97266 115.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="26.663086" y="11" textLength="12.673828">os</tspan>
+      </text>
+      <rect x="122.97266" y="185" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(127.97266 189.5537)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="14.99707" y="11" textLength="36.00586">syscall</tspan>
+      </text>
+      <rect x="122.97266" y="222" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(127.97266 226.5537)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="19.655273" y="11" textLength="26.689453">utf16</tspan>
+      </text>
+      <rect x="0" y="222" width="76" height="23.5" stroke="#666" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(5 226.5537)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="17.332031" y="11" textLength="31.335938">errors</tspan>
+      </text>
+      <line x1="160.21255" y1="23.5" x2="160.21255" y2="31.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 188.37477 23.500003 C 200.08476 29.83677 211 38.35015 211 48.06921 C 211 56.7416 202.30916 64.687 192.11774 71.02284" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 197.74767 23.500009 C 218.19313 31.76049 239.38865 44.239423 239.5 60.5 C 239.6234 78.51898 213.82277 96.32661 191.76642 108.24899" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 198.21255 17.560787 C 216.79686 22.535277 236.5144 31.720686 242.85742 48.63171 C 255.90117 83.4074 229.45227 103.01963 206.2539 134.5 C 203.58735 138.11854 200.93553 141.23882 198.3303 143.92759" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="160.21255" y1="60.5" x2="160.21255" y2="68.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 122.21254 50.13559 C 113.00153 54.213294 102.8189 61.503755 92.5 74 C 67.89765 103.79357 50.741114 153.22393 42.870807 179.34142" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 122.21254 91.98431 C 118.5502 95.44879 114.92645 100.0403 111.5 106.06921 C 90.75852 142.56434 107.82292 178.3966 87 214.5692 C 84.77209 218.43943 82.45999 221.70105 80.10723 224.44" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="38" y1="208.5" x2="38" y2="216.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="160.97266" y1="134.5" x2="160.97266" y2="142.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="160.97266" y1="171.5" x2="160.97266" y2="179.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="160.97266" y1="208.5" x2="160.97266" y2="216.1" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 191.02245 134.5 C 204.52862 141.17393 217.48633 150.19272 217.48633 160.23132 C 217.48633 168.6864 208.29419 176.26144 197.32434 182.29105" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 195.85316 134.50001 C 214.84078 142.7605 234.5 155.23942 234.5 171.5 C 234.5 189.44295 210.56231 207.17633 190.00368 219.09776" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 122.97265 158.83137 C 119.283 160.33365 115.72009 162.50762 112.5 165.56921 C 93.95127 183.20495 116.60622 202.68404 95.5 222 C 91.32614 225.81983 86.55442 228.58839 81.58454 230.57208" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="141.4466" y1="134.5" x2="62.58134" y2="181.95794" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 124.9436 60.5 C 118.85351 66.18221 112.66408 74.35976 107 86.06921 C 84.52826 132.52539 100.44062 170.89066 80.89258 212.72937 C 80.21104 214.18806 79.52489 215.5706 78.83527 216.8805" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+    </g>
+  </g>
+</svg>
diff --git a/2016/refactor/template.html b/2016/refactor/template.html
new file mode 100644
index 0000000..f7d3708
--- /dev/null
+++ b/2016/refactor/template.html
@@ -0,0 +1,5 @@
+<ol>
+<li>Add new API, <i>interchangeable</i> with old API.
+<li>Convert uses of old API to new API.
+<li>Remove old API.
+</ol>
diff --git a/2016/refactor/version1.graffle b/2016/refactor/version1.graffle
new file mode 100644
index 0000000..d76d813
--- /dev/null
+++ b/2016/refactor/version1.graffle
Binary files differ
diff --git a/2016/refactor/version1.html b/2016/refactor/version1.html
new file mode 100644
index 0000000..bd290ec
--- /dev/null
+++ b/2016/refactor/version1.html
@@ -0,0 +1 @@
+<div class="image"><center><img src="refactor/version1.svg" alt="Standard Library Incompatibility"></img></center></div>
diff --git a/2016/refactor/version1.svg b/2016/refactor/version1.svg
new file mode 100644
index 0000000..2e5d5d1
--- /dev/null
+++ b/2016/refactor/version1.svg
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-1 -1 296 187" width="296pt" height="187pt" xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <metadata> Produced by OmniGraffle 7.2.1 
+    <dc:date>2016-12-01 03:51:49 +0000</dc:date>
+  </metadata>
+  <defs>
+    <font-face font-family="Arial" font-size="12" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-105.95703" underline-thickness="73.24219" slope="0" x-height="518.5547" cap-height="716.3086" ascent="905.2734" descent="-211.91406" font-weight="500">
+      <font-face-src>
+        <font-face-name name="ArialMT"/>
+      </font-face-src>
+    </font-face>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black">
+      <g>
+        <path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker_2" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#0432ff">
+      <g>
+        <path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker_3" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#ff2600">
+      <g>
+        <path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker_4" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#ff2600">
+      <g>
+        <path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+    <font-face font-family="Helvetica" font-size="8" units-per-em="1000" underline-position="-75.68359" underline-thickness="49.316406" slope="0" x-height="522.9492" cap-height="717.28516" ascent="770.0195" descent="-229.98047" font-weight="500">
+      <font-face-src>
+        <font-face-name name="Helvetica"/>
+      </font-face-src>
+    </font-face>
+  </defs>
+  <g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1">
+    <title>Canvas 1</title>
+    <g>
+      <title>Layer 1</title>
+      <rect x="78" y="0" width="76" height="23.5" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(83 4.553711)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="19.995117" y="11" textLength="26.009766">Main</tspan>
+      </text>
+      <rect x="0" y="48" width="76" height="23.5" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(5 52.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="22.661133" y="11" textLength="20.677734">Foo</tspan>
+      </text>
+      <rect x="156" y="46" width="76" height="23.5" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(161 50.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="23.663086" y="11" textLength="18.673828">Bar</tspan>
+      </text>
+      <line x1="135.92391" y1="23.5" x2="165.54856" y2="40.97095" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="96.90625" y1="23.5" x2="65.52517" y2="42.811435" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <rect x="48" y="117" width="136" height="68" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(53 166.10742)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="21.64746" y="11" textLength="82.70508">standard library</tspan>
+      </text>
+      <rect x="58.5" y="133.5" width="47.5" height="23.5" stroke="#a5a5a5" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(63.5 138.05371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="5.4052734" y="11" textLength="26.689453">5.1.3</tspan>
+      </text>
+      <rect x="126" y="133.5" width="47.5" height="23.5" stroke="#a5a5a5" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(131 138.05371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="5.4052734" y="11" textLength="26.689453">6.0.0</tspan>
+      </text>
+      <line x1="44.08114" y1="71.5" x2="71.618475" y2="124.70773" marker-end="url(#FilledArrow_Marker_2)" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="188.05786" y1="69.5" x2="160.1599" y2="124.66546" marker-end="url(#FilledArrow_Marker_2)" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="53.357456" y1="71.5" x2="126.5299" y2="127.48429" marker-end="url(#FilledArrow_Marker_3)" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" stroke-dasharray="1,3"/>
+      <line x1="178.99357" y1="69.5" x2="105.05126" y2="127.39667" marker-end="url(#FilledArrow_Marker_4)" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" stroke-dasharray="1,3"/>
+      <line x1="199.5" y1="130" x2="275.95" y2="130" marker-end="url(#FilledArrow_Marker_4)" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-width=".75" stroke-dasharray="1,3"/>
+      <text transform="translate(204.5 120)" fill="#ff2600">
+        <tspan font-family="Helvetica" font-size="8" font-weight="500" fill="#ff2600" x="14.542969" y="8" textLength="44.91406">incompatible</tspan>
+      </text>
+      <line x1="199.5" y1="150" x2="275.95" y2="150" marker-end="url(#FilledArrow_Marker_2)" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width=".75"/>
+      <text transform="translate(204.5 140)" fill="#0432ff">
+        <tspan font-family="Helvetica" font-size="8" font-weight="500" fill="#0432ff" x="17.65625" y="8" textLength="38.6875">compatible</tspan>
+      </text>
+    </g>
+  </g>
+</svg>
diff --git a/2016/refactor/version2.graffle b/2016/refactor/version2.graffle
new file mode 100644
index 0000000..122ec2b
--- /dev/null
+++ b/2016/refactor/version2.graffle
Binary files differ
diff --git a/2016/refactor/version2.html b/2016/refactor/version2.html
new file mode 100644
index 0000000..ea6442e
--- /dev/null
+++ b/2016/refactor/version2.html
@@ -0,0 +1 @@
+<div class="image"><center><img src="refactor/version2.svg" alt="Standard Library Compatibility"></img></center></div>
diff --git a/2016/refactor/version2.svg b/2016/refactor/version2.svg
new file mode 100644
index 0000000..698fd14
--- /dev/null
+++ b/2016/refactor/version2.svg
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xl="http://www.w3.org/1999/xlink" version="1.1" viewBox="-1 -1 296 219" width="296pt" height="219pt" xmlns:dc="http://purl.org/dc/elements/1.1/">
+  <metadata> Produced by OmniGraffle 7.2.1 
+    <dc:date>2016-12-01 03:54:17 +0000</dc:date>
+  </metadata>
+  <defs>
+    <font-face font-family="Arial" font-size="12" panose-1="2 11 6 4 2 2 2 2 2 4" units-per-em="1000" underline-position="-105.95703" underline-thickness="73.24219" slope="0" x-height="518.5547" cap-height="716.3086" ascent="905.2734" descent="-211.91406" font-weight="500">
+      <font-face-src>
+        <font-face-name name="ArialMT"/>
+      </font-face-src>
+    </font-face>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="black">
+      <g>
+        <path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker_2" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#0432ff">
+      <g>
+        <path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker_3" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#ff2600">
+      <g>
+        <path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker_4" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#ff2600">
+      <g>
+        <path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+    <font-face font-family="Helvetica" font-size="8" units-per-em="1000" underline-position="-75.68359" underline-thickness="49.316406" slope="0" x-height="522.9492" cap-height="717.28516" ascent="770.0195" descent="-229.98047" font-weight="500">
+      <font-face-src>
+        <font-face-name name="Helvetica"/>
+      </font-face-src>
+    </font-face>
+    <marker orient="auto" overflow="visible" markerUnits="strokeWidth" id="FilledArrow_Marker_5" viewBox="-1 -4 10 8" markerWidth="10" markerHeight="8" color="#0432ff">
+      <g>
+        <path d="M 8 0 L 0 -3 L 0 3 Z" fill="currentColor" stroke="currentColor" stroke-width="1"/>
+      </g>
+    </marker>
+  </defs>
+  <g stroke="none" stroke-opacity="1" stroke-dasharray="none" fill="none" fill-opacity="1">
+    <title>Canvas 1</title>
+    <g>
+      <title>Layer 1</title>
+      <rect x="78" y="0" width="76" height="23.5" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(83 4.553711)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="19.995117" y="11" textLength="26.009766">Main</tspan>
+      </text>
+      <rect x="0" y="48" width="76" height="23.5" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(5 52.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="22.661133" y="11" textLength="20.677734">Foo</tspan>
+      </text>
+      <rect x="156" y="46" width="76" height="23.5" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(161 50.55371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" x="23.663086" y="11" textLength="18.673828">Bar</tspan>
+      </text>
+      <line x1="135.92391" y1="23.5" x2="165.54856" y2="40.97095" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="96.90625" y1="23.5" x2="65.52517" y2="42.811435" marker-end="url(#FilledArrow_Marker)" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <rect x="48" y="117" width="136" height="100.5" stroke="black" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(53 198.60742)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="21.64746" y="11" textLength="82.70508">standard library</tspan>
+      </text>
+      <rect x="58.5" y="133.5" width="47.5" height="23.5" stroke="#a5a5a5" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(63.5 138.05371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="5.4052734" y="11" textLength="26.689453">5.1.3</tspan>
+      </text>
+      <rect x="126" y="133.5" width="47.5" height="23.5" stroke="#a5a5a5" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(131 138.05371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="5.4052734" y="11" textLength="26.689453">6.0.0</tspan>
+      </text>
+      <line x1="44.08114" y1="71.5" x2="71.618475" y2="124.70773" marker-end="url(#FilledArrow_Marker_2)" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="188.05786" y1="69.5" x2="160.1599" y2="124.66546" marker-end="url(#FilledArrow_Marker_2)" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <line x1="53.357456" y1="71.5" x2="126.5299" y2="127.48429" marker-end="url(#FilledArrow_Marker_3)" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" stroke-dasharray="1,3"/>
+      <line x1="178.99357" y1="69.5" x2="105.05126" y2="127.39667" marker-end="url(#FilledArrow_Marker_4)" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-width="1" stroke-dasharray="1,3"/>
+      <line x1="199.5" y1="130" x2="275.95" y2="130" marker-end="url(#FilledArrow_Marker_4)" stroke="#ff2600" stroke-linecap="round" stroke-linejoin="round" stroke-width=".75" stroke-dasharray="1,3"/>
+      <text transform="translate(204.5 120)" fill="#ff2600">
+        <tspan font-family="Helvetica" font-size="8" font-weight="500" fill="#ff2600" x="14.542969" y="8" textLength="44.91406">incompatible</tspan>
+      </text>
+      <line x1="199.5" y1="150" x2="275.95" y2="150" marker-end="url(#FilledArrow_Marker_2)" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width=".75"/>
+      <text transform="translate(204.5 140)" fill="#0432ff">
+        <tspan font-family="Helvetica" font-size="8" font-weight="500" fill="#0432ff" x="17.65625" y="8" textLength="38.6875">compatible</tspan>
+      </text>
+      <rect x="58.5" y="164.5" width="47.5" height="23.5" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <text transform="translate(63.5 169.05371)" fill="black">
+        <tspan font-family="Arial" font-size="12" font-weight="500" fill="black" x="5.4052734" y="11" textLength="26.689453">5.2.0</tspan>
+      </text>
+      <path d="M 38.299127 71.49998 C 39.23227 79.43687 41.73237 91.49878 48 108 C 54.4882 125.08193 63.43472 142.76385 70.55697 155.84909" marker-end="url(#FilledArrow_Marker_5)" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+      <path d="M 186.36683 69.5 C 174.03483 88.13288 148.80312 124.81951 126 149 C 121.50411 153.76745 117.40286 157.7304 113.67481 161.0212" marker-end="url(#FilledArrow_Marker_5)" stroke="#0432ff" stroke-linecap="round" stroke-linejoin="round" stroke-width="1"/>
+    </g>
+  </g>
+</svg>